Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 9 Dec 2018 23:12:33 +0000 (15:12 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 9 Dec 2018 23:12:33 +0000 (15:12 -0800)
Pull networking fixes from David Miller:
 "A decent batch of fixes here. I'd say about half are for problems that
  have existed for a while, and half are for new regressions added in
  the 4.20 merge window.

   1) Fix 10G SFP phy module detection in mvpp2, from Baruch Siach.

   2) Revert bogus emac driver change, from Benjamin Herrenschmidt.

   3) Handle BPF exported data structure with pointers when building
      32-bit userland, from Daniel Borkmann.

   4) Memory leak fix in act_police, from Davide Caratti.

   5) Check RX checksum offload in RX descriptors properly in aquantia
      driver, from Dmitry Bogdanov.

   6) SKB unlink fix in various spots, from Edward Cree.

   7) ndo_dflt_fdb_dump() only works with ethernet, enforce this, from
      Eric Dumazet.

   8) Fix FID leak in mlxsw driver, from Ido Schimmel.

   9) IOTLB locking fix in vhost, from Jean-Philippe Brucker.

  10) Fix SKB truesize accounting in ipv4/ipv6/netfilter frag memory
      limits otherwise namespace exit can hang. From Jiri Wiesner.

  11) Address block parsing length fixes in x25 from Martin Schiller.

  12) IRQ and ring accounting fixes in bnxt_en, from Michael Chan.

  13) For tun interfaces, only iface delete works with rtnl ops, enforce
      this by disallowing add. From Nicolas Dichtel.

  14) Use after free in liquidio, from Pan Bian.

  15) Fix SKB use after passing to netif_receive_skb(), from Prashant
      Bhole.

  16) Static key accounting and other fixes in XPS from Sabrina Dubroca.

  17) Partially initialized flow key passed to ip6_route_output(), from
      Shmulik Ladkani.

  18) Fix RTNL deadlock during reset in ibmvnic driver, from Thomas
      Falcon.

  19) Several small TCP fixes (off-by-one on window probe abort, NULL
      deref in tail loss probe, SNMP mis-estimations) from Yuchung
      Cheng"

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (93 commits)
  net/sched: cls_flower: Reject duplicated rules also under skip_sw
  bnxt_en: Fix _bnxt_get_max_rings() for 57500 chips.
  bnxt_en: Fix NQ/CP rings accounting on the new 57500 chips.
  bnxt_en: Keep track of reserved IRQs.
  bnxt_en: Fix CNP CoS queue regression.
  net/mlx4_core: Correctly set PFC param if global pause is turned off.
  Revert "net/ibm/emac: wrong bit is used for STA control"
  neighbour: Avoid writing before skb->head in neigh_hh_output()
  ipv6: Check available headroom in ip6_xmit() even without options
  tcp: lack of available data can also cause TSO defer
  ipv6: sr: properly initialize flowi6 prior passing to ip6_route_output
  mlxsw: spectrum_switchdev: Fix VLAN device deletion via ioctl
  mlxsw: spectrum_router: Relax GRE decap matching check
  mlxsw: spectrum_switchdev: Avoid leaking FID's reference count
  mlxsw: spectrum_nve: Remove easily triggerable warnings
  ipv4: ipv6: netfilter: Adjust the frag mem limit when truesize changes
  sctp: frag_point sanity check
  tcp: fix NULL ref in tail loss probe
  tcp: Do not underestimate rwnd_limited
  net: use skb_list_del_init() to remove from RX sublists
  ...

495 files changed:
Documentation/admin-guide/kernel-parameters.txt
Documentation/arm64/silicon-errata.txt
Documentation/devicetree/bindings/clock/clock-bindings.txt
Documentation/devicetree/bindings/input/input-reset.txt
Documentation/devicetree/bindings/media/rockchip-vpu.txt [deleted file]
Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst
Documentation/media/uapi/mediactl/media-request-ioc-queue.rst
Documentation/media/uapi/mediactl/media-request-ioc-reinit.rst
Documentation/media/uapi/mediactl/request-api.rst
Documentation/media/uapi/mediactl/request-func-close.rst
Documentation/media/uapi/mediactl/request-func-ioctl.rst
Documentation/media/uapi/mediactl/request-func-poll.rst
Documentation/userspace-api/spec_ctrl.rst
Documentation/x86/boot.txt
MAINTAINERS
Makefile
arch/arc/Kconfig
arch/arc/Makefile
arch/arc/boot/dts/hsdk.dts
arch/arc/configs/axs101_defconfig
arch/arc/configs/axs103_defconfig
arch/arc/configs/axs103_smp_defconfig
arch/arc/configs/hsdk_defconfig
arch/arc/configs/nps_defconfig
arch/arc/configs/nsim_700_defconfig
arch/arc/configs/nsimosci_defconfig
arch/arc/configs/nsimosci_hs_defconfig
arch/arc/configs/nsimosci_hs_smp_defconfig
arch/arc/configs/tb10x_defconfig
arch/arc/configs/vdk_hs38_defconfig
arch/arc/configs/vdk_hs38_smp_defconfig
arch/arc/include/asm/cache.h
arch/arc/include/asm/io.h
arch/arc/kernel/setup.c
arch/arc/mm/cache.c
arch/arc/mm/fault.c
arch/arm/boot/dts/am3517-evm.dts
arch/arm/boot/dts/am3517-som.dtsi
arch/arm/boot/dts/imx51-zii-rdu1.dts
arch/arm/boot/dts/logicpd-som-lv.dtsi
arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts
arch/arm/boot/dts/rk3288-veyron.dtsi
arch/arm/boot/dts/sama5d2.dtsi
arch/arm/kernel/ftrace.c
arch/arm/mach-davinci/da830.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm365.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/dm646x.c
arch/arm/mach-omap1/board-ams-delta.c
arch/arm/mach-omap2/prm44xx.c
arch/arm/mm/cache-v7.S
arch/arm/mm/cache-v7m.S
arch/arm/mm/dma-mapping.c
arch/arm/mm/proc-macros.S
arch/arm/probes/kprobes/opt-arm.c
arch/arm64/Kconfig
arch/arm64/boot/dts/qcom/msm8998-mtp.dtsi
arch/arm64/boot/dts/qcom/sdm845-mtp.dts
arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi
arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi
arch/arm64/include/asm/ftrace.h
arch/arm64/include/asm/tlbflush.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/ftrace.c
arch/arm64/kernel/hibernate.c
arch/csky/include/asm/mmu_context.h
arch/microblaze/kernel/ftrace.c
arch/mips/include/asm/syscall.h
arch/mips/kernel/ftrace.c
arch/mips/ralink/mt7620.c
arch/nds32/kernel/ftrace.c
arch/parisc/Makefile
arch/parisc/kernel/ftrace.c
arch/powerpc/kernel/trace/ftrace.c
arch/riscv/kernel/ftrace.c
arch/s390/kernel/ftrace.c
arch/s390/kernel/perf_cpum_cf.c
arch/s390/mm/pgalloc.c
arch/sh/kernel/ftrace.c
arch/sparc/kernel/ftrace.c
arch/sparc/kernel/iommu.c
arch/sparc/kernel/signal32.c
arch/sparc/kernel/signal_32.c
arch/sparc/kernel/signal_64.c
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/boot/compressed/eboot.c
arch/x86/boot/header.S
arch/x86/entry/entry_64.S
arch/x86/entry/vdso/Makefile
arch/x86/events/core.c
arch/x86/events/intel/core.c
arch/x86/events/perf_event.h
arch/x86/include/asm/bootparam_utils.h
arch/x86/include/asm/fpu/internal.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/nospec-branch.h
arch/x86/include/asm/spec-ctrl.h
arch/x86/include/asm/switch_to.h
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/tlbflush.h
arch/x86/include/asm/x86_init.h
arch/x86/include/uapi/asm/bootparam.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/fpu/signal.c
arch/x86/kernel/ftrace.c
arch/x86/kernel/head32.c
arch/x86/kernel/head64.c
arch/x86/kernel/kprobes/opt.c
arch/x86/kernel/process.c
arch/x86/kernel/process.h [new file with mode: 0644]
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/setup.c
arch/x86/mm/tlb.c
arch/x86/platform/efi/early_printk.c
arch/x86/xen/enlighten.c
arch/x86/xen/multicalls.c
arch/x86/xen/setup.c
arch/x86/xen/spinlock.c
block/bfq-iosched.c
block/bfq-iosched.h
block/bfq-wf2q.c
block/blk-merge.c
block/blk-mq.c
crypto/Kconfig
crypto/cbc.c
crypto/cfb.c
crypto/pcbc.c
drivers/acpi/acpica/exserial.c
drivers/acpi/arm64/iort.c
drivers/acpi/nfit/core.c
drivers/android/binder.c
drivers/android/binder_alloc.c
drivers/android/binder_alloc.h
drivers/ata/libata-core.c
drivers/base/devres.c
drivers/clk/mmp/clk.c
drivers/clk/mvebu/cp110-system-controller.c
drivers/clk/qcom/common.c
drivers/clk/zynqmp/clkc.c
drivers/dma/at_hdmac.c
drivers/dma/dw/core.c
drivers/dma/imx-sdma.c
drivers/dma/ti/cppi41.c
drivers/firmware/efi/efi.c
drivers/fsi/Kconfig
drivers/fsi/fsi-scom.c
drivers/gnss/sirf.c
drivers/gpio/gpio-davinci.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
drivers/gpu/drm/ast/ast_fb.c
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/bridge/ti-sn65dsi86.c
drivers/gpu/drm/drm_auth.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_internal.h
drivers/gpu/drm/drm_lease.c
drivers/gpu/drm/drm_sysfs.c
drivers/gpu/drm/i915/gvt/aperture_gm.c
drivers/gpu/drm/i915/gvt/gtt.c
drivers/gpu/drm/i915/gvt/mmio_context.c
drivers/gpu/drm/meson/meson_crtc.c
drivers/gpu/drm/meson/meson_dw_hdmi.c
drivers/gpu/drm/meson/meson_venc.c
drivers/gpu/drm/meson/meson_viu.c
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c
drivers/gpu/drm/msm/hdmi/hdmi.c
drivers/gpu/drm/msm/hdmi/hdmi.h
drivers/gpu/drm/msm/hdmi/hdmi_connector.c
drivers/gpu/drm/msm/msm_atomic.c
drivers/gpu/drm/msm/msm_debugfs.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_gem_submit.c
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/msm/msm_iommu.c
drivers/gpu/drm/msm/msm_rd.c
drivers/gpu/drm/omapdrm/displays/panel-dpi.c
drivers/gpu/drm/omapdrm/dss/dsi.c
drivers/gpu/drm/omapdrm/dss/omapdss.h
drivers/gpu/drm/omapdrm/omap_encoder.c
drivers/gpu/drm/rcar-du/rcar_du_group.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/hid/hid-hyperv.c
drivers/hid/hid-sensor-custom.c
drivers/hid/hid-sensor-hub.c
drivers/hv/channel.c
drivers/hv/channel_mgmt.c
drivers/hv/connection.c
drivers/hv/hyperv_vmbus.h
drivers/i2c/busses/i2c-axxia.c
drivers/i2c/busses/i2c-nvidia-gpu.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-scmi.c
drivers/i2c/busses/i2c-uniphier-f.c
drivers/i2c/busses/i2c-uniphier.c
drivers/ide/ide-proc.c
drivers/ide/pmac.c
drivers/iio/accel/hid-sensor-accel-3d.c
drivers/iio/gyro/hid-sensor-gyro-3d.c
drivers/iio/humidity/hid-sensor-humidity.c
drivers/iio/light/hid-sensor-als.c
drivers/iio/light/hid-sensor-prox.c
drivers/iio/magnetometer/hid-sensor-magn-3d.c
drivers/iio/magnetometer/st_magn_buffer.c
drivers/iio/orientation/hid-sensor-incl-3d.c
drivers/iio/pressure/hid-sensor-press.c
drivers/iio/temperature/hid-sensor-temperature.c
drivers/infiniband/core/roce_gid_mgmt.c
drivers/infiniband/core/umem_odp.c
drivers/infiniband/hw/bnxt_re/main.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/odp.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/sw/rdmavt/ah.c
drivers/infiniband/sw/rdmavt/ah.h
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/input/joystick/xpad.c
drivers/input/keyboard/atkbd.c
drivers/input/keyboard/cros_ec_keyb.c
drivers/input/keyboard/matrix_keypad.c
drivers/input/keyboard/omap4-keypad.c
drivers/input/mouse/elan_i2c_core.c
drivers/input/mouse/synaptics.c
drivers/input/serio/hyperv-keyboard.c
drivers/input/touchscreen/migor_ts.c
drivers/input/touchscreen/st1232.c
drivers/media/dvb-frontends/dvb-pll.c
drivers/media/media-request.c
drivers/media/platform/vicodec/vicodec-core.c
drivers/media/usb/gspca/gspca.c
drivers/mfd/cros_ec_dev.c
drivers/misc/mic/scif/scif_rma.c
drivers/mtd/nand/bbt.c
drivers/mtd/spi-nor/spi-nor.c
drivers/nvdimm/nd-core.h
drivers/nvdimm/pfn_devs.c
drivers/nvdimm/region_devs.c
drivers/nvme/host/core.c
drivers/nvme/host/fc.c
drivers/nvme/host/nvme.h
drivers/nvme/host/rdma.c
drivers/nvme/target/rdma.c
drivers/opp/of.c
drivers/opp/ti-opp-supply.c
drivers/pci/controller/dwc/pci-imx6.c
drivers/pci/controller/dwc/pci-layerscape.c
drivers/pci/controller/dwc/pcie-designware-ep.c
drivers/pci/pci.c
drivers/pci/pcie/aspm.c
drivers/phy/qualcomm/phy-qcom-qusb2.c
drivers/phy/socionext/Kconfig
drivers/rtc/rtc-hid-sensor-time.c
drivers/s390/cio/vfio_ccw_cp.c
drivers/s390/cio/vfio_ccw_drv.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/ap_queue.c
drivers/s390/crypto/zcrypt_cex2a.c
drivers/s390/crypto/zcrypt_cex2c.c
drivers/s390/crypto/zcrypt_cex4.c
drivers/s390/virtio/virtio_ccw.c
drivers/sbus/char/display7seg.c
drivers/sbus/char/envctrl.c
drivers/scsi/libiscsi.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/storvsc_drv.c
drivers/scsi/vmw_pvscsi.c
drivers/staging/comedi/comedi.h
drivers/staging/comedi/drivers/ni_mio_common.c
drivers/staging/media/sunxi/cedrus/TODO
drivers/staging/media/sunxi/cedrus/cedrus.c
drivers/staging/most/core.c
drivers/staging/mt7621-dma/mtk-hsdma.c
drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c
drivers/staging/rtl8712/mlme_linux.c
drivers/staging/rtl8712/rtl871x_mlme.c
drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
drivers/thermal/armada_thermal.c
drivers/thermal/broadcom/bcm2835_thermal.c
drivers/thermal/broadcom/brcmstb_thermal.c
drivers/thunderbolt/switch.c
drivers/tty/serial/8250/8250_mtk.c
drivers/tty/serial/kgdboc.c
drivers/tty/serial/suncore.c
drivers/tty/tty_io.c
drivers/tty/tty_port.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/core/usb.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/u_ether.c
drivers/usb/gadget/udc/omap_udc.c
drivers/usb/host/hwa-hc.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/appledisplay.c
drivers/usb/serial/console.c
drivers/usb/storage/unusual_realtek.h
drivers/vhost/vsock.c
drivers/xen/balloon.c
drivers/xen/pvcalls-front.c
drivers/xen/xlate_mmu.c
fs/afs/dir.c
fs/afs/fs_probe.c
fs/afs/inode.c
fs/afs/internal.h
fs/afs/misc.c
fs/afs/rotate.c
fs/afs/vl_probe.c
fs/afs/vl_rotate.c
fs/aio.c
fs/btrfs/tree-checker.c
fs/cachefiles/namei.c
fs/cachefiles/rdwr.c
fs/cachefiles/xattr.c
fs/cifs/Kconfig
fs/cifs/dir.c
fs/cifs/file.c
fs/dax.c
fs/direct-io.c
fs/exec.c
fs/exportfs/expfs.c
fs/ext2/super.c
fs/ext2/xattr.c
fs/fscache/object.c
fs/hfs/btree.c
fs/hfsplus/btree.c
fs/iomap.c
fs/nfs/direct.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/ocfs2/export.c
fs/ocfs2/move_extents.c
fs/pstore/ram.c
fs/read_write.c
fs/splice.c
fs/sysv/inode.c
fs/udf/super.c
fs/udf/unicode.c
fs/userfaultfd.c
fs/xfs/libxfs/xfs_btree.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_qm_bhv.c
include/linux/dax.h
include/linux/fscache-cache.h
include/linux/ftrace.h
include/linux/gfp.h
include/linux/hid-sensor-hub.h
include/linux/hyperv.h
include/linux/mempolicy.h
include/linux/mlx5/mlx5_ifc.h
include/linux/platform_data/gpio-davinci.h
include/linux/psi.h
include/linux/pstore.h
include/linux/ptrace.h
include/linux/sched.h
include/linux/sched/smt.h [new file with mode: 0644]
include/linux/sunrpc/xdr.h
include/linux/tracehook.h
include/linux/tracepoint.h
include/linux/tty.h
include/linux/usb.h
include/media/media-request.h
include/sound/pcm_params.h
include/sound/soc.h
include/trace/events/sched.h
include/uapi/asm-generic/unistd.h
include/uapi/linux/prctl.h
include/xen/balloon.h
init/Kconfig
init/initramfs.c
kernel/cpu.c
kernel/events/uprobes.c
kernel/kcov.c
kernel/ptrace.c
kernel/sched/core.c
kernel/sched/psi.c
kernel/sched/sched.h
kernel/sched/stats.h
kernel/stackleak.c
kernel/trace/ftrace.c
kernel/trace/trace.h
kernel/trace/trace_functions_graph.c
kernel/trace/trace_irqsoff.c
kernel/trace/trace_sched_wakeup.c
lib/debugobjects.c
lib/iov_iter.c
lib/test_hexdump.c
lib/test_kmod.c
mm/gup.c
mm/huge_memory.c
mm/hugetlb.c
mm/khugepaged.c
mm/memory-failure.c
mm/mempolicy.c
mm/page_alloc.c
mm/rmap.c
mm/shmem.c
mm/truncate.c
mm/userfaultfd.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/clnt.c
net/sunrpc/xprt.c
net/sunrpc/xprtsock.c
scripts/Makefile.build
scripts/gcc-plugins/stackleak_plugin.c
scripts/unifdef.c
security/selinux/nlmsgtab.c
sound/core/control.c
sound/core/pcm_native.c
sound/isa/wss/wss_lib.c
sound/pci/ac97/ac97_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/hdac_hdmi.c
sound/soc/codecs/pcm186x.h
sound/soc/codecs/pcm3060.c
sound/soc/codecs/wm_adsp.c
sound/soc/intel/Kconfig
sound/soc/intel/boards/Kconfig
sound/soc/intel/boards/cht_bsw_max98090_ti.c
sound/soc/intel/skylake/skl.c
sound/soc/omap/omap-abe-twl6040.c
sound/soc/omap/omap-dmic.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcpdm.c
sound/soc/qcom/common.c
sound/soc/qcom/qdsp6/q6afe-dai.c
sound/soc/qcom/qdsp6/q6afe.c
sound/soc/qcom/qdsp6/q6asm-dai.c
sound/soc/qcom/qdsp6/q6routing.c
sound/soc/rockchip/rockchip_pcm.c
sound/soc/sh/rcar/ssi.c
sound/soc/soc-acpi.c
sound/soc/soc-core.c
sound/soc/stm/stm32_sai_sub.c
sound/soc/sunxi/Kconfig
sound/soc/sunxi/sun8i-codec.c
sound/sparc/cs4231.c
sound/usb/card.c
sound/usb/quirks-table.h
sound/usb/quirks.c
tools/arch/x86/include/asm/cpufeatures.h
tools/build/Makefile.feature
tools/build/feature/Makefile
tools/build/feature/test-all.c
tools/build/feature/test-get_current_dir_name.c [new file with mode: 0644]
tools/include/uapi/asm-generic/ioctls.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/prctl.h
tools/objtool/elf.c
tools/perf/Makefile.config
tools/perf/tests/attr/base-record
tools/perf/trace/beauty/ioctl.c
tools/perf/util/Build
tools/perf/util/evsel.c
tools/perf/util/get_current_dir_name.c [new file with mode: 0644]
tools/perf/util/namespaces.c
tools/perf/util/namespaces.h
tools/perf/util/util.h
tools/testing/nvdimm/test/nfit.c
tools/testing/selftests/proc/proc-self-map-files-002.c

index 19f4423..aefd358 100644 (file)
                        causing system reset or hang due to sending
                        INIT from AP to BSP.
 
-       disable_counter_freezing [HW]
+       perf_v4_pmi=    [X86,INTEL]
+                       Format: <bool>
                        Disable Intel PMU counter freezing feature.
                        The feature only exists starting from
                        Arch Perfmon v4 (Skylake and newer).
                        before loading.
                        See Documentation/blockdev/ramdisk.txt.
 
+       psi=            [KNL] Enable or disable pressure stall information
+                       tracking.
+                       Format: <bool>
+
        psmouse.proto=  [HW,MOUSE] Highest PS2 mouse protocol extension to
                        probe for; one of (bare|imps|exps|lifebook|any).
        psmouse.rate=   [HW,MOUSE] Set desired mouse report rate, in reports
 
        spectre_v2=     [X86] Control mitigation of Spectre variant 2
                        (indirect branch speculation) vulnerability.
+                       The default operation protects the kernel from
+                       user space attacks.
 
-                       on   - unconditionally enable
-                       off  - unconditionally disable
+                       on   - unconditionally enable, implies
+                              spectre_v2_user=on
+                       off  - unconditionally disable, implies
+                              spectre_v2_user=off
                        auto - kernel detects whether your CPU model is
                               vulnerable
 
                        CONFIG_RETPOLINE configuration option, and the
                        compiler with which the kernel was built.
 
+                       Selecting 'on' will also enable the mitigation
+                       against user space to user space task attacks.
+
+                       Selecting 'off' will disable both the kernel and
+                       the user space protections.
+
                        Specific mitigations can also be selected manually:
 
                        retpoline         - replace indirect branches
                        Not specifying this option is equivalent to
                        spectre_v2=auto.
 
+       spectre_v2_user=
+                       [X86] Control mitigation of Spectre variant 2
+                       (indirect branch speculation) vulnerability between
+                       user space tasks
+
+                       on      - Unconditionally enable mitigations. Is
+                                 enforced by spectre_v2=on
+
+                       off     - Unconditionally disable mitigations. Is
+                                 enforced by spectre_v2=off
+
+                       prctl   - Indirect branch speculation is enabled,
+                                 but mitigation can be enabled via prctl
+                                 per thread.  The mitigation control state
+                                 is inherited on fork.
+
+                       prctl,ibpb
+                               - Like "prctl" above, but only STIBP is
+                                 controlled per thread. IBPB is issued
+                                 always when switching between different user
+                                 space processes.
+
+                       seccomp
+                               - Same as "prctl" above, but all seccomp
+                                 threads will enable the mitigation unless
+                                 they explicitly opt out.
+
+                       seccomp,ibpb
+                               - Like "seccomp" above, but only STIBP is
+                                 controlled per thread. IBPB is issued
+                                 always when switching between different
+                                 user space processes.
+
+                       auto    - Kernel selects the mitigation depending on
+                                 the available CPU features and vulnerability.
+
+                       Default mitigation:
+                       If CONFIG_SECCOMP=y then "seccomp", otherwise "prctl"
+
+                       Not specifying this option is equivalent to
+                       spectre_v2_user=auto.
+
        spec_store_bypass_disable=
                        [HW] Control Speculative Store Bypass (SSB) Disable mitigation
                        (Speculative Store Bypass vulnerability)
index 76ccded..8f95776 100644 (file)
@@ -57,6 +57,7 @@ stable kernels.
 | ARM            | Cortex-A73      | #858921         | ARM64_ERRATUM_858921        |
 | ARM            | Cortex-A55      | #1024718        | ARM64_ERRATUM_1024718       |
 | ARM            | Cortex-A76      | #1188873        | ARM64_ERRATUM_1188873       |
+| ARM            | Cortex-A76      | #1286807        | ARM64_ERRATUM_1286807       |
 | ARM            | MMU-500         | #841119,#826419 | N/A                         |
 |                |                 |                 |                             |
 | Cavium         | ThunderX ITS    | #22375, #24313  | CAVIUM_ERRATUM_22375        |
index 2ec489e..b646bbc 100644 (file)
@@ -168,3 +168,19 @@ a shared clock is forbidden.
 
 Configuration of common clocks, which affect multiple consumer devices can
 be similarly specified in the clock provider node.
+
+==Protected clocks==
+
+Some platforms or firmwares may not fully expose all the clocks to the OS, such
+as in situations where those clks are used by drivers running in ARM secure
+execution levels. Such a configuration can be specified in device tree with the
+protected-clocks property in the form of a clock specifier list. This property should
+only be specified in the node that is providing the clocks being protected:
+
+   clock-controller@a000f000 {
+        compatible = "vendor,clk95;
+        reg = <0xa000f000 0x1000>
+        #clocks-cells = <1>;
+        ...
+        protected-clocks = <UART3_CLK>, <SPI5_CLK>;
+   };
index 2bb2626..1ca6cc5 100644 (file)
@@ -12,7 +12,7 @@ The /chosen node should contain a 'linux,sysrq-reset-seq' child node to define
 a set of keys.
 
 Required property:
-sysrq-reset-seq: array of Linux keycodes, one keycode per cell.
+keyset: array of Linux keycodes, one keycode per cell.
 
 Optional property:
 timeout-ms: duration keys must be pressed together in milliseconds before
diff --git a/Documentation/devicetree/bindings/media/rockchip-vpu.txt b/Documentation/devicetree/bindings/media/rockchip-vpu.txt
deleted file mode 100644 (file)
index 35dc464..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-device-tree bindings for rockchip VPU codec
-
-Rockchip (Video Processing Unit) present in various Rockchip platforms,
-such as RK3288 and RK3399.
-
-Required properties:
-- compatible: value should be one of the following
-               "rockchip,rk3288-vpu";
-               "rockchip,rk3399-vpu";
-- interrupts: encoding and decoding interrupt specifiers
-- interrupt-names: should be "vepu" and "vdpu"
-- clocks: phandle to VPU aclk, hclk clocks
-- clock-names: should be "aclk" and "hclk"
-- power-domains: phandle to power domain node
-- iommus: phandle to a iommu node
-
-Example:
-SoC-specific DT entry:
-       vpu: video-codec@ff9a0000 {
-               compatible = "rockchip,rk3288-vpu";
-               reg = <0x0 0xff9a0000 0x0 0x800>;
-               interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
-                            <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
-               interrupt-names = "vepu", "vdpu";
-               clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>;
-               clock-names = "aclk", "hclk";
-               power-domains = <&power RK3288_PD_VIDEO>;
-               iommus = <&vpu_mmu>;
-       };
index adf20b2..fbc198d 100644 (file)
@@ -40,24 +40,36 @@ Required properties:
                "ref" for 19.2 MHz ref clk,
                "com_aux" for phy common block aux clock,
                "ref_aux" for phy reference aux clock,
+
+               For "qcom,ipq8074-qmp-pcie-phy": no clocks are listed.
                For "qcom,msm8996-qmp-pcie-phy" must contain:
                        "aux", "cfg_ahb", "ref".
                For "qcom,msm8996-qmp-usb3-phy" must contain:
                        "aux", "cfg_ahb", "ref".
-               For "qcom,qmp-v3-usb3-phy" must contain:
+               For "qcom,sdm845-qmp-usb3-phy" must contain:
+                       "aux", "cfg_ahb", "ref", "com_aux".
+               For "qcom,sdm845-qmp-usb3-uni-phy" must contain:
                        "aux", "cfg_ahb", "ref", "com_aux".
+               For "qcom,sdm845-qmp-ufs-phy" must contain:
+                       "ref", "ref_aux".
 
  - resets: a list of phandles and reset controller specifier pairs,
           one for each entry in reset-names.
  - reset-names: "phy" for reset of phy block,
                "common" for phy common block reset,
-               "cfg" for phy's ahb cfg block reset (Optional).
+               "cfg" for phy's ahb cfg block reset.
+
+               For "qcom,ipq8074-qmp-pcie-phy" must contain:
+                       "phy", "common".
                For "qcom,msm8996-qmp-pcie-phy" must contain:
-                "phy", "common", "cfg".
+                       "phy", "common", "cfg".
                For "qcom,msm8996-qmp-usb3-phy" must contain
-                "phy", "common".
-               For "qcom,ipq8074-qmp-pcie-phy" must contain:
-                "phy", "common".
+                       "phy", "common".
+               For "qcom,sdm845-qmp-usb3-phy" must contain:
+                       "phy", "common".
+               For "qcom,sdm845-qmp-usb3-uni-phy" must contain:
+                       "phy", "common".
+               For "qcom,sdm845-qmp-ufs-phy": no resets are listed.
 
  - vdda-phy-supply: Phandle to a regulator supply to PHY core block.
  - vdda-pll-supply: Phandle to 1.8V regulator supply to PHY refclk pll block.
@@ -79,9 +91,10 @@ Required properties for child node:
 
  - #phy-cells: must be 0
 
+Required properties child node of pcie and usb3 qmp phys:
  - clocks: a list of phandles and clock-specifier pairs,
           one for each entry in clock-names.
- - clock-names: Must contain following for pcie and usb qmp phys:
+ - clock-names: Must contain following:
                 "pipe<lane-number>" for pipe clock specific to each lane.
  - clock-output-names: Name of the PHY clock that will be the parent for
                       the above pipe clock.
@@ -91,9 +104,11 @@ Required properties for child node:
                        (or)
                  "pcie20_phy1_pipe_clk"
 
+Required properties for child node of PHYs with lane reset, AKA:
+       "qcom,msm8996-qmp-pcie-phy"
  - resets: a list of phandles and reset controller specifier pairs,
           one for each entry in reset-names.
- - reset-names: Must contain following for pcie qmp phys:
+ - reset-names: Must contain following:
                 "lane<lane-number>" for reset specific to each lane.
 
 Example:
index 0f8b318..de131f0 100644 (file)
@@ -1,4 +1,28 @@
-.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
+.. This file is dual-licensed: you can use it either under the terms
+.. of the GPL or the GFDL 1.1+ license, at your option. Note that this
+.. dual licensing only applies to this file, and not this project as a
+.. whole.
+..
+.. a) This file is free software; you can redistribute it and/or
+..    modify it under the terms of the GNU General Public License as
+..    published by the Free Software Foundation; either version 2 of
+..    the License, or (at your option) any later version.
+..
+..    This file is distributed in the hope that it will be useful,
+..    but WITHOUT ANY WARRANTY; without even the implied warranty of
+..    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+..    GNU General Public License for more details.
+..
+.. Or, alternatively,
+..
+.. b) Permission is granted to copy, distribute and/or modify this
+..    document under the terms of the GNU Free Documentation License,
+..    Version 1.1 or any later version published by the Free Software
+..    Foundation, with no Invariant Sections, no Front-Cover Texts
+..    and no Back-Cover Texts. A copy of the license is included at
+..    Documentation/media/uapi/fdl-appendix.rst.
+..
+.. TODO: replace it to GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
 
 .. _media_ioc_request_alloc:
 
index 6dd2d7f..5d26043 100644 (file)
@@ -1,4 +1,28 @@
-.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
+.. This file is dual-licensed: you can use it either under the terms
+.. of the GPL or the GFDL 1.1+ license, at your option. Note that this
+.. dual licensing only applies to this file, and not this project as a
+.. whole.
+..
+.. a) This file is free software; you can redistribute it and/or
+..    modify it under the terms of the GNU General Public License as
+..    published by the Free Software Foundation; either version 2 of
+..    the License, or (at your option) any later version.
+..
+..    This file is distributed in the hope that it will be useful,
+..    but WITHOUT ANY WARRANTY; without even the implied warranty of
+..    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+..    GNU General Public License for more details.
+..
+.. Or, alternatively,
+..
+.. b) Permission is granted to copy, distribute and/or modify this
+..    document under the terms of the GNU Free Documentation License,
+..    Version 1.1 or any later version published by the Free Software
+..    Foundation, with no Invariant Sections, no Front-Cover Texts
+..    and no Back-Cover Texts. A copy of the license is included at
+..    Documentation/media/uapi/fdl-appendix.rst.
+..
+.. TODO: replace it to GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
 
 .. _media_request_ioc_queue:
 
index febe888..ec61960 100644 (file)
@@ -1,4 +1,28 @@
-.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
+.. This file is dual-licensed: you can use it either under the terms
+.. of the GPL or the GFDL 1.1+ license, at your option. Note that this
+.. dual licensing only applies to this file, and not this project as a
+.. whole.
+..
+.. a) This file is free software; you can redistribute it and/or
+..    modify it under the terms of the GNU General Public License as
+..    published by the Free Software Foundation; either version 2 of
+..    the License, or (at your option) any later version.
+..
+..    This file is distributed in the hope that it will be useful,
+..    but WITHOUT ANY WARRANTY; without even the implied warranty of
+..    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+..    GNU General Public License for more details.
+..
+.. Or, alternatively,
+..
+.. b) Permission is granted to copy, distribute and/or modify this
+..    document under the terms of the GNU Free Documentation License,
+..    Version 1.1 or any later version published by the Free Software
+..    Foundation, with no Invariant Sections, no Front-Cover Texts
+..    and no Back-Cover Texts. A copy of the license is included at
+..    Documentation/media/uapi/fdl-appendix.rst.
+..
+.. TODO: replace it to GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
 
 .. _media_request_ioc_reinit:
 
index 5f4a230..945113d 100644 (file)
@@ -1,4 +1,28 @@
-.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
+.. This file is dual-licensed: you can use it either under the terms
+.. of the GPL or the GFDL 1.1+ license, at your option. Note that this
+.. dual licensing only applies to this file, and not this project as a
+.. whole.
+..
+.. a) This file is free software; you can redistribute it and/or
+..    modify it under the terms of the GNU General Public License as
+..    published by the Free Software Foundation; either version 2 of
+..    the License, or (at your option) any later version.
+..
+..    This file is distributed in the hope that it will be useful,
+..    but WITHOUT ANY WARRANTY; without even the implied warranty of
+..    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+..    GNU General Public License for more details.
+..
+.. Or, alternatively,
+..
+.. b) Permission is granted to copy, distribute and/or modify this
+..    document under the terms of the GNU Free Documentation License,
+..    Version 1.1 or any later version published by the Free Software
+..    Foundation, with no Invariant Sections, no Front-Cover Texts
+..    and no Back-Cover Texts. A copy of the license is included at
+..    Documentation/media/uapi/fdl-appendix.rst.
+..
+.. TODO: replace it to GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
 
 .. _media-request-api:
 
index 098d7f2..dcf3f35 100644 (file)
@@ -1,4 +1,28 @@
-.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
+.. This file is dual-licensed: you can use it either under the terms
+.. of the GPL or the GFDL 1.1+ license, at your option. Note that this
+.. dual licensing only applies to this file, and not this project as a
+.. whole.
+..
+.. a) This file is free software; you can redistribute it and/or
+..    modify it under the terms of the GNU General Public License as
+..    published by the Free Software Foundation; either version 2 of
+..    the License, or (at your option) any later version.
+..
+..    This file is distributed in the hope that it will be useful,
+..    but WITHOUT ANY WARRANTY; without even the implied warranty of
+..    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+..    GNU General Public License for more details.
+..
+.. Or, alternatively,
+..
+.. b) Permission is granted to copy, distribute and/or modify this
+..    document under the terms of the GNU Free Documentation License,
+..    Version 1.1 or any later version published by the Free Software
+..    Foundation, with no Invariant Sections, no Front-Cover Texts
+..    and no Back-Cover Texts. A copy of the license is included at
+..    Documentation/media/uapi/fdl-appendix.rst.
+..
+.. TODO: replace it to GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
 
 .. _request-func-close:
 
index ff7b072..11a22f8 100644 (file)
@@ -1,4 +1,28 @@
-.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
+.. This file is dual-licensed: you can use it either under the terms
+.. of the GPL or the GFDL 1.1+ license, at your option. Note that this
+.. dual licensing only applies to this file, and not this project as a
+.. whole.
+..
+.. a) This file is free software; you can redistribute it and/or
+..    modify it under the terms of the GNU General Public License as
+..    published by the Free Software Foundation; either version 2 of
+..    the License, or (at your option) any later version.
+..
+..    This file is distributed in the hope that it will be useful,
+..    but WITHOUT ANY WARRANTY; without even the implied warranty of
+..    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+..    GNU General Public License for more details.
+..
+.. Or, alternatively,
+..
+.. b) Permission is granted to copy, distribute and/or modify this
+..    document under the terms of the GNU Free Documentation License,
+..    Version 1.1 or any later version published by the Free Software
+..    Foundation, with no Invariant Sections, no Front-Cover Texts
+..    and no Back-Cover Texts. A copy of the license is included at
+..    Documentation/media/uapi/fdl-appendix.rst.
+..
+.. TODO: replace it to GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
 
 .. _request-func-ioctl:
 
index 8519125..2609fd5 100644 (file)
@@ -1,4 +1,28 @@
-.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
+.. This file is dual-licensed: you can use it either under the terms
+.. of the GPL or the GFDL 1.1+ license, at your option. Note that this
+.. dual licensing only applies to this file, and not this project as a
+.. whole.
+..
+.. a) This file is free software; you can redistribute it and/or
+..    modify it under the terms of the GNU General Public License as
+..    published by the Free Software Foundation; either version 2 of
+..    the License, or (at your option) any later version.
+..
+..    This file is distributed in the hope that it will be useful,
+..    but WITHOUT ANY WARRANTY; without even the implied warranty of
+..    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+..    GNU General Public License for more details.
+..
+.. Or, alternatively,
+..
+.. b) Permission is granted to copy, distribute and/or modify this
+..    document under the terms of the GNU Free Documentation License,
+..    Version 1.1 or any later version published by the Free Software
+..    Foundation, with no Invariant Sections, no Front-Cover Texts
+..    and no Back-Cover Texts. A copy of the license is included at
+..    Documentation/media/uapi/fdl-appendix.rst.
+..
+.. TODO: replace it to GPL-2.0 OR GFDL-1.1-or-later WITH no-invariant-sections
 
 .. _request-func-poll:
 
index 32f3d55..c4dbe6f 100644 (file)
@@ -92,3 +92,12 @@ Speculation misfeature controls
    * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_ENABLE, 0, 0);
    * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0);
    * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_FORCE_DISABLE, 0, 0);
+
+- PR_SPEC_INDIR_BRANCH: Indirect Branch Speculation in User Processes
+                        (Mitigate Spectre V2 style attacks against user processes)
+
+  Invocations:
+   * prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, 0, 0, 0);
+   * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_ENABLE, 0, 0);
+   * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_DISABLE, 0, 0);
+   * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_FORCE_DISABLE, 0, 0);
index 7727db8..5e9b826 100644 (file)
@@ -61,18 +61,6 @@ Protocol 2.12:       (Kernel 3.8) Added the xloadflags field and extension fields
                to struct boot_params for loading bzImage and ramdisk
                above 4G in 64bit.
 
-Protocol 2.13: (Kernel 3.14) Support 32- and 64-bit flags being set in
-               xloadflags to support booting a 64-bit kernel from 32-bit
-               EFI
-
-Protocol 2.14: (Kernel 4.20) Added acpi_rsdp_addr holding the physical
-               address of the ACPI RSDP table.
-               The bootloader updates version with:
-               0x8000 | min(kernel-version, bootloader-version)
-               kernel-version being the protocol version supported by
-               the kernel and bootloader-version the protocol version
-               supported by the bootloader.
-
 **** MEMORY LAYOUT
 
 The traditional memory map for the kernel loader, used for Image or
@@ -209,7 +197,6 @@ Offset      Proto   Name            Meaning
 0258/8 2.10+   pref_address    Preferred loading address
 0260/4 2.10+   init_size       Linear memory required during initialization
 0264/4 2.11+   handover_offset Offset of handover entry point
-0268/8 2.14+   acpi_rsdp_addr  Physical address of RSDP table
 
 (1) For backwards compatibility, if the setup_sects field contains 0, the
     real value is 4.
@@ -322,7 +309,7 @@ Protocol:   2.00+
   Contains the magic number "HdrS" (0x53726448).
 
 Field name:    version
-Type:          modify
+Type:          read
 Offset/size:   0x206/2
 Protocol:      2.00+
 
@@ -330,12 +317,6 @@ Protocol:  2.00+
   e.g. 0x0204 for version 2.04, and 0x0a11 for a hypothetical version
   10.17.
 
-  Up to protocol version 2.13 this information is only read by the
-  bootloader. From protocol version 2.14 onwards the bootloader will
-  write the used protocol version or-ed with 0x8000 to the field. The
-  used protocol version will be the minimum of the supported protocol
-  versions of the bootloader and the kernel.
-
 Field name:    realmode_swtch
 Type:          modify (optional)
 Offset/size:   0x208/4
@@ -763,17 +744,6 @@ Offset/size:       0x264/4
 
   See EFI HANDOVER PROTOCOL below for more details.
 
-Field name:    acpi_rsdp_addr
-Type:          write
-Offset/size:   0x268/8
-Protocol:      2.14+
-
-  This field can be set by the boot loader to tell the kernel the
-  physical address of the ACPI RSDP table.
-
-  A value of 0 indicates the kernel should fall back to the standard
-  methods to locate the RSDP.
-
 
 **** THE IMAGE CHECKSUM
 
index 51d35f0..8119141 100644 (file)
@@ -1472,6 +1472,7 @@ F:        drivers/clk/sirf/
 F:     drivers/clocksource/timer-prima2.c
 F:     drivers/clocksource/timer-atlas7.c
 N:     [^a-z]sirf
+X:     drivers/gnss
 
 ARM/EBSA110 MACHINE SUPPORT
 M:     Russell King <linux@armlinux.org.uk>
@@ -1923,7 +1924,6 @@ ARM/QUALCOMM SUPPORT
 M:     Andy Gross <andy.gross@linaro.org>
 M:     David Brown <david.brown@linaro.org>
 L:     linux-arm-msm@vger.kernel.org
-L:     linux-soc@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/soc/qcom/
 F:     arch/arm/boot/dts/qcom-*.dts
@@ -2491,7 +2491,7 @@ F:        drivers/net/wireless/ath/*
 ATHEROS ATH5K WIRELESS DRIVER
 M:     Jiri Slaby <jirislaby@gmail.com>
 M:     Nick Kossifidis <mickflemm@gmail.com>
-M:     "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
+M:     Luis Chamberlain <mcgrof@kernel.org>
 L:     linux-wireless@vger.kernel.org
 W:     http://wireless.kernel.org/en/users/Drivers/ath5k
 S:     Maintained
@@ -2922,7 +2922,7 @@ F:        drivers/staging/vc04_services
 BROADCOM BCM47XX MIPS ARCHITECTURE
 M:     Hauke Mehrtens <hauke@hauke-m.de>
 M:     RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/mips/brcm/
 F:     arch/mips/bcm47xx/*
@@ -2931,7 +2931,6 @@ F:        arch/mips/include/asm/mach-bcm47xx/*
 BROADCOM BCM5301X ARM ARCHITECTURE
 M:     Hauke Mehrtens <hauke@hauke-m.de>
 M:     RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
-M:     Jon Mason <jonmason@broadcom.com>
 M:     bcm-kernel-feedback-list@broadcom.com
 L:     linux-arm-kernel@lists.infradead.org
 S:     Maintained
@@ -2986,7 +2985,7 @@ F:        drivers/cpufreq/bmips-cpufreq.c
 BROADCOM BMIPS MIPS ARCHITECTURE
 M:     Kevin Cernekee <cernekee@gmail.com>
 M:     Florian Fainelli <f.fainelli@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 T:     git git://github.com/broadcom/stblinux.git
 S:     Maintained
 F:     arch/mips/bmips/*
@@ -3077,7 +3076,6 @@ F:        drivers/net/ethernet/broadcom/genet/
 BROADCOM IPROC ARM ARCHITECTURE
 M:     Ray Jui <rjui@broadcom.com>
 M:     Scott Branden <sbranden@broadcom.com>
-M:     Jon Mason <jonmason@broadcom.com>
 M:     bcm-kernel-feedback-list@broadcom.com
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 T:     git git://github.com/broadcom/cygnus-linux.git
@@ -3124,7 +3122,7 @@ F:        include/uapi/rdma/bnxt_re-abi.h
 
 BROADCOM NVRAM DRIVER
 M:     RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     drivers/firmware/broadcom/*
 
@@ -3274,11 +3272,16 @@ S:      Maintained
 F:     sound/pci/oxygen/
 
 C-SKY ARCHITECTURE
-M:     Guo Ren <ren_guo@c-sky.com>
+M:     Guo Ren <guoren@kernel.org>
 T:     git https://github.com/c-sky/csky-linux.git
 S:     Supported
 F:     arch/csky/
 F:     Documentation/devicetree/bindings/csky/
+F:     drivers/irqchip/irq-csky-*
+F:     Documentation/devicetree/bindings/interrupt-controller/csky,*
+F:     drivers/clocksource/timer-gx6605s.c
+F:     drivers/clocksource/timer-mp-csky.c
+F:     Documentation/devicetree/bindings/timer/csky,*
 K:     csky
 N:     csky
 
@@ -4226,7 +4229,7 @@ F:        net/decnet/
 
 DECSTATION PLATFORM SUPPORT
 M:     "Maciej W. Rozycki" <macro@linux-mips.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 W:     http://www.linux-mips.org/wiki/DECstation
 S:     Maintained
 F:     arch/mips/dec/
@@ -5317,7 +5320,7 @@ EDAC-CAVIUM OCTEON
 M:     Ralf Baechle <ralf@linux-mips.org>
 M:     David Daney <david.daney@cavium.com>
 L:     linux-edac@vger.kernel.org
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Supported
 F:     drivers/edac/octeon_edac*
 
@@ -5835,7 +5838,7 @@ F:        include/uapi/linux/firewire*.h
 F:     tools/firewire/
 
 FIRMWARE LOADER (request_firmware)
-M:     Luis R. Rodriguez <mcgrof@kernel.org>
+M:     Luis Chamberlain <mcgrof@kernel.org>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 F:     Documentation/firmware_class/
@@ -6319,6 +6322,7 @@ F:        include/uapi/linux/gigaset_dev.h
 
 GNSS SUBSYSTEM
 M:     Johan Hovold <johan@kernel.org>
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/johan/gnss.git
 S:     Maintained
 F:     Documentation/ABI/testing/sysfs-class-gnss
 F:     Documentation/devicetree/bindings/gnss/
@@ -7764,7 +7768,7 @@ F:        Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.txt
 
 IOC3 ETHERNET DRIVER
 M:     Ralf Baechle <ralf@linux-mips.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/sgi/ioc3-eth.c
 
@@ -8135,7 +8139,7 @@ F:        tools/testing/selftests/
 F:     Documentation/dev-tools/kselftest*
 
 KERNEL USERMODE HELPER
-M:     "Luis R. Rodriguez" <mcgrof@kernel.org>
+M:     Luis Chamberlain <mcgrof@kernel.org>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 F:     kernel/umh.c
@@ -8192,7 +8196,7 @@ F:        arch/arm64/kvm/
 
 KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
 M:     James Hogan <jhogan@kernel.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Supported
 F:     arch/mips/include/uapi/asm/kvm*
 F:     arch/mips/include/asm/kvm*
@@ -8311,7 +8315,7 @@ F:        mm/kmemleak.c
 F:     mm/kmemleak-test.c
 
 KMOD KERNEL MODULE LOADER - USERMODE HELPER
-M:     "Luis R. Rodriguez" <mcgrof@kernel.org>
+M:     Luis Chamberlain <mcgrof@kernel.org>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 F:     kernel/kmod.c
@@ -8365,7 +8369,7 @@ F:        drivers/net/dsa/lantiq_gswip.c
 
 LANTIQ MIPS ARCHITECTURE
 M:     John Crispin <john@phrozen.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/lantiq
 F:     drivers/soc/lantiq
@@ -8928,7 +8932,7 @@ S:        Maintained
 
 MARDUK (CREATOR CI40) DEVICE TREE SUPPORT
 M:     Rahul Bedarkar <rahulbedarkar89@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/boot/dts/img/pistachio_marduk.dts
 
@@ -9887,7 +9891,7 @@ F:        drivers/dma/at_xdmac.c
 
 MICROSEMI MIPS SOCS
 M:     Alexandre Belloni <alexandre.belloni@bootlin.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/generic/board-ocelot.c
 F:     arch/mips/configs/generic/board-ocelot.config
@@ -9927,7 +9931,7 @@ MIPS
 M:     Ralf Baechle <ralf@linux-mips.org>
 M:     Paul Burton <paul.burton@mips.com>
 M:     James Hogan <jhogan@kernel.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 W:     http://www.linux-mips.org/
 T:     git git://git.linux-mips.org/pub/scm/ralf/linux.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux.git
@@ -9940,7 +9944,7 @@ F:        drivers/platform/mips/
 
 MIPS BOSTON DEVELOPMENT BOARD
 M:     Paul Burton <paul.burton@mips.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/clock/img,boston-clock.txt
 F:     arch/mips/boot/dts/img/boston.dts
@@ -9950,7 +9954,7 @@ F:        include/dt-bindings/clock/boston-clock.h
 
 MIPS GENERIC PLATFORM
 M:     Paul Burton <paul.burton@mips.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/power/mti,mips-cpc.txt
 F:     arch/mips/generic/
@@ -9958,7 +9962,7 @@ F:        arch/mips/tools/generic-board-config.sh
 
 MIPS/LOONGSON1 ARCHITECTURE
 M:     Keguang Zhang <keguang.zhang@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/loongson32/
 F:     arch/mips/include/asm/mach-loongson32/
@@ -9967,7 +9971,7 @@ F:        drivers/*/*/*loongson1*
 
 MIPS/LOONGSON2 ARCHITECTURE
 M:     Jiaxun Yang <jiaxun.yang@flygoat.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/loongson64/fuloong-2e/
 F:     arch/mips/loongson64/lemote-2f/
@@ -9977,7 +9981,7 @@ F:        drivers/*/*/*loongson2*
 
 MIPS/LOONGSON3 ARCHITECTURE
 M:     Huacai Chen <chenhc@lemote.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/loongson64/
 F:     arch/mips/include/asm/mach-loongson64/
@@ -9987,7 +9991,7 @@ F:        drivers/*/*/*loongson3*
 
 MIPS RINT INSTRUCTION EMULATION
 M:     Aleksandar Markovic <aleksandar.markovic@mips.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Supported
 F:     arch/mips/math-emu/sp_rint.c
 F:     arch/mips/math-emu/dp_rint.c
@@ -10972,7 +10976,7 @@ F:      include/linux/platform_data/i2c-omap.h
 
 ONION OMEGA2+ BOARD
 M:     Harvey Hunt <harveyhuntnexus@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/boot/dts/ralink/omega2p.dts
 
@@ -11881,7 +11885,7 @@ F:      drivers/pinctrl/spear/
 
 PISTACHIO SOC SUPPORT
 M:     James Hartley <james.hartley@sondrel.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Odd Fixes
 F:     arch/mips/pistachio/
 F:     arch/mips/include/asm/mach-pistachio/
@@ -12061,7 +12065,7 @@ F:      kernel/printk/
 F:     include/linux/printk.h
 
 PRISM54 WIRELESS DRIVER
-M:     "Luis R. Rodriguez" <mcgrof@gmail.com>
+M:     Luis Chamberlain <mcgrof@kernel.org>
 L:     linux-wireless@vger.kernel.org
 W:     http://wireless.kernel.org/en/users/Drivers/p54
 S:     Obsolete
@@ -12075,9 +12079,10 @@ S:     Maintained
 F:     fs/proc/
 F:     include/linux/proc_fs.h
 F:     tools/testing/selftests/proc/
+F:     Documentation/filesystems/proc.txt
 
 PROC SYSCTL
-M:     "Luis R. Rodriguez" <mcgrof@kernel.org>
+M:     Luis Chamberlain <mcgrof@kernel.org>
 M:     Kees Cook <keescook@chromium.org>
 L:     linux-kernel@vger.kernel.org
 L:     linux-fsdevel@vger.kernel.org
@@ -12540,7 +12545,7 @@ F:      drivers/media/usb/rainshadow-cec/*
 
 RALINK MIPS ARCHITECTURE
 M:     John Crispin <john@phrozen.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/ralink
 
@@ -12560,7 +12565,7 @@ F:      drivers/block/brd.c
 
 RANCHU VIRTUAL BOARD FOR MIPS
 M:     Miodrag Dinic <miodrag.dinic@mips.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Supported
 F:     arch/mips/generic/board-ranchu.c
 F:     arch/mips/configs/generic/board-ranchu.config
@@ -14017,6 +14022,7 @@ S:      Supported
 F:     Documentation/devicetree/bindings/sound/
 F:     Documentation/sound/soc/
 F:     sound/soc/
+F:     include/dt-bindings/sound/
 F:     include/sound/soc*
 
 SOUNDWIRE SUBSYSTEM
@@ -15302,7 +15308,7 @@ F:      arch/um/os-Linux/drivers/
 TURBOCHANNEL SUBSYSTEM
 M:     "Maciej W. Rozycki" <macro@linux-mips.org>
 M:     Ralf Baechle <ralf@linux-mips.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 Q:     http://patchwork.linux-mips.org/project/linux-mips/list/
 S:     Maintained
 F:     drivers/tc/
@@ -16123,7 +16129,7 @@ F:      drivers/net/vmxnet3/
 
 VOCORE VOCORE2 BOARD
 M:     Harvey Hunt <harveyhuntnexus@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/boot/dts/ralink/vocore2.dts
 
index 0ce4e29..e9fd22c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 4
 PATCHLEVEL = 20
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc5
 NAME = Shy Crocodile
 
 # *DOCUMENTATION*
index c9e2a13..6dd7835 100644 (file)
@@ -109,7 +109,7 @@ endmenu
 
 choice
        prompt "ARC Instruction Set"
-       default ISA_ARCOMPACT
+       default ISA_ARCV2
 
 config ISA_ARCOMPACT
        bool "ARCompact ISA"
@@ -176,13 +176,11 @@ endchoice
 
 config CPU_BIG_ENDIAN
        bool "Enable Big Endian Mode"
-       default n
        help
          Build kernel for Big Endian Mode of ARC CPU
 
 config SMP
        bool "Symmetric Multi-Processing"
-       default n
        select ARC_MCIP if ISA_ARCV2
        help
          This enables support for systems with more than one CPU.
@@ -254,7 +252,6 @@ config ARC_CACHE_PAGES
 config ARC_CACHE_VIPT_ALIASING
        bool "Support VIPT Aliasing D$"
        depends on ARC_HAS_DCACHE && ISA_ARCOMPACT
-       default n
 
 endif  #ARC_CACHE
 
@@ -262,7 +259,6 @@ config ARC_HAS_ICCM
        bool "Use ICCM"
        help
          Single Cycle RAMS to store Fast Path Code
-       default n
 
 config ARC_ICCM_SZ
        int "ICCM Size in KB"
@@ -273,7 +269,6 @@ config ARC_HAS_DCCM
        bool "Use DCCM"
        help
          Single Cycle RAMS to store Fast Path Data
-       default n
 
 config ARC_DCCM_SZ
        int "DCCM Size in KB"
@@ -366,13 +361,11 @@ if ISA_ARCOMPACT
 
 config ARC_COMPACT_IRQ_LEVELS
        bool "Setup Timer IRQ as high Priority"
-       default n
        # if SMP, LV2 enabled ONLY if ARC implementation has LV2 re-entrancy
        depends on !SMP
 
 config ARC_FPU_SAVE_RESTORE
        bool "Enable FPU state persistence across context switch"
-       default n
        help
          Double Precision Floating Point unit had dedicated regs which
          need to be saved/restored across context-switch.
@@ -453,7 +446,6 @@ config HIGHMEM
 
 config ARC_HAS_PAE40
        bool "Support for the 40-bit Physical Address Extension"
-       default n
        depends on ISA_ARCV2
        select HIGHMEM
        select PHYS_ADDR_T_64BIT
@@ -496,7 +488,6 @@ config HZ
 
 config ARC_METAWARE_HLINK
        bool "Support for Metaware debugger assisted Host access"
-       default n
        help
          This options allows a Linux userland apps to directly access
          host file system (open/creat/read/write etc) with help from
@@ -524,13 +515,11 @@ config ARC_DW2_UNWIND
 
 config ARC_DBG_TLB_PARANOIA
        bool "Paranoia Checks in Low Level TLB Handlers"
-       default n
 
 endif
 
 config ARC_UBOOT_SUPPORT
        bool "Support uboot arg Handling"
-       default n
        help
          ARC Linux by default checks for uboot provided args as pointers to
          external cmdline or DTB. This however breaks in absence of uboot,
index c64c505..df00578 100644 (file)
@@ -6,7 +6,7 @@
 # published by the Free Software Foundation.
 #
 
-KBUILD_DEFCONFIG := nsim_700_defconfig
+KBUILD_DEFCONFIG := nsim_hs_defconfig
 
 cflags-y       += -fno-common -pipe -fno-builtin -mmedium-calls -D__linux__
 cflags-$(CONFIG_ISA_ARCOMPACT) += -mA7
index ef149f5..43f17b5 100644 (file)
                        bus-width = <4>;
                        dma-coherent;
                };
+
+               gpio: gpio@3000 {
+                       compatible = "snps,dw-apb-gpio";
+                       reg = <0x3000 0x20>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       gpio_port_a: gpio-controller@0 {
+                               compatible = "snps,dw-apb-gpio-port";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               snps,nr-gpios = <24>;
+                               reg = <0>;
+                       };
+               };
        };
 
        memory@80000000 {
index 41bc08b..020d449 100644 (file)
@@ -14,6 +14,7 @@ CONFIG_PERF_EVENTS=y
 # CONFIG_VM_EVENT_COUNTERS is not set
 # CONFIG_SLUB_DEBUG is not set
 # CONFIG_COMPAT_BRK is not set
+CONFIG_ISA_ARCOMPACT=y
 CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
 CONFIG_MODULE_UNLOAD=y
@@ -95,6 +96,7 @@ CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
 CONFIG_TMPFS=y
 CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
index 1e1c4a8..666314f 100644 (file)
@@ -94,6 +94,7 @@ CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
 CONFIG_TMPFS=y
 CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
index 6b0c0cf..429832b 100644 (file)
@@ -97,6 +97,7 @@ CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
 CONFIG_TMPFS=y
 CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
index 1dec2b4..87b23b7 100644 (file)
@@ -45,6 +45,9 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_DW=y
 CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_DWAPB=y
 # CONFIG_HWMON is not set
 CONFIG_DRM=y
 # CONFIG_DRM_FBDEV_EMULATION is not set
@@ -65,6 +68,7 @@ CONFIG_EXT3_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
index 31ba224..6e84060 100644 (file)
@@ -15,6 +15,7 @@ CONFIG_SYSCTL_SYSCALL=y
 CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
 # CONFIG_COMPAT_BRK is not set
+CONFIG_ISA_ARCOMPACT=y
 CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
@@ -73,6 +74,7 @@ CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
 CONFIG_ROOT_NFS=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
index 8e0b8b1..219c2a6 100644 (file)
@@ -15,6 +15,7 @@ CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
 # CONFIG_SLUB_DEBUG is not set
 # CONFIG_COMPAT_BRK is not set
+CONFIG_ISA_ARCOMPACT=y
 CONFIG_KPROBES=y
 CONFIG_MODULES=y
 # CONFIG_LBDAF is not set
index f14eeff..35dfc64 100644 (file)
@@ -15,6 +15,7 @@ CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
 # CONFIG_SLUB_DEBUG is not set
 # CONFIG_COMPAT_BRK is not set
+CONFIG_ISA_ARCOMPACT=y
 CONFIG_KPROBES=y
 CONFIG_MODULES=y
 # CONFIG_LBDAF is not set
@@ -66,5 +67,6 @@ CONFIG_EXT2_FS_XATTR=y
 CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
index 025298a..1638e5b 100644 (file)
@@ -65,5 +65,6 @@ CONFIG_EXT2_FS_XATTR=y
 CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
index df7b77b..11cfbdb 100644 (file)
@@ -76,6 +76,7 @@ CONFIG_EXT2_FS_XATTR=y
 CONFIG_TMPFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_FTRACE=y
index a7f6531..e71ade3 100644 (file)
@@ -19,6 +19,7 @@ CONFIG_KALLSYMS_ALL=y
 # CONFIG_AIO is not set
 CONFIG_EMBEDDED=y
 # CONFIG_COMPAT_BRK is not set
+CONFIG_ISA_ARCOMPACT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
index db47c35..1e59a2e 100644 (file)
@@ -85,6 +85,7 @@ CONFIG_NTFS_FS=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
index a8ac5e9..b5c3f6c 100644 (file)
@@ -90,6 +90,7 @@ CONFIG_NTFS_FS=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
index ff7d323..f393b66 100644 (file)
@@ -113,7 +113,9 @@ extern unsigned long perip_base, perip_end;
 
 /* IO coherency related Auxiliary registers */
 #define ARC_REG_IO_COH_ENABLE  0x500
+#define ARC_IO_COH_ENABLE_BIT  BIT(0)
 #define ARC_REG_IO_COH_PARTIAL 0x501
+#define ARC_IO_COH_PARTIAL_BIT BIT(0)
 #define ARC_REG_IO_COH_AP0_BASE        0x508
 #define ARC_REG_IO_COH_AP0_SIZE        0x509
 
index c22b181..2f39d9b 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <asm/byteorder.h>
 #include <asm/page.h>
+#include <asm/unaligned.h>
 
 #ifdef CONFIG_ISA_ARCV2
 #include <asm/barrier.h>
@@ -94,6 +95,42 @@ static inline u32 __raw_readl(const volatile void __iomem *addr)
        return w;
 }
 
+/*
+ * {read,write}s{b,w,l}() repeatedly access the same IO address in
+ * native endianness in 8-, 16-, 32-bit chunks {into,from} memory,
+ * @count times
+ */
+#define __raw_readsx(t,f) \
+static inline void __raw_reads##f(const volatile void __iomem *addr,   \
+                                 void *ptr, unsigned int count)        \
+{                                                                      \
+       bool is_aligned = ((unsigned long)ptr % ((t) / 8)) == 0;        \
+       u##t *buf = ptr;                                                \
+                                                                       \
+       if (!count)                                                     \
+               return;                                                 \
+                                                                       \
+       /* Some ARC CPU's don't support unaligned accesses */           \
+       if (is_aligned) {                                               \
+               do {                                                    \
+                       u##t x = __raw_read##f(addr);                   \
+                       *buf++ = x;                                     \
+               } while (--count);                                      \
+       } else {                                                        \
+               do {                                                    \
+                       u##t x = __raw_read##f(addr);                   \
+                       put_unaligned(x, buf++);                        \
+               } while (--count);                                      \
+       }                                                               \
+}
+
+#define __raw_readsb __raw_readsb
+__raw_readsx(8, b)
+#define __raw_readsw __raw_readsw
+__raw_readsx(16, w)
+#define __raw_readsl __raw_readsl
+__raw_readsx(32, l)
+
 #define __raw_writeb __raw_writeb
 static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
 {
@@ -126,6 +163,35 @@ static inline void __raw_writel(u32 w, volatile void __iomem *addr)
 
 }
 
+#define __raw_writesx(t,f)                                             \
+static inline void __raw_writes##f(volatile void __iomem *addr,        \
+                                  const void *ptr, unsigned int count) \
+{                                                                      \
+       bool is_aligned = ((unsigned long)ptr % ((t) / 8)) == 0;        \
+       const u##t *buf = ptr;                                          \
+                                                                       \
+       if (!count)                                                     \
+               return;                                                 \
+                                                                       \
+       /* Some ARC CPU's don't support unaligned accesses */           \
+       if (is_aligned) {                                               \
+               do {                                                    \
+                       __raw_write##f(*buf++, addr);                   \
+               } while (--count);                                      \
+       } else {                                                        \
+               do {                                                    \
+                       __raw_write##f(get_unaligned(buf++), addr);     \
+               } while (--count);                                      \
+       }                                                               \
+}
+
+#define __raw_writesb __raw_writesb
+__raw_writesx(8, b)
+#define __raw_writesw __raw_writesw
+__raw_writesx(16, w)
+#define __raw_writesl __raw_writesl
+__raw_writesx(32, l)
+
 /*
  * MMIO can also get buffered/optimized in micro-arch, so barriers needed
  * Based on ARM model for the typical use case
@@ -141,10 +207,16 @@ static inline void __raw_writel(u32 w, volatile void __iomem *addr)
 #define readb(c)               ({ u8  __v = readb_relaxed(c); __iormb(); __v; })
 #define readw(c)               ({ u16 __v = readw_relaxed(c); __iormb(); __v; })
 #define readl(c)               ({ u32 __v = readl_relaxed(c); __iormb(); __v; })
+#define readsb(p,d,l)          ({ __raw_readsb(p,d,l); __iormb(); })
+#define readsw(p,d,l)          ({ __raw_readsw(p,d,l); __iormb(); })
+#define readsl(p,d,l)          ({ __raw_readsl(p,d,l); __iormb(); })
 
 #define writeb(v,c)            ({ __iowmb(); writeb_relaxed(v,c); })
 #define writew(v,c)            ({ __iowmb(); writew_relaxed(v,c); })
 #define writel(v,c)            ({ __iowmb(); writel_relaxed(v,c); })
+#define writesb(p,d,l)         ({ __iowmb(); __raw_writesb(p,d,l); })
+#define writesw(p,d,l)         ({ __iowmb(); __raw_writesw(p,d,l); })
+#define writesl(p,d,l)         ({ __iowmb(); __raw_writesl(p,d,l); })
 
 /*
  * Relaxed API for drivers which can handle barrier ordering themselves
index b2cae79..eea8c5c 100644 (file)
@@ -243,7 +243,7 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
 {
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id];
        struct bcr_identity *core = &cpu->core;
-       int i, n = 0;
+       int i, n = 0, ua = 0;
 
        FIX_PTR(cpu);
 
@@ -263,10 +263,13 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
                       IS_AVAIL2(cpu->extn.rtc, "RTC [UP 64-bit] ", CONFIG_ARC_TIMERS_64BIT),
                       IS_AVAIL2(cpu->extn.gfrc, "GFRC [SMP 64-bit] ", CONFIG_ARC_TIMERS_64BIT));
 
-       n += i = scnprintf(buf + n, len - n, "%s%s%s%s%s",
+#ifdef __ARC_UNALIGNED__
+       ua = 1;
+#endif
+       n += i = scnprintf(buf + n, len - n, "%s%s%s%s%s%s",
                           IS_AVAIL2(cpu->isa.atomic, "atomic ", CONFIG_ARC_HAS_LLSC),
                           IS_AVAIL2(cpu->isa.ldd, "ll64 ", CONFIG_ARC_HAS_LL64),
-                          IS_AVAIL1(cpu->isa.unalign, "unalign (not used)"));
+                          IS_AVAIL1(cpu->isa.unalign, "unalign "), IS_USED_RUN(ua));
 
        if (i)
                n += scnprintf(buf + n, len - n, "\n\t\t: ");
index f2701c1..cf9619d 100644 (file)
@@ -1144,6 +1144,20 @@ noinline void __init arc_ioc_setup(void)
 {
        unsigned int ioc_base, mem_sz;
 
+       /*
+        * If IOC was already enabled (due to bootloader) it technically needs to
+        * be reconfigured with aperture base,size corresponding to Linux memory map
+        * which will certainly be different than uboot's. But disabling and
+        * reenabling IOC when DMA might be potentially active is tricky business.
+        * To avoid random memory issues later, just panic here and ask user to
+        * upgrade bootloader to one which doesn't enable IOC
+        */
+       if (read_aux_reg(ARC_REG_IO_COH_ENABLE) & ARC_IO_COH_ENABLE_BIT)
+               panic("IOC already enabled, please upgrade bootloader!\n");
+
+       if (!ioc_enable)
+               return;
+
        /*
         * As for today we don't support both IOC and ZONE_HIGHMEM enabled
         * simultaneously. This happens because as of today IOC aperture covers
@@ -1187,8 +1201,8 @@ noinline void __init arc_ioc_setup(void)
                panic("IOC Aperture start must be aligned to the size of the aperture");
 
        write_aux_reg(ARC_REG_IO_COH_AP0_BASE, ioc_base >> 12);
-       write_aux_reg(ARC_REG_IO_COH_PARTIAL, 1);
-       write_aux_reg(ARC_REG_IO_COH_ENABLE, 1);
+       write_aux_reg(ARC_REG_IO_COH_PARTIAL, ARC_IO_COH_PARTIAL_BIT);
+       write_aux_reg(ARC_REG_IO_COH_ENABLE, ARC_IO_COH_ENABLE_BIT);
 
        /* Re-enable L1 dcache */
        __dc_enable();
@@ -1265,7 +1279,7 @@ void __init arc_cache_init_master(void)
        if (is_isa_arcv2() && l2_line_sz && !slc_enable)
                arc_slc_disable();
 
-       if (is_isa_arcv2() && ioc_enable)
+       if (is_isa_arcv2() && ioc_exists)
                arc_ioc_setup();
 
        if (is_isa_arcv2() && l2_line_sz && slc_enable) {
index c9da610..e2d9fc3 100644 (file)
@@ -66,7 +66,7 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
        struct vm_area_struct *vma = NULL;
        struct task_struct *tsk = current;
        struct mm_struct *mm = tsk->mm;
-       int si_code;
+       int si_code = 0;
        int ret;
        vm_fault_t fault;
        int write = regs->ecr_cause & ECR_C_PROTV_STORE;  /* ST/EX */
index d4d33cd..1e2bb68 100644 (file)
        vmmc-supply = <&vmmc_fixed>;
        bus-width = <4>;
        wp-gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>; /* gpio_126 */
-       cd-gpios = <&gpio4 31 GPIO_ACTIVE_HIGH>; /* gpio_127 */
+       cd-gpios = <&gpio4 31 GPIO_ACTIVE_LOW>; /* gpio_127 */
 };
 
 &mmc3 {
index dae6e45..b1c988e 100644 (file)
                compatible = "ti,wl1271";
                reg = <2>;
                interrupt-parent = <&gpio6>;
-               interrupts = <10 IRQ_TYPE_LEVEL_HIGH>; /* gpio_170 */
+               interrupts = <10 IRQ_TYPE_EDGE_RISING>; /* gpio_170 */
                ref-clock-frequency = <26000000>;
                tcxo-clock-frequency = <26000000>;
        };
index e45a15c..69d753c 100644 (file)
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
 
-       eeprom@50 {
-               compatible = "atmel,24c04";
-               pagesize = <16>;
-               reg = <0x50>;
-       };
-
        hpa1: amp@60 {
                compatible = "ti,tpa6130a2";
                reg = <0x60>;
index ac34333..98b682a 100644 (file)
 };
 
 &mmc3 {
-       interrupts-extended = <&intc 94 &omap3_pmx_core2 0x46>;
+       interrupts-extended = <&intc 94 &omap3_pmx_core 0x136>;
        pinctrl-0 = <&mmc3_pins &wl127x_gpio>;
        pinctrl-names = "default";
        vmmc-supply = <&wl12xx_vmmc>;
index 9d5d53f..c39cf2c 100644 (file)
@@ -35,7 +35,7 @@
  * jumpering combinations for the long run.
  */
 &mmc3 {
-       interrupts-extended = <&intc 94 &omap3_pmx_core2 0x46>;
+       interrupts-extended = <&intc 94 &omap3_pmx_core 0x136>;
        pinctrl-0 = <&mmc3_pins &mmc3_core2_pins>;
        pinctrl-names = "default";
        vmmc-supply = <&wl12xx_vmmc>;
index 2075120..d8bf939 100644 (file)
 #include "rk3288.dtsi"
 
 / {
-       memory@0 {
+       /*
+        * The default coreboot on veyron devices ignores memory@0 nodes
+        * and would instead create another memory node.
+        */
+       memory {
                device_type = "memory";
                reg = <0x0 0x0 0x0 0x80000000>;
        };
index 843052f..dd0dda6 100644 (file)
                                  0x1 0x0 0x60000000 0x10000000
                                  0x2 0x0 0x70000000 0x10000000
                                  0x3 0x0 0x80000000 0x10000000>;
-                       clocks = <&mck>;
+                       clocks = <&h32ck>;
                        status = "disabled";
 
                        nand_controller: nand-controller {
index 0142fcf..bda949f 100644 (file)
@@ -183,9 +183,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
                           unsigned long frame_pointer)
 {
        unsigned long return_hooker = (unsigned long) &return_to_handler;
-       struct ftrace_graph_ent trace;
        unsigned long old;
-       int err;
 
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                return;
@@ -193,21 +191,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
        old = *parent;
        *parent = return_hooker;
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace)) {
+       if (function_graph_enter(old, self_addr, frame_pointer, NULL))
                *parent = old;
-               return;
-       }
-
-       err = ftrace_push_return_trace(old, self_addr, &trace.depth,
-                                      frame_pointer, NULL);
-       if (err == -EBUSY) {
-               *parent = old;
-               return;
-       }
 }
 
 #ifdef CONFIG_DYNAMIC_FTRACE
index 0bc5bd2..2cc9fe4 100644 (file)
@@ -759,7 +759,9 @@ static struct davinci_id da830_ids[] = {
 };
 
 static struct davinci_gpio_platform_data da830_gpio_platform_data = {
-       .ngpio = 128,
+       .no_auto_base   = true,
+       .base           = 0,
+       .ngpio          = 128,
 };
 
 int __init da830_register_gpio(void)
index 4528bbf..e7b78df 100644 (file)
@@ -719,7 +719,9 @@ int __init da850_register_vpif_capture(struct vpif_capture_config
 }
 
 static struct davinci_gpio_platform_data da850_gpio_platform_data = {
-       .ngpio = 144,
+       .no_auto_base   = true,
+       .base           = 0,
+       .ngpio          = 144,
 };
 
 int __init da850_register_gpio(void)
index 1fd3619..cf78da5 100644 (file)
@@ -701,6 +701,46 @@ static struct resource da8xx_gpio_resources[] = {
        },
        { /* interrupt */
                .start  = IRQ_DA8XX_GPIO0,
+               .end    = IRQ_DA8XX_GPIO0,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO1,
+               .end    = IRQ_DA8XX_GPIO1,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO2,
+               .end    = IRQ_DA8XX_GPIO2,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO3,
+               .end    = IRQ_DA8XX_GPIO3,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO4,
+               .end    = IRQ_DA8XX_GPIO4,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO5,
+               .end    = IRQ_DA8XX_GPIO5,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO6,
+               .end    = IRQ_DA8XX_GPIO6,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO7,
+               .end    = IRQ_DA8XX_GPIO7,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO8,
                .end    = IRQ_DA8XX_GPIO8,
                .flags  = IORESOURCE_IRQ,
        },
index 9f7d38d..4c6e0be 100644 (file)
@@ -548,12 +548,44 @@ static struct resource dm355_gpio_resources[] = {
        },
        {       /* interrupt */
                .start  = IRQ_DM355_GPIOBNK0,
+               .end    = IRQ_DM355_GPIOBNK0,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM355_GPIOBNK1,
+               .end    = IRQ_DM355_GPIOBNK1,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM355_GPIOBNK2,
+               .end    = IRQ_DM355_GPIOBNK2,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM355_GPIOBNK3,
+               .end    = IRQ_DM355_GPIOBNK3,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM355_GPIOBNK4,
+               .end    = IRQ_DM355_GPIOBNK4,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM355_GPIOBNK5,
+               .end    = IRQ_DM355_GPIOBNK5,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM355_GPIOBNK6,
                .end    = IRQ_DM355_GPIOBNK6,
                .flags  = IORESOURCE_IRQ,
        },
 };
 
 static struct davinci_gpio_platform_data dm355_gpio_platform_data = {
+       .no_auto_base   = true,
+       .base           = 0,
        .ngpio          = 104,
 };
 
index abcf2a5..01fb2b0 100644 (file)
@@ -267,12 +267,49 @@ static struct resource dm365_gpio_resources[] = {
        },
        {       /* interrupt */
                .start  = IRQ_DM365_GPIO0,
+               .end    = IRQ_DM365_GPIO0,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO1,
+               .end    = IRQ_DM365_GPIO1,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO2,
+               .end    = IRQ_DM365_GPIO2,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO3,
+               .end    = IRQ_DM365_GPIO3,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO4,
+               .end    = IRQ_DM365_GPIO4,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO5,
+               .end    = IRQ_DM365_GPIO5,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO6,
+               .end    = IRQ_DM365_GPIO6,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO7,
                .end    = IRQ_DM365_GPIO7,
                .flags  = IORESOURCE_IRQ,
        },
 };
 
 static struct davinci_gpio_platform_data dm365_gpio_platform_data = {
+       .no_auto_base   = true,
+       .base           = 0,
        .ngpio          = 104,
        .gpio_unbanked  = 8,
 };
index 0720da7..38f92b7 100644 (file)
@@ -492,12 +492,34 @@ static struct resource dm644_gpio_resources[] = {
        },
        {       /* interrupt */
                .start  = IRQ_GPIOBNK0,
+               .end    = IRQ_GPIOBNK0,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_GPIOBNK1,
+               .end    = IRQ_GPIOBNK1,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_GPIOBNK2,
+               .end    = IRQ_GPIOBNK2,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_GPIOBNK3,
+               .end    = IRQ_GPIOBNK3,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_GPIOBNK4,
                .end    = IRQ_GPIOBNK4,
                .flags  = IORESOURCE_IRQ,
        },
 };
 
 static struct davinci_gpio_platform_data dm644_gpio_platform_data = {
+       .no_auto_base   = true,
+       .base           = 0,
        .ngpio          = 71,
 };
 
index 6bd2ed0..7dc54b2 100644 (file)
@@ -442,12 +442,24 @@ static struct resource dm646x_gpio_resources[] = {
        },
        {       /* interrupt */
                .start  = IRQ_DM646X_GPIOBNK0,
+               .end    = IRQ_DM646X_GPIOBNK0,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM646X_GPIOBNK1,
+               .end    = IRQ_DM646X_GPIOBNK1,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM646X_GPIOBNK2,
                .end    = IRQ_DM646X_GPIOBNK2,
                .flags  = IORESOURCE_IRQ,
        },
 };
 
 static struct davinci_gpio_platform_data dm646x_gpio_platform_data = {
+       .no_auto_base   = true,
+       .base           = 0,
        .ngpio          = 43,
 };
 
index 3d191fd..1788674 100644 (file)
@@ -750,6 +750,9 @@ static void modem_pm(struct uart_port *port, unsigned int state, unsigned old)
        struct modem_private_data *priv = port->private_data;
        int ret;
 
+       if (!priv)
+               return;
+
        if (IS_ERR(priv->regulator))
                return;
 
index 7b95729..38a1be6 100644 (file)
@@ -351,7 +351,7 @@ static void omap44xx_prm_reconfigure_io_chain(void)
  * to occur, WAKEUPENABLE bits must be set in the pad mux registers, and
  * omap44xx_prm_reconfigure_io_chain() must be called.  No return value.
  */
-static void __init omap44xx_prm_enable_io_wakeup(void)
+static void omap44xx_prm_enable_io_wakeup(void)
 {
        s32 inst = omap4_prmst_get_prm_dev_inst();
 
index 215df43..2149b47 100644 (file)
@@ -360,14 +360,16 @@ v7_dma_inv_range:
        ALT_UP(W(nop))
 #endif
        mcrne   p15, 0, r0, c7, c14, 1          @ clean & invalidate D / U line
+       addne   r0, r0, r2
 
        tst     r1, r3
        bic     r1, r1, r3
        mcrne   p15, 0, r1, c7, c14, 1          @ clean & invalidate D / U line
-1:
-       mcr     p15, 0, r0, c7, c6, 1           @ invalidate D / U line
-       add     r0, r0, r2
        cmp     r0, r1
+1:
+       mcrlo   p15, 0, r0, c7, c6, 1           @ invalidate D / U line
+       addlo   r0, r0, r2
+       cmplo   r0, r1
        blo     1b
        dsb     st
        ret     lr
index 788486e..32aa2a2 100644 (file)
 /*
  * dcimvac: Invalidate data cache line by MVA to PoC
  */
-.macro dcimvac, rt, tmp
-       v7m_cacheop \rt, \tmp, V7M_SCB_DCIMVAC
+.irp    c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
+.macro dcimvac\c, rt, tmp
+       v7m_cacheop \rt, \tmp, V7M_SCB_DCIMVAC, \c
 .endm
+.endr
 
 /*
  * dccmvau: Clean data cache line by MVA to PoU
@@ -369,14 +371,16 @@ v7m_dma_inv_range:
        tst     r0, r3
        bic     r0, r0, r3
        dccimvacne r0, r3
+       addne   r0, r0, r2
        subne   r3, r2, #1      @ restore r3, corrupted by v7m's dccimvac
        tst     r1, r3
        bic     r1, r1, r3
        dccimvacne r1, r3
-1:
-       dcimvac r0, r3
-       add     r0, r0, r2
        cmp     r0, r1
+1:
+       dcimvaclo r0, r3
+       addlo   r0, r0, r2
+       cmplo   r0, r1
        blo     1b
        dsb     st
        ret     lr
index 661fe48..78de138 100644 (file)
@@ -829,7 +829,7 @@ static int __arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
                 void *cpu_addr, dma_addr_t dma_addr, size_t size,
                 unsigned long attrs)
 {
-       int ret;
+       int ret = -ENXIO;
        unsigned long nr_vma_pages = vma_pages(vma);
        unsigned long nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
        unsigned long pfn = dma_to_pfn(dev, dma_addr);
index 81d0efb..19516fb 100644 (file)
        .endm
 
 .macro define_processor_functions name:req, dabort:req, pabort:req, nommu=0, suspend=0, bugs=0
+/*
+ * If we are building for big.Little with branch predictor hardening,
+ * we need the processor function tables to remain available after boot.
+ */
+#if 1 // defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+       .section ".rodata"
+#endif
        .type   \name\()_processor_functions, #object
        .align 2
 ENTRY(\name\()_processor_functions)
@@ -309,6 +316,9 @@ ENTRY(\name\()_processor_functions)
        .endif
 
        .size   \name\()_processor_functions, . - \name\()_processor_functions
+#if 1 // defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+       .previous
+#endif
 .endm
 
 .macro define_cache_functions name:req
index b2aa9b3..2c118a6 100644 (file)
@@ -247,7 +247,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *or
        }
 
        /* Copy arch-dep-instance from template. */
-       memcpy(code, &optprobe_template_entry,
+       memcpy(code, (unsigned char *)optprobe_template_entry,
                        TMPL_END_IDX * sizeof(kprobe_opcode_t));
 
        /* Adjust buffer according to instruction. */
index 787d785..ea2ab03 100644 (file)
@@ -497,6 +497,24 @@ config ARM64_ERRATUM_1188873
 
          If unsure, say Y.
 
+config ARM64_ERRATUM_1286807
+       bool "Cortex-A76: Modification of the translation table for a virtual address might lead to read-after-read ordering violation"
+       default y
+       select ARM64_WORKAROUND_REPEAT_TLBI
+       help
+         This option adds workaround for ARM Cortex-A76 erratum 1286807
+
+         On the affected Cortex-A76 cores (r0p0 to r3p0), if a virtual
+         address for a cacheable mapping of a location is being
+         accessed by a core while another core is remapping the virtual
+         address to a new physical page using the recommended
+         break-before-make sequence, then under very rare circumstances
+         TLBI+DSB completes before a read using the translation being
+         invalidated has been observed by other observers. The
+         workaround repeats the TLBI+DSB operation.
+
+         If unsure, say Y.
+
 config CAVIUM_ERRATUM_22375
        bool "Cavium erratum 22375, 24313"
        default y
@@ -566,9 +584,16 @@ config QCOM_FALKOR_ERRATUM_1003
          is unchanged. Work around the erratum by invalidating the walk cache
          entries for the trampoline before entering the kernel proper.
 
+config ARM64_WORKAROUND_REPEAT_TLBI
+       bool
+       help
+         Enable the repeat TLBI workaround for Falkor erratum 1009 and
+         Cortex-A76 erratum 1286807.
+
 config QCOM_FALKOR_ERRATUM_1009
        bool "Falkor E1009: Prematurely complete a DSB after a TLBI"
        default y
+       select ARM64_WORKAROUND_REPEAT_TLBI
        help
          On Falkor v1, the CPU may prematurely complete a DSB following a
          TLBI xxIS invalidate maintenance operation. Repeat the TLBI operation
index b4276da..11fd1fe 100644 (file)
                };
        };
 };
+
+&tlmm {
+       gpio-reserved-ranges = <0 4>, <81 4>;
+};
index eedfaf8..b3def03 100644 (file)
        };
 };
 
+&gcc {
+       protected-clocks = <GCC_QSPI_CORE_CLK>,
+                          <GCC_QSPI_CORE_CLK_SRC>,
+                          <GCC_QSPI_CNOC_PERIPH_AHB_CLK>;
+};
+
 &i2c10 {
        status = "okay";
        clock-frequency = <400000>;
        status = "okay";
 };
 
+&tlmm {
+       gpio-reserved-ranges = <0 4>, <81 4>;
+};
+
 &uart9 {
        status = "okay";
 };
index 2dceeea..1e6a710 100644 (file)
 };
 
 &pcie0 {
-       ep-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_LOW>;
+       ep-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
        num-lanes = <4>;
        pinctrl-names = "default";
        pinctrl-0 = <&pcie_clkreqn_cpm>;
index 6c8c4ab..56abbb0 100644 (file)
                regulator-always-on;
                vin-supply = <&vcc_sys>;
        };
-
-       vdd_log: vdd-log {
-               compatible = "pwm-regulator";
-               pwms = <&pwm2 0 25000 0>;
-               regulator-name = "vdd_log";
-               regulator-min-microvolt = <800000>;
-               regulator-max-microvolt = <1400000>;
-               regulator-always-on;
-               regulator-boot-on;
-               vin-supply = <&vcc_sys>;
-       };
-
 };
 
 &cpu_l0 {
index affc3c3..8d7b47f 100644 (file)
@@ -36,7 +36,7 @@
 
        wkup_uart0: serial@42300000 {
                compatible = "ti,am654-uart";
-               reg = <0x00 0x42300000 0x00 0x100>;
+               reg = <0x42300000 0x100>;
                reg-shift = <2>;
                reg-io-width = <4>;
                interrupts = <GIC_SPI 697 IRQ_TYPE_LEVEL_HIGH>;
index caa955f..fac54fb 100644 (file)
@@ -56,6 +56,19 @@ static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
 {
        return is_compat_task();
 }
+
+#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
+
+static inline bool arch_syscall_match_sym_name(const char *sym,
+                                              const char *name)
+{
+       /*
+        * Since all syscall functions have __arm64_ prefix, we must skip it.
+        * However, as we described above, we decided to ignore compat
+        * syscalls, so we don't care about __arm64_compat_ prefix here.
+        */
+       return !strcmp(sym + 8, name);
+}
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
index c3c0387..5dfd238 100644 (file)
                   ALTERNATIVE("nop\n                   nop",                  \
                               "dsb ish\n               tlbi " #op,            \
                               ARM64_WORKAROUND_REPEAT_TLBI,                   \
-                              CONFIG_QCOM_FALKOR_ERRATUM_1009)                \
+                              CONFIG_ARM64_WORKAROUND_REPEAT_TLBI)            \
                            : : )
 
 #define __TLBI_1(op, arg) asm ("tlbi " #op ", %0\n"                           \
                   ALTERNATIVE("nop\n                   nop",                  \
                               "dsb ish\n               tlbi " #op ", %0",     \
                               ARM64_WORKAROUND_REPEAT_TLBI,                   \
-                              CONFIG_QCOM_FALKOR_ERRATUM_1009)                \
+                              CONFIG_ARM64_WORKAROUND_REPEAT_TLBI)            \
                            : : "r" (arg))
 
 #define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg)
index a509e35..6ad715d 100644 (file)
@@ -570,6 +570,20 @@ static const struct midr_range arm64_harden_el2_vectors[] = {
 
 #endif
 
+#ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI
+
+static const struct midr_range arm64_repeat_tlbi_cpus[] = {
+#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009
+       MIDR_RANGE(MIDR_QCOM_FALKOR_V1, 0, 0, 0, 0),
+#endif
+#ifdef CONFIG_ARM64_ERRATUM_1286807
+       MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 0),
+#endif
+       {},
+};
+
+#endif
+
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #if    defined(CONFIG_ARM64_ERRATUM_826319) || \
        defined(CONFIG_ARM64_ERRATUM_827319) || \
@@ -695,11 +709,11 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
                .matches = is_kryo_midr,
        },
 #endif
-#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009
+#ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI
        {
-               .desc = "Qualcomm Technologies Falkor erratum 1009",
+               .desc = "Qualcomm erratum 1009, ARM erratum 1286807",
                .capability = ARM64_WORKAROUND_REPEAT_TLBI,
-               ERRATA_MIDR_REV(MIDR_QCOM_FALKOR_V1, 0, 0),
+               ERRATA_MIDR_RANGE_LIST(arm64_repeat_tlbi_cpus),
        },
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_858921
index 50986e3..57e9622 100644 (file)
@@ -216,8 +216,6 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 {
        unsigned long return_hooker = (unsigned long)&return_to_handler;
        unsigned long old;
-       struct ftrace_graph_ent trace;
-       int err;
 
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                return;
@@ -229,18 +227,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
         */
        old = *parent;
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace))
-               return;
-
-       err = ftrace_push_return_trace(old, self_addr, &trace.depth,
-                                      frame_pointer, NULL);
-       if (err == -EBUSY)
-               return;
-       else
+       if (!function_graph_enter(old, self_addr, frame_pointer, NULL))
                *parent = return_hooker;
 }
 
index 6b2686d..29cdc99 100644 (file)
@@ -214,7 +214,7 @@ static int create_safe_exec_page(void *src_start, size_t length,
        }
 
        memcpy((void *)dst, src_start, length);
-       flush_icache_range(dst, dst + length);
+       __flush_icache_range(dst, dst + length);
 
        pgdp = pgd_offset_raw(allocator(mask), dst_addr);
        if (pgd_none(READ_ONCE(*pgdp))) {
index c410aa4..b2905c0 100644 (file)
@@ -16,7 +16,7 @@
 
 static inline void tlbmiss_handler_setup_pgd(unsigned long pgd, bool kernel)
 {
-       pgd &= ~(1<<31);
+       pgd -= PAGE_OFFSET;
        pgd += PHYS_OFFSET;
        pgd |= 1;
        setup_pgd(pgd, kernel);
@@ -29,7 +29,7 @@ static inline void tlbmiss_handler_setup_pgd(unsigned long pgd, bool kernel)
 
 static inline unsigned long tlb_get_pgd(void)
 {
-       return ((get_pgd()|(1<<31)) - PHYS_OFFSET) & ~1;
+       return ((get_pgd() - PHYS_OFFSET) & ~1) + PAGE_OFFSET;
 }
 
 #define cpu_context(cpu, mm)   ((mm)->context.asid[cpu])
index d57563c..224eea4 100644 (file)
@@ -22,8 +22,7 @@
 void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
 {
        unsigned long old;
-       int faulted, err;
-       struct ftrace_graph_ent trace;
+       int faulted;
        unsigned long return_hooker = (unsigned long)
                                &return_to_handler;
 
@@ -63,18 +62,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
                return;
        }
 
-       err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0, NULL);
-       if (err == -EBUSY) {
+       if (function_graph_enter(old, self_addr, 0, NULL))
                *parent = old;
-               return;
-       }
-
-       trace.func = self_addr;
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace)) {
-               current->curr_ret_stack--;
-               *parent = old;
-       }
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
index 0170602..6cf8ffb 100644 (file)
@@ -73,7 +73,7 @@ static inline unsigned long mips_get_syscall_arg(unsigned long *arg,
 #ifdef CONFIG_64BIT
        case 4: case 5: case 6: case 7:
 #ifdef CONFIG_MIPS32_O32
-               if (test_thread_flag(TIF_32BIT_REGS))
+               if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
                        return get_user(*arg, (int *)usp + n);
                else
 #endif
index 7f3dfdb..b122cbb 100644 (file)
@@ -322,7 +322,6 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra,
                           unsigned long fp)
 {
        unsigned long old_parent_ra;
-       struct ftrace_graph_ent trace;
        unsigned long return_hooker = (unsigned long)
            &return_to_handler;
        int faulted, insns;
@@ -369,12 +368,6 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra,
        if (unlikely(faulted))
                goto out;
 
-       if (ftrace_push_return_trace(old_parent_ra, self_ra, &trace.depth, fp,
-                                    NULL) == -EBUSY) {
-               *parent_ra_addr = old_parent_ra;
-               return;
-       }
-
        /*
         * Get the recorded ip of the current mcount calling site in the
         * __mcount_loc section, which will be used to filter the function
@@ -382,13 +375,10 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra,
         */
 
        insns = core_kernel_text(self_ra) ? 2 : MCOUNT_OFFSET_INSNS + 1;
-       trace.func = self_ra - (MCOUNT_INSN_SIZE * insns);
+       self_ra -= (MCOUNT_INSN_SIZE * insns);
 
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace)) {
-               current->curr_ret_stack--;
+       if (function_graph_enter(old_parent_ra, self_ra, fp, NULL))
                *parent_ra_addr = old_parent_ra;
-       }
        return;
 out:
        ftrace_graph_stop();
index 41b71c4..c1ce6f4 100644 (file)
@@ -84,7 +84,7 @@ static struct rt2880_pmx_func pcie_rst_grp[] = {
 };
 static struct rt2880_pmx_func nd_sd_grp[] = {
        FUNC("nand", MT7620_GPIO_MODE_NAND, 45, 15),
-       FUNC("sd", MT7620_GPIO_MODE_SD, 45, 15)
+       FUNC("sd", MT7620_GPIO_MODE_SD, 47, 13)
 };
 
 static struct rt2880_pmx_group mt7620a_pinmux_data[] = {
index a0a9679..8a41372 100644 (file)
@@ -211,29 +211,15 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
                           unsigned long frame_pointer)
 {
        unsigned long return_hooker = (unsigned long)&return_to_handler;
-       struct ftrace_graph_ent trace;
        unsigned long old;
-       int err;
 
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                return;
 
        old = *parent;
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace))
-               return;
-
-       err = ftrace_push_return_trace(old, self_addr, &trace.depth,
-                                      frame_pointer, NULL);
-
-       if (err == -EBUSY)
-               return;
-
-       *parent = return_hooker;
+       if (!function_graph_enter(old, self_addr, frame_pointer, NULL))
+               *parent = return_hooker;
 }
 
 noinline void ftrace_graph_caller(void)
index d047a09..1085385 100644 (file)
@@ -71,6 +71,13 @@ ifdef CONFIG_MLONGCALLS
 KBUILD_CFLAGS_KERNEL += -mlong-calls
 endif
 
+# Without this, "ld -r" results in .text sections that are too big (> 0x40000)
+# for branches to reach stubs. And multiple .text sections trigger a warning
+# when creating the sysfs module information section.
+ifndef CONFIG_64BIT
+KBUILD_CFLAGS_MODULE += -ffunction-sections
+endif
+
 # select which processor to optimise for
 cflags-$(CONFIG_PA7000)                += -march=1.1 -mschedule=7100
 cflags-$(CONFIG_PA7200)                += -march=1.1 -mschedule=7200
index 6fa8535..e46a415 100644 (file)
@@ -30,7 +30,6 @@ static void __hot prepare_ftrace_return(unsigned long *parent,
                                        unsigned long self_addr)
 {
        unsigned long old;
-       struct ftrace_graph_ent trace;
        extern int parisc_return_to_handler;
 
        if (unlikely(ftrace_graph_is_dead()))
@@ -41,19 +40,9 @@ static void __hot prepare_ftrace_return(unsigned long *parent,
 
        old = *parent;
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace))
-               return;
-
-        if (ftrace_push_return_trace(old, self_addr, &trace.depth,
-                                    0, NULL) == -EBUSY)
-                return;
-
-       /* activate parisc_return_to_handler() as return point */
-       *parent = (unsigned long) &parisc_return_to_handler;
+       if (!function_graph_enter(old, self_addr, 0, NULL))
+               /* activate parisc_return_to_handler() as return point */
+               *parent = (unsigned long) &parisc_return_to_handler;
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
index 4bf051d..b65c8a3 100644 (file)
@@ -950,7 +950,6 @@ int ftrace_disable_ftrace_graph_caller(void)
  */
 unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip)
 {
-       struct ftrace_graph_ent trace;
        unsigned long return_hooker;
 
        if (unlikely(ftrace_graph_is_dead()))
@@ -961,18 +960,8 @@ unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip)
 
        return_hooker = ppc_function_entry(return_to_handler);
 
-       trace.func = ip;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace))
-               goto out;
-
-       if (ftrace_push_return_trace(parent, ip, &trace.depth, 0,
-                                    NULL) == -EBUSY)
-               goto out;
-
-       parent = return_hooker;
+       if (!function_graph_enter(parent, ip, 0, NULL))
+               parent = return_hooker;
 out:
        return parent;
 }
index 1157b6b..c433f6d 100644 (file)
@@ -132,7 +132,6 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 {
        unsigned long return_hooker = (unsigned long)&return_to_handler;
        unsigned long old;
-       struct ftrace_graph_ent trace;
        int err;
 
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
@@ -144,17 +143,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
         */
        old = *parent;
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       if (!ftrace_graph_entry(&trace))
-               return;
-
-       err = ftrace_push_return_trace(old, self_addr, &trace.depth,
-                                      frame_pointer, parent);
-       if (err == -EBUSY)
-               return;
-       *parent = return_hooker;
+       if (function_graph_enter(old, self_addr, frame_pointer, parent))
+               *parent = return_hooker;
 }
 
 #ifdef CONFIG_DYNAMIC_FTRACE
index 84be7f0..39b13d7 100644 (file)
@@ -203,22 +203,13 @@ device_initcall(ftrace_plt_init);
  */
 unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip)
 {
-       struct ftrace_graph_ent trace;
-
        if (unlikely(ftrace_graph_is_dead()))
                goto out;
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                goto out;
        ip -= MCOUNT_INSN_SIZE;
-       trace.func = ip;
-       trace.depth = current->curr_ret_stack + 1;
-       /* Only trace if the calling function expects to. */
-       if (!ftrace_graph_entry(&trace))
-               goto out;
-       if (ftrace_push_return_trace(parent, ip, &trace.depth, 0,
-                                    NULL) == -EBUSY)
-               goto out;
-       parent = (unsigned long) return_to_handler;
+       if (!function_graph_enter(parent, ip, 0, NULL))
+               parent = (unsigned long) return_to_handler;
 out:
        return parent;
 }
index 74091fd..d5523ad 100644 (file)
@@ -346,6 +346,8 @@ static int __hw_perf_event_init(struct perf_event *event)
                break;
 
        case PERF_TYPE_HARDWARE:
+               if (is_sampling_event(event))   /* No sampling support */
+                       return -ENOENT;
                ev = attr->config;
                /* Count user space (problem-state) only */
                if (!attr->exclude_user && attr->exclude_kernel) {
index 814f265..6791562 100644 (file)
@@ -131,6 +131,7 @@ void crst_table_downgrade(struct mm_struct *mm)
        }
 
        pgd = mm->pgd;
+       mm_dec_nr_pmds(mm);
        mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN);
        mm->context.asce_limit = _REGION3_SIZE;
        mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH |
index 96dd9f7..1b04270 100644 (file)
@@ -321,8 +321,7 @@ int ftrace_disable_ftrace_graph_caller(void)
 void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
 {
        unsigned long old;
-       int faulted, err;
-       struct ftrace_graph_ent trace;
+       int faulted;
        unsigned long return_hooker = (unsigned long)&return_to_handler;
 
        if (unlikely(ftrace_graph_is_dead()))
@@ -365,18 +364,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
                return;
        }
 
-       err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0, NULL);
-       if (err == -EBUSY) {
+       if (function_graph_enter(old, self_addr, 0, NULL))
                __raw_writel(old, parent);
-               return;
-       }
-
-       trace.func = self_addr;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace)) {
-               current->curr_ret_stack--;
-               __raw_writel(old, parent);
-       }
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
index 915dda4..684b84c 100644 (file)
@@ -126,20 +126,11 @@ unsigned long prepare_ftrace_return(unsigned long parent,
                                    unsigned long frame_pointer)
 {
        unsigned long return_hooker = (unsigned long) &return_to_handler;
-       struct ftrace_graph_ent trace;
 
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                return parent + 8UL;
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace))
-               return parent + 8UL;
-
-       if (ftrace_push_return_trace(parent, self_addr, &trace.depth,
-                                    frame_pointer, NULL) == -EBUSY)
+       if (function_graph_enter(parent, self_addr, frame_pointer, NULL))
                return parent + 8UL;
 
        return return_hooker;
index 40d008b..05eb016 100644 (file)
@@ -108,10 +108,9 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
        /* Allocate and initialize the free area map.  */
        sz = num_tsb_entries / 8;
        sz = (sz + 7UL) & ~7UL;
-       iommu->tbl.map = kmalloc_node(sz, GFP_KERNEL, numa_node);
+       iommu->tbl.map = kzalloc_node(sz, GFP_KERNEL, numa_node);
        if (!iommu->tbl.map)
                return -ENOMEM;
-       memset(iommu->tbl.map, 0, sz);
 
        iommu_tbl_pool_init(&iommu->tbl, num_tsb_entries, IO_PAGE_SHIFT,
                            (tlb_type != hypervisor ? iommu_flushall : NULL),
index 4c5b3fc..e800ce1 100644 (file)
@@ -683,6 +683,7 @@ void do_signal32(struct pt_regs * regs)
                                regs->tpc -= 4;
                                regs->tnpc -= 4;
                                pt_regs_clear_syscall(regs);
+                               /* fall through */
                        case ERESTART_RESTARTBLOCK:
                                regs->u_regs[UREG_G1] = __NR_restart_syscall;
                                regs->tpc -= 4;
index 5665261..8395378 100644 (file)
@@ -508,6 +508,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
                                regs->pc -= 4;
                                regs->npc -= 4;
                                pt_regs_clear_syscall(regs);
+                               /* fall through */
                        case ERESTART_RESTARTBLOCK:
                                regs->u_regs[UREG_G1] = __NR_restart_syscall;
                                regs->pc -= 4;
index e9de180..ca70787 100644 (file)
@@ -533,6 +533,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
                                regs->tpc -= 4;
                                regs->tnpc -= 4;
                                pt_regs_clear_syscall(regs);
+                               /* fall through */
                        case ERESTART_RESTARTBLOCK:
                                regs->u_regs[UREG_G1] = __NR_restart_syscall;
                                regs->tpc -= 4;
index 9d734f3..8689e79 100644 (file)
@@ -444,10 +444,6 @@ config RETPOLINE
          branches. Requires a compiler with -mindirect-branch=thunk-extern
          support for full protection. The kernel may run slower.
 
-         Without compiler support, at least indirect branches in assembler
-         code are eliminated. Since this includes the syscall entry path,
-         it is not entirely pointless.
-
 config INTEL_RDT
        bool "Intel Resource Director Technology support"
        depends on X86 && CPU_SUP_INTEL
@@ -1004,13 +1000,7 @@ config NR_CPUS
          to the kernel image.
 
 config SCHED_SMT
-       bool "SMT (Hyperthreading) scheduler support"
-       depends on SMP
-       ---help---
-         SMT scheduler support improves the CPU scheduler's decision making
-         when dealing with Intel Pentium 4 chips with HyperThreading at a
-         cost of slightly increased overhead in some places. If unsure say
-         N here.
+       def_bool y if SMP
 
 config SCHED_MC
        def_bool y
index 88398fd..75ef499 100644 (file)
@@ -220,9 +220,7 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
 
 # Avoid indirect branches in kernel to deal with Spectre
 ifdef CONFIG_RETPOLINE
-ifneq ($(RETPOLINE_CFLAGS),)
-  KBUILD_CFLAGS += $(RETPOLINE_CFLAGS) -DRETPOLINE
-endif
+  KBUILD_CFLAGS += $(RETPOLINE_CFLAGS)
 endif
 
 archscripts: scripts_basic
@@ -306,6 +304,13 @@ ifndef CC_HAVE_ASM_GOTO
        @echo Compiler lacks asm-goto support.
        @exit 1
 endif
+ifdef CONFIG_RETPOLINE
+ifeq ($(RETPOLINE_CFLAGS),)
+       @echo "You are building kernel with non-retpoline compiler." >&2
+       @echo "Please update your compiler." >&2
+       @false
+endif
+endif
 
 archclean:
        $(Q)rm -rf $(objtree)/arch/i386
index 8b4c5e0..544ac4f 100644 (file)
@@ -1,3 +1,4 @@
+
 /* -----------------------------------------------------------------------
  *
  *   Copyright 2011 Intel Corporation; author Matt Fleming
@@ -634,37 +635,54 @@ static efi_status_t alloc_e820ext(u32 nr_desc, struct setup_data **e820ext,
        return status;
 }
 
+static efi_status_t allocate_e820(struct boot_params *params,
+                                 struct setup_data **e820ext,
+                                 u32 *e820ext_size)
+{
+       unsigned long map_size, desc_size, buff_size;
+       struct efi_boot_memmap boot_map;
+       efi_memory_desc_t *map;
+       efi_status_t status;
+       __u32 nr_desc;
+
+       boot_map.map            = &map;
+       boot_map.map_size       = &map_size;
+       boot_map.desc_size      = &desc_size;
+       boot_map.desc_ver       = NULL;
+       boot_map.key_ptr        = NULL;
+       boot_map.buff_size      = &buff_size;
+
+       status = efi_get_memory_map(sys_table, &boot_map);
+       if (status != EFI_SUCCESS)
+               return status;
+
+       nr_desc = buff_size / desc_size;
+
+       if (nr_desc > ARRAY_SIZE(params->e820_table)) {
+               u32 nr_e820ext = nr_desc - ARRAY_SIZE(params->e820_table);
+
+               status = alloc_e820ext(nr_e820ext, e820ext, e820ext_size);
+               if (status != EFI_SUCCESS)
+                       return status;
+       }
+
+       return EFI_SUCCESS;
+}
+
 struct exit_boot_struct {
        struct boot_params      *boot_params;
        struct efi_info         *efi;
-       struct setup_data       *e820ext;
-       __u32                   e820ext_size;
 };
 
 static efi_status_t exit_boot_func(efi_system_table_t *sys_table_arg,
                                   struct efi_boot_memmap *map,
                                   void *priv)
 {
-       static bool first = true;
        const char *signature;
        __u32 nr_desc;
        efi_status_t status;
        struct exit_boot_struct *p = priv;
 
-       if (first) {
-               nr_desc = *map->buff_size / *map->desc_size;
-               if (nr_desc > ARRAY_SIZE(p->boot_params->e820_table)) {
-                       u32 nr_e820ext = nr_desc -
-                                       ARRAY_SIZE(p->boot_params->e820_table);
-
-                       status = alloc_e820ext(nr_e820ext, &p->e820ext,
-                                              &p->e820ext_size);
-                       if (status != EFI_SUCCESS)
-                               return status;
-               }
-               first = false;
-       }
-
        signature = efi_is_64bit() ? EFI64_LOADER_SIGNATURE
                                   : EFI32_LOADER_SIGNATURE;
        memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32));
@@ -687,8 +705,8 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
 {
        unsigned long map_sz, key, desc_size, buff_size;
        efi_memory_desc_t *mem_map;
-       struct setup_data *e820ext;
-       __u32 e820ext_size;
+       struct setup_data *e820ext = NULL;
+       __u32 e820ext_size = 0;
        efi_status_t status;
        __u32 desc_version;
        struct efi_boot_memmap map;
@@ -702,8 +720,10 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
        map.buff_size           = &buff_size;
        priv.boot_params        = boot_params;
        priv.efi                = &boot_params->efi_info;
-       priv.e820ext            = NULL;
-       priv.e820ext_size       = 0;
+
+       status = allocate_e820(boot_params, &e820ext, &e820ext_size);
+       if (status != EFI_SUCCESS)
+               return status;
 
        /* Might as well exit boot services now */
        status = efi_exit_boot_services(sys_table, handle, &map, &priv,
@@ -711,9 +731,6 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle)
        if (status != EFI_SUCCESS)
                return status;
 
-       e820ext                 = priv.e820ext;
-       e820ext_size            = priv.e820ext_size;
-
        /* Historic? */
        boot_params->alt_mem_k  = 32 * 1024;
 
index 4c881c8..850b876 100644 (file)
@@ -300,7 +300,7 @@ _start:
        # Part 2 of the header, from the old setup.S
 
                .ascii  "HdrS"          # header signature
-               .word   0x020e          # header version number (>= 0x0105)
+               .word   0x020d          # header version number (>= 0x0105)
                                        # or else old loadlin-1.5 will fail)
                .globl realmode_swtch
 realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
@@ -558,10 +558,6 @@ pref_address:              .quad LOAD_PHYSICAL_ADDR        # preferred load addr
 init_size:             .long INIT_SIZE         # kernel initialization size
 handover_offset:       .long 0                 # Filled in by build.c
 
-acpi_rsdp_addr:                .quad 0                 # 64-bit physical pointer to the
-                                               # ACPI RSDP table, added with
-                                               # version 2.14
-
 # End of setup header #####################################################
 
        .section ".entrytext", "ax"
index ce25d84..1f0efdb 100644 (file)
@@ -566,6 +566,7 @@ ENTRY(interrupt_entry)
 
        ret
 END(interrupt_entry)
+_ASM_NOKPROBE(interrupt_entry)
 
 
 /* Interrupt entry/exit. */
@@ -766,6 +767,7 @@ native_irq_return_ldt:
        jmp     native_irq_return_iret
 #endif
 END(common_interrupt)
+_ASM_NOKPROBE(common_interrupt)
 
 /*
  * APIC interrupts.
@@ -780,6 +782,7 @@ ENTRY(\sym)
        call    \do_sym /* rdi points to pt_regs */
        jmp     ret_from_intr
 END(\sym)
+_ASM_NOKPROBE(\sym)
 .endm
 
 /* Make sure APIC interrupt handlers end up in the irqentry section: */
@@ -960,6 +963,7 @@ ENTRY(\sym)
 
        jmp     error_exit
        .endif
+_ASM_NOKPROBE(\sym)
 END(\sym)
 .endm
 
index 141d415..0624bf2 100644 (file)
@@ -47,7 +47,7 @@ targets += $(vdso_img_sodbg) $(vdso_img-y:%=vdso%.so)
 CPPFLAGS_vdso.lds += -P -C
 
 VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -soname linux-vdso.so.1 --no-undefined \
-                       -z max-page-size=4096 -z common-page-size=4096
+                       -z max-page-size=4096
 
 $(obj)/vdso64.so.dbg: $(obj)/vdso.lds $(vobjs) FORCE
        $(call if_changed,vdso)
@@ -98,7 +98,7 @@ CFLAGS_REMOVE_vvar.o = -pg
 
 CPPFLAGS_vdsox32.lds = $(CPPFLAGS_vdso.lds)
 VDSO_LDFLAGS_vdsox32.lds = -m elf32_x86_64 -soname linux-vdso.so.1 \
-                          -z max-page-size=4096 -z common-page-size=4096
+                          -z max-page-size=4096
 
 # x32-rebranded versions
 vobjx32s-y := $(vobjs-y:.o=-x32.o)
index 106911b..374a197 100644 (file)
@@ -438,26 +438,6 @@ int x86_setup_perfctr(struct perf_event *event)
        if (config == -1LL)
                return -EINVAL;
 
-       /*
-        * Branch tracing:
-        */
-       if (attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
-           !attr->freq && hwc->sample_period == 1) {
-               /* BTS is not supported by this architecture. */
-               if (!x86_pmu.bts_active)
-                       return -EOPNOTSUPP;
-
-               /* BTS is currently only allowed for user-mode. */
-               if (!attr->exclude_kernel)
-                       return -EOPNOTSUPP;
-
-               /* disallow bts if conflicting events are present */
-               if (x86_add_exclusive(x86_lbr_exclusive_lbr))
-                       return -EBUSY;
-
-               event->destroy = hw_perf_lbr_event_destroy;
-       }
-
        hwc->config |= config;
 
        return 0;
index 273c62e..ecc3e34 100644 (file)
@@ -2306,14 +2306,18 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status)
        return handled;
 }
 
-static bool disable_counter_freezing;
+static bool disable_counter_freezing = true;
 static int __init intel_perf_counter_freezing_setup(char *s)
 {
-       disable_counter_freezing = true;
-       pr_info("Intel PMU Counter freezing feature disabled\n");
+       bool res;
+
+       if (kstrtobool(s, &res))
+               return -EINVAL;
+
+       disable_counter_freezing = !res;
        return 1;
 }
-__setup("disable_counter_freezing", intel_perf_counter_freezing_setup);
+__setup("perf_v4_pmi=", intel_perf_counter_freezing_setup);
 
 /*
  * Simplified handler for Arch Perfmon v4:
@@ -2470,16 +2474,7 @@ done:
 static struct event_constraint *
 intel_bts_constraints(struct perf_event *event)
 {
-       struct hw_perf_event *hwc = &event->hw;
-       unsigned int hw_event, bts_event;
-
-       if (event->attr.freq)
-               return NULL;
-
-       hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
-       bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
-
-       if (unlikely(hw_event == bts_event && hwc->sample_period == 1))
+       if (unlikely(intel_pmu_has_bts(event)))
                return &bts_constraint;
 
        return NULL;
@@ -3098,10 +3093,51 @@ static unsigned long intel_pmu_large_pebs_flags(struct perf_event *event)
        return flags;
 }
 
+static int intel_pmu_bts_config(struct perf_event *event)
+{
+       struct perf_event_attr *attr = &event->attr;
+
+       if (unlikely(intel_pmu_has_bts(event))) {
+               /* BTS is not supported by this architecture. */
+               if (!x86_pmu.bts_active)
+                       return -EOPNOTSUPP;
+
+               /* BTS is currently only allowed for user-mode. */
+               if (!attr->exclude_kernel)
+                       return -EOPNOTSUPP;
+
+               /* BTS is not allowed for precise events. */
+               if (attr->precise_ip)
+                       return -EOPNOTSUPP;
+
+               /* disallow bts if conflicting events are present */
+               if (x86_add_exclusive(x86_lbr_exclusive_lbr))
+                       return -EBUSY;
+
+               event->destroy = hw_perf_lbr_event_destroy;
+       }
+
+       return 0;
+}
+
+static int core_pmu_hw_config(struct perf_event *event)
+{
+       int ret = x86_pmu_hw_config(event);
+
+       if (ret)
+               return ret;
+
+       return intel_pmu_bts_config(event);
+}
+
 static int intel_pmu_hw_config(struct perf_event *event)
 {
        int ret = x86_pmu_hw_config(event);
 
+       if (ret)
+               return ret;
+
+       ret = intel_pmu_bts_config(event);
        if (ret)
                return ret;
 
@@ -3127,7 +3163,7 @@ static int intel_pmu_hw_config(struct perf_event *event)
                /*
                 * BTS is set up earlier in this path, so don't account twice
                 */
-               if (!intel_pmu_has_bts(event)) {
+               if (!unlikely(intel_pmu_has_bts(event))) {
                        /* disallow lbr if conflicting events are present */
                        if (x86_add_exclusive(x86_lbr_exclusive_lbr))
                                return -EBUSY;
@@ -3596,7 +3632,7 @@ static __initconst const struct x86_pmu core_pmu = {
        .enable_all             = core_pmu_enable_all,
        .enable                 = core_pmu_enable_event,
        .disable                = x86_pmu_disable_event,
-       .hw_config              = x86_pmu_hw_config,
+       .hw_config              = core_pmu_hw_config,
        .schedule_events        = x86_schedule_events,
        .eventsel               = MSR_ARCH_PERFMON_EVENTSEL0,
        .perfctr                = MSR_ARCH_PERFMON_PERFCTR0,
index adae087..78d7b70 100644 (file)
@@ -859,11 +859,16 @@ static inline int amd_pmu_init(void)
 
 static inline bool intel_pmu_has_bts(struct perf_event *event)
 {
-       if (event->attr.config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
-           !event->attr.freq && event->hw.sample_period == 1)
-               return true;
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned int hw_event, bts_event;
+
+       if (event->attr.freq)
+               return false;
+
+       hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
+       bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
 
-       return false;
+       return hw_event == bts_event && hwc->sample_period == 1;
 }
 
 int intel_pmu_save_and_restart(struct perf_event *event);
index a07ffd2..f6f6ef4 100644 (file)
@@ -36,6 +36,7 @@ static void sanitize_boot_params(struct boot_params *boot_params)
         */
        if (boot_params->sentinel) {
                /* fields in boot_params are left uninitialized, clear them */
+               boot_params->acpi_rsdp_addr = 0;
                memset(&boot_params->ext_ramdisk_image, 0,
                       (char *)&boot_params->efi_info -
                        (char *)&boot_params->ext_ramdisk_image);
index 5f7290e..69dcdf1 100644 (file)
@@ -226,7 +226,7 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu)
                     "3: movl $-2,%[err]\n\t"                           \
                     "jmp 2b\n\t"                                       \
                     ".popsection\n\t"                                  \
-                    _ASM_EXTABLE_UA(1b, 3b)                            \
+                    _ASM_EXTABLE(1b, 3b)                               \
                     : [err] "=r" (err)                                 \
                     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)    \
                     : "memory")
index 80f4a4f..c8f73ef 100644 (file)
 
 #define MSR_IA32_SPEC_CTRL             0x00000048 /* Speculation Control */
 #define SPEC_CTRL_IBRS                 (1 << 0)   /* Indirect Branch Restricted Speculation */
-#define SPEC_CTRL_STIBP                        (1 << 1)   /* Single Thread Indirect Branch Predictors */
+#define SPEC_CTRL_STIBP_SHIFT          1          /* Single Thread Indirect Branch Predictor (STIBP) bit */
+#define SPEC_CTRL_STIBP                        (1 << SPEC_CTRL_STIBP_SHIFT)    /* STIBP mask */
 #define SPEC_CTRL_SSBD_SHIFT           2          /* Speculative Store Bypass Disable bit */
-#define SPEC_CTRL_SSBD                 (1 << SPEC_CTRL_SSBD_SHIFT)   /* Speculative Store Bypass Disable */
+#define SPEC_CTRL_SSBD                 (1 << SPEC_CTRL_SSBD_SHIFT)     /* Speculative Store Bypass Disable */
 
 #define MSR_IA32_PRED_CMD              0x00000049 /* Prediction Command */
 #define PRED_CMD_IBPB                  (1 << 0)   /* Indirect Branch Prediction Barrier */
index 80dc144..032b600 100644 (file)
@@ -3,6 +3,8 @@
 #ifndef _ASM_X86_NOSPEC_BRANCH_H_
 #define _ASM_X86_NOSPEC_BRANCH_H_
 
+#include <linux/static_key.h>
+
 #include <asm/alternative.h>
 #include <asm/alternative-asm.h>
 #include <asm/cpufeatures.h>
        _ASM_PTR " 999b\n\t"                                    \
        ".popsection\n\t"
 
-#if defined(CONFIG_X86_64) && defined(RETPOLINE)
+#ifdef CONFIG_RETPOLINE
+#ifdef CONFIG_X86_64
 
 /*
- * Since the inline asm uses the %V modifier which is only in newer GCC,
- * the 64-bit one is dependent on RETPOLINE not CONFIG_RETPOLINE.
+ * Inline asm uses the %V modifier which is only in newer GCC
+ * which is ensured when CONFIG_RETPOLINE is defined.
  */
 # define CALL_NOSPEC                                           \
        ANNOTATE_NOSPEC_ALTERNATIVE                             \
        X86_FEATURE_RETPOLINE_AMD)
 # define THUNK_TARGET(addr) [thunk_target] "r" (addr)
 
-#elif defined(CONFIG_X86_32) && defined(CONFIG_RETPOLINE)
+#else /* CONFIG_X86_32 */
 /*
  * For i386 we use the original ret-equivalent retpoline, because
  * otherwise we'll run out of registers. We don't care about CET
        X86_FEATURE_RETPOLINE_AMD)
 
 # define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
+#endif
 #else /* No retpoline for C / inline asm */
 # define CALL_NOSPEC "call *%[thunk_target]\n"
 # define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
 /* The Spectre V2 mitigation variants */
 enum spectre_v2_mitigation {
        SPECTRE_V2_NONE,
-       SPECTRE_V2_RETPOLINE_MINIMAL,
-       SPECTRE_V2_RETPOLINE_MINIMAL_AMD,
        SPECTRE_V2_RETPOLINE_GENERIC,
        SPECTRE_V2_RETPOLINE_AMD,
        SPECTRE_V2_IBRS_ENHANCED,
 };
 
+/* The indirect branch speculation control variants */
+enum spectre_v2_user_mitigation {
+       SPECTRE_V2_USER_NONE,
+       SPECTRE_V2_USER_STRICT,
+       SPECTRE_V2_USER_PRCTL,
+       SPECTRE_V2_USER_SECCOMP,
+};
+
 /* The Speculative Store Bypass disable variants */
 enum ssb_mitigation {
        SPEC_STORE_BYPASS_NONE,
@@ -303,6 +313,10 @@ do {                                                                       \
        preempt_enable();                                               \
 } while (0)
 
+DECLARE_STATIC_KEY_FALSE(switch_to_cond_stibp);
+DECLARE_STATIC_KEY_FALSE(switch_mm_cond_ibpb);
+DECLARE_STATIC_KEY_FALSE(switch_mm_always_ibpb);
+
 #endif /* __ASSEMBLY__ */
 
 /*
index ae7c2c5..5393bab 100644 (file)
@@ -53,12 +53,24 @@ static inline u64 ssbd_tif_to_spec_ctrl(u64 tifn)
        return (tifn & _TIF_SSBD) >> (TIF_SSBD - SPEC_CTRL_SSBD_SHIFT);
 }
 
+static inline u64 stibp_tif_to_spec_ctrl(u64 tifn)
+{
+       BUILD_BUG_ON(TIF_SPEC_IB < SPEC_CTRL_STIBP_SHIFT);
+       return (tifn & _TIF_SPEC_IB) >> (TIF_SPEC_IB - SPEC_CTRL_STIBP_SHIFT);
+}
+
 static inline unsigned long ssbd_spec_ctrl_to_tif(u64 spec_ctrl)
 {
        BUILD_BUG_ON(TIF_SSBD < SPEC_CTRL_SSBD_SHIFT);
        return (spec_ctrl & SPEC_CTRL_SSBD) << (TIF_SSBD - SPEC_CTRL_SSBD_SHIFT);
 }
 
+static inline unsigned long stibp_spec_ctrl_to_tif(u64 spec_ctrl)
+{
+       BUILD_BUG_ON(TIF_SPEC_IB < SPEC_CTRL_STIBP_SHIFT);
+       return (spec_ctrl & SPEC_CTRL_STIBP) << (TIF_SPEC_IB - SPEC_CTRL_STIBP_SHIFT);
+}
+
 static inline u64 ssbd_tif_to_amd_ls_cfg(u64 tifn)
 {
        return (tifn & _TIF_SSBD) ? x86_amd_ls_cfg_ssbd_mask : 0ULL;
@@ -70,11 +82,7 @@ extern void speculative_store_bypass_ht_init(void);
 static inline void speculative_store_bypass_ht_init(void) { }
 #endif
 
-extern void speculative_store_bypass_update(unsigned long tif);
-
-static inline void speculative_store_bypass_update_current(void)
-{
-       speculative_store_bypass_update(current_thread_info()->flags);
-}
+extern void speculation_ctrl_update(unsigned long tif);
+extern void speculation_ctrl_update_current(void);
 
 #endif
index 36bd243..7cf1a27 100644 (file)
@@ -11,9 +11,6 @@ struct task_struct *__switch_to_asm(struct task_struct *prev,
 
 __visible struct task_struct *__switch_to(struct task_struct *prev,
                                          struct task_struct *next);
-struct tss_struct;
-void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
-                     struct tss_struct *tss);
 
 /* This runs runs on the previous thread's stack. */
 static inline void prepare_switch_to(struct task_struct *next)
index 2ff2a30..82b73b7 100644 (file)
@@ -79,10 +79,12 @@ struct thread_info {
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_SINGLESTEP         4       /* reenable singlestep on user return*/
-#define TIF_SSBD                       5       /* Reduced data speculation */
+#define TIF_SSBD               5       /* Speculative store bypass disable */
 #define TIF_SYSCALL_EMU                6       /* syscall emulation active */
 #define TIF_SYSCALL_AUDIT      7       /* syscall auditing active */
 #define TIF_SECCOMP            8       /* secure computing */
+#define TIF_SPEC_IB            9       /* Indirect branch speculation mitigation */
+#define TIF_SPEC_FORCE_UPDATE  10      /* Force speculation MSR update in context switch */
 #define TIF_USER_RETURN_NOTIFY 11      /* notify kernel of userspace return */
 #define TIF_UPROBE             12      /* breakpointed or singlestepping */
 #define TIF_PATCH_PENDING      13      /* pending live patching update */
@@ -110,6 +112,8 @@ struct thread_info {
 #define _TIF_SYSCALL_EMU       (1 << TIF_SYSCALL_EMU)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
+#define _TIF_SPEC_IB           (1 << TIF_SPEC_IB)
+#define _TIF_SPEC_FORCE_UPDATE (1 << TIF_SPEC_FORCE_UPDATE)
 #define _TIF_USER_RETURN_NOTIFY        (1 << TIF_USER_RETURN_NOTIFY)
 #define _TIF_UPROBE            (1 << TIF_UPROBE)
 #define _TIF_PATCH_PENDING     (1 << TIF_PATCH_PENDING)
@@ -145,8 +149,18 @@ struct thread_info {
         _TIF_FSCHECK)
 
 /* flags to check in __switch_to() */
-#define _TIF_WORK_CTXSW                                                        \
-       (_TIF_IO_BITMAP|_TIF_NOCPUID|_TIF_NOTSC|_TIF_BLOCKSTEP|_TIF_SSBD)
+#define _TIF_WORK_CTXSW_BASE                                           \
+       (_TIF_IO_BITMAP|_TIF_NOCPUID|_TIF_NOTSC|_TIF_BLOCKSTEP|         \
+        _TIF_SSBD | _TIF_SPEC_FORCE_UPDATE)
+
+/*
+ * Avoid calls to __switch_to_xtra() on UP as STIBP is not evaluated.
+ */
+#ifdef CONFIG_SMP
+# define _TIF_WORK_CTXSW       (_TIF_WORK_CTXSW_BASE | _TIF_SPEC_IB)
+#else
+# define _TIF_WORK_CTXSW       (_TIF_WORK_CTXSW_BASE)
+#endif
 
 #define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY)
 #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)
index d760611..f4204bf 100644 (file)
@@ -169,10 +169,14 @@ struct tlb_state {
 
 #define LOADED_MM_SWITCHING ((struct mm_struct *)1)
 
+       /* Last user mm for optimizing IBPB */
+       union {
+               struct mm_struct        *last_user_mm;
+               unsigned long           last_user_mm_ibpb;
+       };
+
        u16 loaded_mm_asid;
        u16 next_asid;
-       /* last user mm's ctx id */
-       u64 last_ctx_id;
 
        /*
         * We can be in one of several states:
index 0f84210..b85a7c5 100644 (file)
@@ -303,6 +303,4 @@ extern void x86_init_noop(void);
 extern void x86_init_uint_noop(unsigned int unused);
 extern bool x86_pnpbios_disabled(void);
 
-void x86_verify_bootdata_version(void);
-
 #endif
index 22f89d0..60733f1 100644 (file)
@@ -16,9 +16,6 @@
 #define RAMDISK_PROMPT_FLAG            0x8000
 #define RAMDISK_LOAD_FLAG              0x4000
 
-/* version flags */
-#define VERSION_WRITTEN        0x8000
-
 /* loadflags */
 #define LOADED_HIGH    (1<<0)
 #define KASLR_FLAG     (1<<1)
@@ -89,7 +86,6 @@ struct setup_header {
        __u64   pref_address;
        __u32   init_size;
        __u32   handover_offset;
-       __u64   acpi_rsdp_addr;
 } __attribute__((packed));
 
 struct sys_desc_table {
@@ -159,7 +155,8 @@ struct boot_params {
        __u8  _pad2[4];                                 /* 0x054 */
        __u64  tboot_addr;                              /* 0x058 */
        struct ist_info ist_info;                       /* 0x060 */
-       __u8  _pad3[16];                                /* 0x070 */
+       __u64 acpi_rsdp_addr;                           /* 0x070 */
+       __u8  _pad3[8];                                 /* 0x078 */
        __u8  hd0_info[16];     /* obsolete! */         /* 0x080 */
        __u8  hd1_info[16];     /* obsolete! */         /* 0x090 */
        struct sys_desc_table sys_desc_table; /* obsolete! */   /* 0x0a0 */
index 92c76bf..06635fb 100644 (file)
@@ -1776,5 +1776,5 @@ void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size)
 
 u64 x86_default_get_root_pointer(void)
 {
-       return boot_params.hdr.acpi_rsdp_addr;
+       return boot_params.acpi_rsdp_addr;
 }
index c37e66e..500278f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/nospec.h>
 #include <linux/prctl.h>
+#include <linux/sched/smt.h>
 
 #include <asm/spec-ctrl.h>
 #include <asm/cmdline.h>
@@ -53,6 +54,13 @@ static u64 __ro_after_init x86_spec_ctrl_mask = SPEC_CTRL_IBRS;
 u64 __ro_after_init x86_amd_ls_cfg_base;
 u64 __ro_after_init x86_amd_ls_cfg_ssbd_mask;
 
+/* Control conditional STIPB in switch_to() */
+DEFINE_STATIC_KEY_FALSE(switch_to_cond_stibp);
+/* Control conditional IBPB in switch_mm() */
+DEFINE_STATIC_KEY_FALSE(switch_mm_cond_ibpb);
+/* Control unconditional IBPB in switch_mm() */
+DEFINE_STATIC_KEY_FALSE(switch_mm_always_ibpb);
+
 void __init check_bugs(void)
 {
        identify_boot_cpu();
@@ -123,31 +131,6 @@ void __init check_bugs(void)
 #endif
 }
 
-/* The kernel command line selection */
-enum spectre_v2_mitigation_cmd {
-       SPECTRE_V2_CMD_NONE,
-       SPECTRE_V2_CMD_AUTO,
-       SPECTRE_V2_CMD_FORCE,
-       SPECTRE_V2_CMD_RETPOLINE,
-       SPECTRE_V2_CMD_RETPOLINE_GENERIC,
-       SPECTRE_V2_CMD_RETPOLINE_AMD,
-};
-
-static const char *spectre_v2_strings[] = {
-       [SPECTRE_V2_NONE]                       = "Vulnerable",
-       [SPECTRE_V2_RETPOLINE_MINIMAL]          = "Vulnerable: Minimal generic ASM retpoline",
-       [SPECTRE_V2_RETPOLINE_MINIMAL_AMD]      = "Vulnerable: Minimal AMD ASM retpoline",
-       [SPECTRE_V2_RETPOLINE_GENERIC]          = "Mitigation: Full generic retpoline",
-       [SPECTRE_V2_RETPOLINE_AMD]              = "Mitigation: Full AMD retpoline",
-       [SPECTRE_V2_IBRS_ENHANCED]              = "Mitigation: Enhanced IBRS",
-};
-
-#undef pr_fmt
-#define pr_fmt(fmt)     "Spectre V2 : " fmt
-
-static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
-       SPECTRE_V2_NONE;
-
 void
 x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool setguest)
 {
@@ -169,6 +152,10 @@ x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool setguest)
                    static_cpu_has(X86_FEATURE_AMD_SSBD))
                        hostval |= ssbd_tif_to_spec_ctrl(ti->flags);
 
+               /* Conditional STIBP enabled? */
+               if (static_branch_unlikely(&switch_to_cond_stibp))
+                       hostval |= stibp_tif_to_spec_ctrl(ti->flags);
+
                if (hostval != guestval) {
                        msrval = setguest ? guestval : hostval;
                        wrmsrl(MSR_IA32_SPEC_CTRL, msrval);
@@ -202,7 +189,7 @@ x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool setguest)
                tif = setguest ? ssbd_spec_ctrl_to_tif(guestval) :
                                 ssbd_spec_ctrl_to_tif(hostval);
 
-               speculative_store_bypass_update(tif);
+               speculation_ctrl_update(tif);
        }
 }
 EXPORT_SYMBOL_GPL(x86_virt_spec_ctrl);
@@ -217,6 +204,15 @@ static void x86_amd_ssb_disable(void)
                wrmsrl(MSR_AMD64_LS_CFG, msrval);
 }
 
+#undef pr_fmt
+#define pr_fmt(fmt)     "Spectre V2 : " fmt
+
+static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
+       SPECTRE_V2_NONE;
+
+static enum spectre_v2_user_mitigation spectre_v2_user __ro_after_init =
+       SPECTRE_V2_USER_NONE;
+
 #ifdef RETPOLINE
 static bool spectre_v2_bad_module;
 
@@ -238,67 +234,217 @@ static inline const char *spectre_v2_module_string(void)
 static inline const char *spectre_v2_module_string(void) { return ""; }
 #endif
 
-static void __init spec2_print_if_insecure(const char *reason)
+static inline bool match_option(const char *arg, int arglen, const char *opt)
 {
-       if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
-               pr_info("%s selected on command line.\n", reason);
+       int len = strlen(opt);
+
+       return len == arglen && !strncmp(arg, opt, len);
 }
 
-static void __init spec2_print_if_secure(const char *reason)
+/* The kernel command line selection for spectre v2 */
+enum spectre_v2_mitigation_cmd {
+       SPECTRE_V2_CMD_NONE,
+       SPECTRE_V2_CMD_AUTO,
+       SPECTRE_V2_CMD_FORCE,
+       SPECTRE_V2_CMD_RETPOLINE,
+       SPECTRE_V2_CMD_RETPOLINE_GENERIC,
+       SPECTRE_V2_CMD_RETPOLINE_AMD,
+};
+
+enum spectre_v2_user_cmd {
+       SPECTRE_V2_USER_CMD_NONE,
+       SPECTRE_V2_USER_CMD_AUTO,
+       SPECTRE_V2_USER_CMD_FORCE,
+       SPECTRE_V2_USER_CMD_PRCTL,
+       SPECTRE_V2_USER_CMD_PRCTL_IBPB,
+       SPECTRE_V2_USER_CMD_SECCOMP,
+       SPECTRE_V2_USER_CMD_SECCOMP_IBPB,
+};
+
+static const char * const spectre_v2_user_strings[] = {
+       [SPECTRE_V2_USER_NONE]          = "User space: Vulnerable",
+       [SPECTRE_V2_USER_STRICT]        = "User space: Mitigation: STIBP protection",
+       [SPECTRE_V2_USER_PRCTL]         = "User space: Mitigation: STIBP via prctl",
+       [SPECTRE_V2_USER_SECCOMP]       = "User space: Mitigation: STIBP via seccomp and prctl",
+};
+
+static const struct {
+       const char                      *option;
+       enum spectre_v2_user_cmd        cmd;
+       bool                            secure;
+} v2_user_options[] __initdata = {
+       { "auto",               SPECTRE_V2_USER_CMD_AUTO,               false },
+       { "off",                SPECTRE_V2_USER_CMD_NONE,               false },
+       { "on",                 SPECTRE_V2_USER_CMD_FORCE,              true  },
+       { "prctl",              SPECTRE_V2_USER_CMD_PRCTL,              false },
+       { "prctl,ibpb",         SPECTRE_V2_USER_CMD_PRCTL_IBPB,         false },
+       { "seccomp",            SPECTRE_V2_USER_CMD_SECCOMP,            false },
+       { "seccomp,ibpb",       SPECTRE_V2_USER_CMD_SECCOMP_IBPB,       false },
+};
+
+static void __init spec_v2_user_print_cond(const char *reason, bool secure)
 {
-       if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
-               pr_info("%s selected on command line.\n", reason);
+       if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2) != secure)
+               pr_info("spectre_v2_user=%s forced on command line.\n", reason);
 }
 
-static inline bool retp_compiler(void)
+static enum spectre_v2_user_cmd __init
+spectre_v2_parse_user_cmdline(enum spectre_v2_mitigation_cmd v2_cmd)
 {
-       return __is_defined(RETPOLINE);
+       char arg[20];
+       int ret, i;
+
+       switch (v2_cmd) {
+       case SPECTRE_V2_CMD_NONE:
+               return SPECTRE_V2_USER_CMD_NONE;
+       case SPECTRE_V2_CMD_FORCE:
+               return SPECTRE_V2_USER_CMD_FORCE;
+       default:
+               break;
+       }
+
+       ret = cmdline_find_option(boot_command_line, "spectre_v2_user",
+                                 arg, sizeof(arg));
+       if (ret < 0)
+               return SPECTRE_V2_USER_CMD_AUTO;
+
+       for (i = 0; i < ARRAY_SIZE(v2_user_options); i++) {
+               if (match_option(arg, ret, v2_user_options[i].option)) {
+                       spec_v2_user_print_cond(v2_user_options[i].option,
+                                               v2_user_options[i].secure);
+                       return v2_user_options[i].cmd;
+               }
+       }
+
+       pr_err("Unknown user space protection option (%s). Switching to AUTO select\n", arg);
+       return SPECTRE_V2_USER_CMD_AUTO;
 }
 
-static inline bool match_option(const char *arg, int arglen, const char *opt)
+static void __init
+spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
 {
-       int len = strlen(opt);
+       enum spectre_v2_user_mitigation mode = SPECTRE_V2_USER_NONE;
+       bool smt_possible = IS_ENABLED(CONFIG_SMP);
+       enum spectre_v2_user_cmd cmd;
 
-       return len == arglen && !strncmp(arg, opt, len);
+       if (!boot_cpu_has(X86_FEATURE_IBPB) && !boot_cpu_has(X86_FEATURE_STIBP))
+               return;
+
+       if (cpu_smt_control == CPU_SMT_FORCE_DISABLED ||
+           cpu_smt_control == CPU_SMT_NOT_SUPPORTED)
+               smt_possible = false;
+
+       cmd = spectre_v2_parse_user_cmdline(v2_cmd);
+       switch (cmd) {
+       case SPECTRE_V2_USER_CMD_NONE:
+               goto set_mode;
+       case SPECTRE_V2_USER_CMD_FORCE:
+               mode = SPECTRE_V2_USER_STRICT;
+               break;
+       case SPECTRE_V2_USER_CMD_PRCTL:
+       case SPECTRE_V2_USER_CMD_PRCTL_IBPB:
+               mode = SPECTRE_V2_USER_PRCTL;
+               break;
+       case SPECTRE_V2_USER_CMD_AUTO:
+       case SPECTRE_V2_USER_CMD_SECCOMP:
+       case SPECTRE_V2_USER_CMD_SECCOMP_IBPB:
+               if (IS_ENABLED(CONFIG_SECCOMP))
+                       mode = SPECTRE_V2_USER_SECCOMP;
+               else
+                       mode = SPECTRE_V2_USER_PRCTL;
+               break;
+       }
+
+       /* Initialize Indirect Branch Prediction Barrier */
+       if (boot_cpu_has(X86_FEATURE_IBPB)) {
+               setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
+
+               switch (cmd) {
+               case SPECTRE_V2_USER_CMD_FORCE:
+               case SPECTRE_V2_USER_CMD_PRCTL_IBPB:
+               case SPECTRE_V2_USER_CMD_SECCOMP_IBPB:
+                       static_branch_enable(&switch_mm_always_ibpb);
+                       break;
+               case SPECTRE_V2_USER_CMD_PRCTL:
+               case SPECTRE_V2_USER_CMD_AUTO:
+               case SPECTRE_V2_USER_CMD_SECCOMP:
+                       static_branch_enable(&switch_mm_cond_ibpb);
+                       break;
+               default:
+                       break;
+               }
+
+               pr_info("mitigation: Enabling %s Indirect Branch Prediction Barrier\n",
+                       static_key_enabled(&switch_mm_always_ibpb) ?
+                       "always-on" : "conditional");
+       }
+
+       /* If enhanced IBRS is enabled no STIPB required */
+       if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
+               return;
+
+       /*
+        * If SMT is not possible or STIBP is not available clear the STIPB
+        * mode.
+        */
+       if (!smt_possible || !boot_cpu_has(X86_FEATURE_STIBP))
+               mode = SPECTRE_V2_USER_NONE;
+set_mode:
+       spectre_v2_user = mode;
+       /* Only print the STIBP mode when SMT possible */
+       if (smt_possible)
+               pr_info("%s\n", spectre_v2_user_strings[mode]);
 }
 
+static const char * const spectre_v2_strings[] = {
+       [SPECTRE_V2_NONE]                       = "Vulnerable",
+       [SPECTRE_V2_RETPOLINE_GENERIC]          = "Mitigation: Full generic retpoline",
+       [SPECTRE_V2_RETPOLINE_AMD]              = "Mitigation: Full AMD retpoline",
+       [SPECTRE_V2_IBRS_ENHANCED]              = "Mitigation: Enhanced IBRS",
+};
+
 static const struct {
        const char *option;
        enum spectre_v2_mitigation_cmd cmd;
        bool secure;
-} mitigation_options[] = {
-       { "off",               SPECTRE_V2_CMD_NONE,              false },
-       { "on",                SPECTRE_V2_CMD_FORCE,             true },
-       { "retpoline",         SPECTRE_V2_CMD_RETPOLINE,         false },
-       { "retpoline,amd",     SPECTRE_V2_CMD_RETPOLINE_AMD,     false },
-       { "retpoline,generic", SPECTRE_V2_CMD_RETPOLINE_GENERIC, false },
-       { "auto",              SPECTRE_V2_CMD_AUTO,              false },
+} mitigation_options[] __initdata = {
+       { "off",                SPECTRE_V2_CMD_NONE,              false },
+       { "on",                 SPECTRE_V2_CMD_FORCE,             true  },
+       { "retpoline",          SPECTRE_V2_CMD_RETPOLINE,         false },
+       { "retpoline,amd",      SPECTRE_V2_CMD_RETPOLINE_AMD,     false },
+       { "retpoline,generic",  SPECTRE_V2_CMD_RETPOLINE_GENERIC, false },
+       { "auto",               SPECTRE_V2_CMD_AUTO,              false },
 };
 
+static void __init spec_v2_print_cond(const char *reason, bool secure)
+{
+       if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2) != secure)
+               pr_info("%s selected on command line.\n", reason);
+}
+
 static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
 {
+       enum spectre_v2_mitigation_cmd cmd = SPECTRE_V2_CMD_AUTO;
        char arg[20];
        int ret, i;
-       enum spectre_v2_mitigation_cmd cmd = SPECTRE_V2_CMD_AUTO;
 
        if (cmdline_find_option_bool(boot_command_line, "nospectre_v2"))
                return SPECTRE_V2_CMD_NONE;
-       else {
-               ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg));
-               if (ret < 0)
-                       return SPECTRE_V2_CMD_AUTO;
 
-               for (i = 0; i < ARRAY_SIZE(mitigation_options); i++) {
-                       if (!match_option(arg, ret, mitigation_options[i].option))
-                               continue;
-                       cmd = mitigation_options[i].cmd;
-                       break;
-               }
+       ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg));
+       if (ret < 0)
+               return SPECTRE_V2_CMD_AUTO;
 
-               if (i >= ARRAY_SIZE(mitigation_options)) {
-                       pr_err("unknown option (%s). Switching to AUTO select\n", arg);
-                       return SPECTRE_V2_CMD_AUTO;
-               }
+       for (i = 0; i < ARRAY_SIZE(mitigation_options); i++) {
+               if (!match_option(arg, ret, mitigation_options[i].option))
+                       continue;
+               cmd = mitigation_options[i].cmd;
+               break;
+       }
+
+       if (i >= ARRAY_SIZE(mitigation_options)) {
+               pr_err("unknown option (%s). Switching to AUTO select\n", arg);
+               return SPECTRE_V2_CMD_AUTO;
        }
 
        if ((cmd == SPECTRE_V2_CMD_RETPOLINE ||
@@ -316,54 +462,11 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
                return SPECTRE_V2_CMD_AUTO;
        }
 
-       if (mitigation_options[i].secure)
-               spec2_print_if_secure(mitigation_options[i].option);
-       else
-               spec2_print_if_insecure(mitigation_options[i].option);
-
+       spec_v2_print_cond(mitigation_options[i].option,
+                          mitigation_options[i].secure);
        return cmd;
 }
 
-static bool stibp_needed(void)
-{
-       if (spectre_v2_enabled == SPECTRE_V2_NONE)
-               return false;
-
-       if (!boot_cpu_has(X86_FEATURE_STIBP))
-               return false;
-
-       return true;
-}
-
-static void update_stibp_msr(void *info)
-{
-       wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
-}
-
-void arch_smt_update(void)
-{
-       u64 mask;
-
-       if (!stibp_needed())
-               return;
-
-       mutex_lock(&spec_ctrl_mutex);
-       mask = x86_spec_ctrl_base;
-       if (cpu_smt_control == CPU_SMT_ENABLED)
-               mask |= SPEC_CTRL_STIBP;
-       else
-               mask &= ~SPEC_CTRL_STIBP;
-
-       if (mask != x86_spec_ctrl_base) {
-               pr_info("Spectre v2 cross-process SMT mitigation: %s STIBP\n",
-                               cpu_smt_control == CPU_SMT_ENABLED ?
-                               "Enabling" : "Disabling");
-               x86_spec_ctrl_base = mask;
-               on_each_cpu(update_stibp_msr, NULL, 1);
-       }
-       mutex_unlock(&spec_ctrl_mutex);
-}
-
 static void __init spectre_v2_select_mitigation(void)
 {
        enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
@@ -417,14 +520,12 @@ retpoline_auto:
                        pr_err("Spectre mitigation: LFENCE not serializing, switching to generic retpoline\n");
                        goto retpoline_generic;
                }
-               mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_AMD :
-                                        SPECTRE_V2_RETPOLINE_MINIMAL_AMD;
+               mode = SPECTRE_V2_RETPOLINE_AMD;
                setup_force_cpu_cap(X86_FEATURE_RETPOLINE_AMD);
                setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
        } else {
        retpoline_generic:
-               mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_GENERIC :
-                                        SPECTRE_V2_RETPOLINE_MINIMAL;
+               mode = SPECTRE_V2_RETPOLINE_GENERIC;
                setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
        }
 
@@ -443,12 +544,6 @@ specv2_set_mode:
        setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
        pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n");
 
-       /* Initialize Indirect Branch Prediction Barrier if supported */
-       if (boot_cpu_has(X86_FEATURE_IBPB)) {
-               setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
-               pr_info("Spectre v2 mitigation: Enabling Indirect Branch Prediction Barrier\n");
-       }
-
        /*
         * Retpoline means the kernel is safe because it has no indirect
         * branches. Enhanced IBRS protects firmware too, so, enable restricted
@@ -465,10 +560,67 @@ specv2_set_mode:
                pr_info("Enabling Restricted Speculation for firmware calls\n");
        }
 
+       /* Set up IBPB and STIBP depending on the general spectre V2 command */
+       spectre_v2_user_select_mitigation(cmd);
+
        /* Enable STIBP if appropriate */
        arch_smt_update();
 }
 
+static void update_stibp_msr(void * __unused)
+{
+       wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+}
+
+/* Update x86_spec_ctrl_base in case SMT state changed. */
+static void update_stibp_strict(void)
+{
+       u64 mask = x86_spec_ctrl_base & ~SPEC_CTRL_STIBP;
+
+       if (sched_smt_active())
+               mask |= SPEC_CTRL_STIBP;
+
+       if (mask == x86_spec_ctrl_base)
+               return;
+
+       pr_info("Update user space SMT mitigation: STIBP %s\n",
+               mask & SPEC_CTRL_STIBP ? "always-on" : "off");
+       x86_spec_ctrl_base = mask;
+       on_each_cpu(update_stibp_msr, NULL, 1);
+}
+
+/* Update the static key controlling the evaluation of TIF_SPEC_IB */
+static void update_indir_branch_cond(void)
+{
+       if (sched_smt_active())
+               static_branch_enable(&switch_to_cond_stibp);
+       else
+               static_branch_disable(&switch_to_cond_stibp);
+}
+
+void arch_smt_update(void)
+{
+       /* Enhanced IBRS implies STIBP. No update required. */
+       if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
+               return;
+
+       mutex_lock(&spec_ctrl_mutex);
+
+       switch (spectre_v2_user) {
+       case SPECTRE_V2_USER_NONE:
+               break;
+       case SPECTRE_V2_USER_STRICT:
+               update_stibp_strict();
+               break;
+       case SPECTRE_V2_USER_PRCTL:
+       case SPECTRE_V2_USER_SECCOMP:
+               update_indir_branch_cond();
+               break;
+       }
+
+       mutex_unlock(&spec_ctrl_mutex);
+}
+
 #undef pr_fmt
 #define pr_fmt(fmt)    "Speculative Store Bypass: " fmt
 
@@ -483,7 +635,7 @@ enum ssb_mitigation_cmd {
        SPEC_STORE_BYPASS_CMD_SECCOMP,
 };
 
-static const char *ssb_strings[] = {
+static const char * const ssb_strings[] = {
        [SPEC_STORE_BYPASS_NONE]        = "Vulnerable",
        [SPEC_STORE_BYPASS_DISABLE]     = "Mitigation: Speculative Store Bypass disabled",
        [SPEC_STORE_BYPASS_PRCTL]       = "Mitigation: Speculative Store Bypass disabled via prctl",
@@ -493,7 +645,7 @@ static const char *ssb_strings[] = {
 static const struct {
        const char *option;
        enum ssb_mitigation_cmd cmd;
-} ssb_mitigation_options[] = {
+} ssb_mitigation_options[]  __initdata = {
        { "auto",       SPEC_STORE_BYPASS_CMD_AUTO },    /* Platform decides */
        { "on",         SPEC_STORE_BYPASS_CMD_ON },      /* Disable Speculative Store Bypass */
        { "off",        SPEC_STORE_BYPASS_CMD_NONE },    /* Don't touch Speculative Store Bypass */
@@ -604,10 +756,25 @@ static void ssb_select_mitigation(void)
 #undef pr_fmt
 #define pr_fmt(fmt)     "Speculation prctl: " fmt
 
-static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
+static void task_update_spec_tif(struct task_struct *tsk)
 {
-       bool update;
+       /* Force the update of the real TIF bits */
+       set_tsk_thread_flag(tsk, TIF_SPEC_FORCE_UPDATE);
 
+       /*
+        * Immediately update the speculation control MSRs for the current
+        * task, but for a non-current task delay setting the CPU
+        * mitigation until it is scheduled next.
+        *
+        * This can only happen for SECCOMP mitigation. For PRCTL it's
+        * always the current task.
+        */
+       if (tsk == current)
+               speculation_ctrl_update_current();
+}
+
+static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
+{
        if (ssb_mode != SPEC_STORE_BYPASS_PRCTL &&
            ssb_mode != SPEC_STORE_BYPASS_SECCOMP)
                return -ENXIO;
@@ -618,28 +785,56 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
                if (task_spec_ssb_force_disable(task))
                        return -EPERM;
                task_clear_spec_ssb_disable(task);
-               update = test_and_clear_tsk_thread_flag(task, TIF_SSBD);
+               task_update_spec_tif(task);
                break;
        case PR_SPEC_DISABLE:
                task_set_spec_ssb_disable(task);
-               update = !test_and_set_tsk_thread_flag(task, TIF_SSBD);
+               task_update_spec_tif(task);
                break;
        case PR_SPEC_FORCE_DISABLE:
                task_set_spec_ssb_disable(task);
                task_set_spec_ssb_force_disable(task);
-               update = !test_and_set_tsk_thread_flag(task, TIF_SSBD);
+               task_update_spec_tif(task);
                break;
        default:
                return -ERANGE;
        }
+       return 0;
+}
 
-       /*
-        * If being set on non-current task, delay setting the CPU
-        * mitigation until it is next scheduled.
-        */
-       if (task == current && update)
-               speculative_store_bypass_update_current();
-
+static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
+{
+       switch (ctrl) {
+       case PR_SPEC_ENABLE:
+               if (spectre_v2_user == SPECTRE_V2_USER_NONE)
+                       return 0;
+               /*
+                * Indirect branch speculation is always disabled in strict
+                * mode.
+                */
+               if (spectre_v2_user == SPECTRE_V2_USER_STRICT)
+                       return -EPERM;
+               task_clear_spec_ib_disable(task);
+               task_update_spec_tif(task);
+               break;
+       case PR_SPEC_DISABLE:
+       case PR_SPEC_FORCE_DISABLE:
+               /*
+                * Indirect branch speculation is always allowed when
+                * mitigation is force disabled.
+                */
+               if (spectre_v2_user == SPECTRE_V2_USER_NONE)
+                       return -EPERM;
+               if (spectre_v2_user == SPECTRE_V2_USER_STRICT)
+                       return 0;
+               task_set_spec_ib_disable(task);
+               if (ctrl == PR_SPEC_FORCE_DISABLE)
+                       task_set_spec_ib_force_disable(task);
+               task_update_spec_tif(task);
+               break;
+       default:
+               return -ERANGE;
+       }
        return 0;
 }
 
@@ -649,6 +844,8 @@ int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
        switch (which) {
        case PR_SPEC_STORE_BYPASS:
                return ssb_prctl_set(task, ctrl);
+       case PR_SPEC_INDIRECT_BRANCH:
+               return ib_prctl_set(task, ctrl);
        default:
                return -ENODEV;
        }
@@ -659,6 +856,8 @@ void arch_seccomp_spec_mitigate(struct task_struct *task)
 {
        if (ssb_mode == SPEC_STORE_BYPASS_SECCOMP)
                ssb_prctl_set(task, PR_SPEC_FORCE_DISABLE);
+       if (spectre_v2_user == SPECTRE_V2_USER_SECCOMP)
+               ib_prctl_set(task, PR_SPEC_FORCE_DISABLE);
 }
 #endif
 
@@ -681,11 +880,35 @@ static int ssb_prctl_get(struct task_struct *task)
        }
 }
 
+static int ib_prctl_get(struct task_struct *task)
+{
+       if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
+               return PR_SPEC_NOT_AFFECTED;
+
+       switch (spectre_v2_user) {
+       case SPECTRE_V2_USER_NONE:
+               return PR_SPEC_ENABLE;
+       case SPECTRE_V2_USER_PRCTL:
+       case SPECTRE_V2_USER_SECCOMP:
+               if (task_spec_ib_force_disable(task))
+                       return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
+               if (task_spec_ib_disable(task))
+                       return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
+               return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
+       case SPECTRE_V2_USER_STRICT:
+               return PR_SPEC_DISABLE;
+       default:
+               return PR_SPEC_NOT_AFFECTED;
+       }
+}
+
 int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
 {
        switch (which) {
        case PR_SPEC_STORE_BYPASS:
                return ssb_prctl_get(task);
+       case PR_SPEC_INDIRECT_BRANCH:
+               return ib_prctl_get(task);
        default:
                return -ENODEV;
        }
@@ -823,7 +1046,7 @@ early_param("l1tf", l1tf_cmdline);
 #define L1TF_DEFAULT_MSG "Mitigation: PTE Inversion"
 
 #if IS_ENABLED(CONFIG_KVM_INTEL)
-static const char *l1tf_vmx_states[] = {
+static const char * const l1tf_vmx_states[] = {
        [VMENTER_L1D_FLUSH_AUTO]                = "auto",
        [VMENTER_L1D_FLUSH_NEVER]               = "vulnerable",
        [VMENTER_L1D_FLUSH_COND]                = "conditional cache flushes",
@@ -839,13 +1062,14 @@ static ssize_t l1tf_show_state(char *buf)
 
        if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_EPT_DISABLED ||
            (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER &&
-            cpu_smt_control == CPU_SMT_ENABLED))
+            sched_smt_active())) {
                return sprintf(buf, "%s; VMX: %s\n", L1TF_DEFAULT_MSG,
                               l1tf_vmx_states[l1tf_vmx_mitigation]);
+       }
 
        return sprintf(buf, "%s; VMX: %s, SMT %s\n", L1TF_DEFAULT_MSG,
                       l1tf_vmx_states[l1tf_vmx_mitigation],
-                      cpu_smt_control == CPU_SMT_ENABLED ? "vulnerable" : "disabled");
+                      sched_smt_active() ? "vulnerable" : "disabled");
 }
 #else
 static ssize_t l1tf_show_state(char *buf)
@@ -854,11 +1078,39 @@ static ssize_t l1tf_show_state(char *buf)
 }
 #endif
 
+static char *stibp_state(void)
+{
+       if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
+               return "";
+
+       switch (spectre_v2_user) {
+       case SPECTRE_V2_USER_NONE:
+               return ", STIBP: disabled";
+       case SPECTRE_V2_USER_STRICT:
+               return ", STIBP: forced";
+       case SPECTRE_V2_USER_PRCTL:
+       case SPECTRE_V2_USER_SECCOMP:
+               if (static_key_enabled(&switch_to_cond_stibp))
+                       return ", STIBP: conditional";
+       }
+       return "";
+}
+
+static char *ibpb_state(void)
+{
+       if (boot_cpu_has(X86_FEATURE_IBPB)) {
+               if (static_key_enabled(&switch_mm_always_ibpb))
+                       return ", IBPB: always-on";
+               if (static_key_enabled(&switch_mm_cond_ibpb))
+                       return ", IBPB: conditional";
+               return ", IBPB: disabled";
+       }
+       return "";
+}
+
 static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
                               char *buf, unsigned int bug)
 {
-       int ret;
-
        if (!boot_cpu_has_bug(bug))
                return sprintf(buf, "Not affected\n");
 
@@ -876,13 +1128,12 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
                return sprintf(buf, "Mitigation: __user pointer sanitization\n");
 
        case X86_BUG_SPECTRE_V2:
-               ret = sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
-                              boot_cpu_has(X86_FEATURE_USE_IBPB) ? ", IBPB" : "",
+               return sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
+                              ibpb_state(),
                               boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
-                              (x86_spec_ctrl_base & SPEC_CTRL_STIBP) ? ", STIBP" : "",
+                              stibp_state(),
                               boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
                               spectre_v2_module_string());
-               return ret;
 
        case X86_BUG_SPEC_STORE_BYPASS:
                return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
index dd33c35..e12454e 100644 (file)
@@ -56,7 +56,7 @@
 /* Threshold LVT offset is at MSR0xC0000410[15:12] */
 #define SMCA_THR_LVT_OFF       0xF000
 
-static bool thresholding_en;
+static bool thresholding_irq_en;
 
 static const char * const th_names[] = {
        "load_store",
@@ -534,9 +534,8 @@ prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr,
 
 set_offset:
        offset = setup_APIC_mce_threshold(offset, new);
-
-       if ((offset == new) && (mce_threshold_vector != amd_threshold_interrupt))
-               mce_threshold_vector = amd_threshold_interrupt;
+       if (offset == new)
+               thresholding_irq_en = true;
 
 done:
        mce_threshold_block_init(&b, offset);
@@ -1357,9 +1356,6 @@ int mce_threshold_remove_device(unsigned int cpu)
 {
        unsigned int bank;
 
-       if (!thresholding_en)
-               return 0;
-
        for (bank = 0; bank < mca_cfg.banks; ++bank) {
                if (!(per_cpu(bank_map, cpu) & (1 << bank)))
                        continue;
@@ -1377,9 +1373,6 @@ int mce_threshold_create_device(unsigned int cpu)
        struct threshold_bank **bp;
        int err = 0;
 
-       if (!thresholding_en)
-               return 0;
-
        bp = per_cpu(threshold_banks, cpu);
        if (bp)
                return 0;
@@ -1408,9 +1401,6 @@ static __init int threshold_init_device(void)
 {
        unsigned lcpu = 0;
 
-       if (mce_threshold_vector == amd_threshold_interrupt)
-               thresholding_en = true;
-
        /* to hit CPUs online before the notifier is up */
        for_each_online_cpu(lcpu) {
                int err = mce_threshold_create_device(lcpu);
@@ -1419,6 +1409,9 @@ static __init int threshold_init_device(void)
                        return err;
        }
 
+       if (thresholding_irq_en)
+               mce_threshold_vector = amd_threshold_interrupt;
+
        return 0;
 }
 /*
index 61a949d..d99a8ee 100644 (file)
@@ -344,10 +344,10 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
                        sanitize_restored_xstate(tsk, &env, xfeatures, fx_only);
                }
 
+               local_bh_disable();
                fpu->initialized = 1;
-               preempt_disable();
                fpu__restore(fpu);
-               preempt_enable();
+               local_bh_enable();
 
                return err;
        } else {
index 01ebcb6..7ee8067 100644 (file)
@@ -994,7 +994,6 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
 {
        unsigned long old;
        int faulted;
-       struct ftrace_graph_ent trace;
        unsigned long return_hooker = (unsigned long)
                                &return_to_handler;
 
@@ -1046,19 +1045,7 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
                return;
        }
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace)) {
+       if (function_graph_enter(old, self_addr, frame_pointer, parent))
                *parent = old;
-               return;
-       }
-
-       if (ftrace_push_return_trace(old, self_addr, &trace.depth,
-                                    frame_pointer, parent) == -EBUSY) {
-               *parent = old;
-               return;
-       }
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
index 76fa3b8..ec6fefb 100644 (file)
@@ -37,7 +37,6 @@ asmlinkage __visible void __init i386_start_kernel(void)
        cr4_init_shadow();
 
        sanitize_boot_params(&boot_params);
-       x86_verify_bootdata_version();
 
        x86_early_init_platform_quirks();
 
index 7663a8e..16b1cbd 100644 (file)
@@ -457,8 +457,6 @@ void __init x86_64_start_reservations(char *real_mode_data)
        if (!boot_params.hdr.version)
                copy_bootdata(__va(real_mode_data));
 
-       x86_verify_bootdata_version();
-
        x86_early_init_platform_quirks();
 
        switch (boot_params.hdr.hardware_subarch) {
index 40b16b2..6adf6e6 100644 (file)
@@ -189,7 +189,7 @@ static int copy_optimized_instructions(u8 *dest, u8 *src, u8 *real)
        int len = 0, ret;
 
        while (len < RELATIVEJUMP_SIZE) {
-               ret = __copy_instruction(dest + len, src + len, real, &insn);
+               ret = __copy_instruction(dest + len, src + len, real + len, &insn);
                if (!ret || !can_boost(&insn, src + len))
                        return -EINVAL;
                len += ret;
index c93fcfd..7d31192 100644 (file)
@@ -40,6 +40,8 @@
 #include <asm/prctl.h>
 #include <asm/spec-ctrl.h>
 
+#include "process.h"
+
 /*
  * per-CPU TSS segments. Threads are completely 'soft' on Linux,
  * no more per-task TSS's. The TSS size is kept cacheline-aligned
@@ -252,11 +254,12 @@ void arch_setup_new_exec(void)
                enable_cpuid();
 }
 
-static inline void switch_to_bitmap(struct tss_struct *tss,
-                                   struct thread_struct *prev,
+static inline void switch_to_bitmap(struct thread_struct *prev,
                                    struct thread_struct *next,
                                    unsigned long tifp, unsigned long tifn)
 {
+       struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw);
+
        if (tifn & _TIF_IO_BITMAP) {
                /*
                 * Copy the relevant range of the IO bitmap.
@@ -395,32 +398,85 @@ static __always_inline void amd_set_ssb_virt_state(unsigned long tifn)
        wrmsrl(MSR_AMD64_VIRT_SPEC_CTRL, ssbd_tif_to_spec_ctrl(tifn));
 }
 
-static __always_inline void intel_set_ssb_state(unsigned long tifn)
+/*
+ * Update the MSRs managing speculation control, during context switch.
+ *
+ * tifp: Previous task's thread flags
+ * tifn: Next task's thread flags
+ */
+static __always_inline void __speculation_ctrl_update(unsigned long tifp,
+                                                     unsigned long tifn)
 {
-       u64 msr = x86_spec_ctrl_base | ssbd_tif_to_spec_ctrl(tifn);
+       unsigned long tif_diff = tifp ^ tifn;
+       u64 msr = x86_spec_ctrl_base;
+       bool updmsr = false;
+
+       /*
+        * If TIF_SSBD is different, select the proper mitigation
+        * method. Note that if SSBD mitigation is disabled or permanentely
+        * enabled this branch can't be taken because nothing can set
+        * TIF_SSBD.
+        */
+       if (tif_diff & _TIF_SSBD) {
+               if (static_cpu_has(X86_FEATURE_VIRT_SSBD)) {
+                       amd_set_ssb_virt_state(tifn);
+               } else if (static_cpu_has(X86_FEATURE_LS_CFG_SSBD)) {
+                       amd_set_core_ssb_state(tifn);
+               } else if (static_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
+                          static_cpu_has(X86_FEATURE_AMD_SSBD)) {
+                       msr |= ssbd_tif_to_spec_ctrl(tifn);
+                       updmsr  = true;
+               }
+       }
+
+       /*
+        * Only evaluate TIF_SPEC_IB if conditional STIBP is enabled,
+        * otherwise avoid the MSR write.
+        */
+       if (IS_ENABLED(CONFIG_SMP) &&
+           static_branch_unlikely(&switch_to_cond_stibp)) {
+               updmsr |= !!(tif_diff & _TIF_SPEC_IB);
+               msr |= stibp_tif_to_spec_ctrl(tifn);
+       }
 
-       wrmsrl(MSR_IA32_SPEC_CTRL, msr);
+       if (updmsr)
+               wrmsrl(MSR_IA32_SPEC_CTRL, msr);
 }
 
-static __always_inline void __speculative_store_bypass_update(unsigned long tifn)
+static unsigned long speculation_ctrl_update_tif(struct task_struct *tsk)
 {
-       if (static_cpu_has(X86_FEATURE_VIRT_SSBD))
-               amd_set_ssb_virt_state(tifn);
-       else if (static_cpu_has(X86_FEATURE_LS_CFG_SSBD))
-               amd_set_core_ssb_state(tifn);
-       else
-               intel_set_ssb_state(tifn);
+       if (test_and_clear_tsk_thread_flag(tsk, TIF_SPEC_FORCE_UPDATE)) {
+               if (task_spec_ssb_disable(tsk))
+                       set_tsk_thread_flag(tsk, TIF_SSBD);
+               else
+                       clear_tsk_thread_flag(tsk, TIF_SSBD);
+
+               if (task_spec_ib_disable(tsk))
+                       set_tsk_thread_flag(tsk, TIF_SPEC_IB);
+               else
+                       clear_tsk_thread_flag(tsk, TIF_SPEC_IB);
+       }
+       /* Return the updated threadinfo flags*/
+       return task_thread_info(tsk)->flags;
 }
 
-void speculative_store_bypass_update(unsigned long tif)
+void speculation_ctrl_update(unsigned long tif)
 {
+       /* Forced update. Make sure all relevant TIF flags are different */
        preempt_disable();
-       __speculative_store_bypass_update(tif);
+       __speculation_ctrl_update(~tif, tif);
        preempt_enable();
 }
 
-void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
-                     struct tss_struct *tss)
+/* Called from seccomp/prctl update */
+void speculation_ctrl_update_current(void)
+{
+       preempt_disable();
+       speculation_ctrl_update(speculation_ctrl_update_tif(current));
+       preempt_enable();
+}
+
+void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
 {
        struct thread_struct *prev, *next;
        unsigned long tifp, tifn;
@@ -430,7 +486,7 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
 
        tifn = READ_ONCE(task_thread_info(next_p)->flags);
        tifp = READ_ONCE(task_thread_info(prev_p)->flags);
-       switch_to_bitmap(tss, prev, next, tifp, tifn);
+       switch_to_bitmap(prev, next, tifp, tifn);
 
        propagate_user_return_notify(prev_p, next_p);
 
@@ -451,8 +507,15 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
        if ((tifp ^ tifn) & _TIF_NOCPUID)
                set_cpuid_faulting(!!(tifn & _TIF_NOCPUID));
 
-       if ((tifp ^ tifn) & _TIF_SSBD)
-               __speculative_store_bypass_update(tifn);
+       if (likely(!((tifp | tifn) & _TIF_SPEC_FORCE_UPDATE))) {
+               __speculation_ctrl_update(tifp, tifn);
+       } else {
+               speculation_ctrl_update_tif(prev_p);
+               tifn = speculation_ctrl_update_tif(next_p);
+
+               /* Enforce MSR update to ensure consistent state */
+               __speculation_ctrl_update(~tifn, tifn);
+       }
 }
 
 /*
diff --git a/arch/x86/kernel/process.h b/arch/x86/kernel/process.h
new file mode 100644 (file)
index 0000000..898e97c
--- /dev/null
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Code shared between 32 and 64 bit
+
+#include <asm/spec-ctrl.h>
+
+void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p);
+
+/*
+ * This needs to be inline to optimize for the common case where no extra
+ * work needs to be done.
+ */
+static inline void switch_to_extra(struct task_struct *prev,
+                                  struct task_struct *next)
+{
+       unsigned long next_tif = task_thread_info(next)->flags;
+       unsigned long prev_tif = task_thread_info(prev)->flags;
+
+       if (IS_ENABLED(CONFIG_SMP)) {
+               /*
+                * Avoid __switch_to_xtra() invocation when conditional
+                * STIPB is disabled and the only different bit is
+                * TIF_SPEC_IB. For CONFIG_SMP=n TIF_SPEC_IB is not
+                * in the TIF_WORK_CTXSW masks.
+                */
+               if (!static_branch_likely(&switch_to_cond_stibp)) {
+                       prev_tif &= ~_TIF_SPEC_IB;
+                       next_tif &= ~_TIF_SPEC_IB;
+               }
+       }
+
+       /*
+        * __switch_to_xtra() handles debug registers, i/o bitmaps,
+        * speculation mitigations etc.
+        */
+       if (unlikely(next_tif & _TIF_WORK_CTXSW_NEXT ||
+                    prev_tif & _TIF_WORK_CTXSW_PREV))
+               __switch_to_xtra(prev, next);
+}
index 5046a3c..d3e593e 100644 (file)
@@ -59,6 +59,8 @@
 #include <asm/intel_rdt_sched.h>
 #include <asm/proto.h>
 
+#include "process.h"
+
 void __show_regs(struct pt_regs *regs, enum show_regs_mode mode)
 {
        unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
@@ -232,7 +234,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        struct fpu *prev_fpu = &prev->fpu;
        struct fpu *next_fpu = &next->fpu;
        int cpu = smp_processor_id();
-       struct tss_struct *tss = &per_cpu(cpu_tss_rw, cpu);
 
        /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
 
@@ -264,12 +265,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        if (get_kernel_rpl() && unlikely(prev->iopl != next->iopl))
                set_iopl_mask(next->iopl);
 
-       /*
-        * Now maybe handle debug registers and/or IO bitmaps
-        */
-       if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV ||
-                    task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
-               __switch_to_xtra(prev_p, next_p, tss);
+       switch_to_extra(prev_p, next_p);
 
        /*
         * Leave lazy mode, flushing any hypercalls made here.
index 0e0b428..bbfbf01 100644 (file)
@@ -60,6 +60,8 @@
 #include <asm/unistd_32_ia32.h>
 #endif
 
+#include "process.h"
+
 /* Prints also some state that isn't saved in the pt_regs */
 void __show_regs(struct pt_regs *regs, enum show_regs_mode mode)
 {
@@ -553,7 +555,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        struct fpu *prev_fpu = &prev->fpu;
        struct fpu *next_fpu = &next->fpu;
        int cpu = smp_processor_id();
-       struct tss_struct *tss = &per_cpu(cpu_tss_rw, cpu);
 
        WARN_ON_ONCE(IS_ENABLED(CONFIG_DEBUG_ENTRY) &&
                     this_cpu_read(irq_count) != -1);
@@ -617,12 +618,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        /* Reload sp0. */
        update_task_stack(next_p);
 
-       /*
-        * Now maybe reload the debug registers and handle I/O bitmaps
-        */
-       if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT ||
-                    task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
-               __switch_to_xtra(prev_p, next_p, tss);
+       switch_to_extra(prev_p, next_p);
 
 #ifdef CONFIG_XEN_PV
        /*
index b74e7bf..d494b9b 100644 (file)
@@ -1280,23 +1280,6 @@ void __init setup_arch(char **cmdline_p)
        unwind_init();
 }
 
-/*
- * From boot protocol 2.14 onwards we expect the bootloader to set the
- * version to "0x8000 | <used version>". In case we find a version >= 2.14
- * without the 0x8000 we assume the boot loader supports 2.13 only and
- * reset the version accordingly. The 0x8000 flag is removed in any case.
- */
-void __init x86_verify_bootdata_version(void)
-{
-       if (boot_params.hdr.version & VERSION_WRITTEN)
-               boot_params.hdr.version &= ~VERSION_WRITTEN;
-       else if (boot_params.hdr.version >= 0x020e)
-               boot_params.hdr.version = 0x020d;
-
-       if (boot_params.hdr.version < 0x020e)
-               boot_params.hdr.acpi_rsdp_addr = 0;
-}
-
 #ifdef CONFIG_X86_32
 
 static struct resource video_ram_resource = {
index bddd6b3..03b6b4c 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/export.h>
 #include <linux/cpu.h>
 #include <linux/debugfs.h>
-#include <linux/ptrace.h>
 
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
  *     Implement flush IPI by CALL_FUNCTION_VECTOR, Alex Shi
  */
 
+/*
+ * Use bit 0 to mangle the TIF_SPEC_IB state into the mm pointer which is
+ * stored in cpu_tlb_state.last_user_mm_ibpb.
+ */
+#define LAST_USER_MM_IBPB      0x1UL
+
 /*
  * We get here when we do something requiring a TLB invalidation
  * but could not go invalidate all of the contexts.  We do the
@@ -181,17 +186,87 @@ static void sync_current_stack_to_mm(struct mm_struct *mm)
        }
 }
 
-static bool ibpb_needed(struct task_struct *tsk, u64 last_ctx_id)
+static inline unsigned long mm_mangle_tif_spec_ib(struct task_struct *next)
+{
+       unsigned long next_tif = task_thread_info(next)->flags;
+       unsigned long ibpb = (next_tif >> TIF_SPEC_IB) & LAST_USER_MM_IBPB;
+
+       return (unsigned long)next->mm | ibpb;
+}
+
+static void cond_ibpb(struct task_struct *next)
 {
+       if (!next || !next->mm)
+               return;
+
        /*
-        * Check if the current (previous) task has access to the memory
-        * of the @tsk (next) task. If access is denied, make sure to
-        * issue a IBPB to stop user->user Spectre-v2 attacks.
-        *
-        * Note: __ptrace_may_access() returns 0 or -ERRNO.
+        * Both, the conditional and the always IBPB mode use the mm
+        * pointer to avoid the IBPB when switching between tasks of the
+        * same process. Using the mm pointer instead of mm->context.ctx_id
+        * opens a hypothetical hole vs. mm_struct reuse, which is more or
+        * less impossible to control by an attacker. Aside of that it
+        * would only affect the first schedule so the theoretically
+        * exposed data is not really interesting.
         */
-       return (tsk && tsk->mm && tsk->mm->context.ctx_id != last_ctx_id &&
-               ptrace_may_access_sched(tsk, PTRACE_MODE_SPEC_IBPB));
+       if (static_branch_likely(&switch_mm_cond_ibpb)) {
+               unsigned long prev_mm, next_mm;
+
+               /*
+                * This is a bit more complex than the always mode because
+                * it has to handle two cases:
+                *
+                * 1) Switch from a user space task (potential attacker)
+                *    which has TIF_SPEC_IB set to a user space task
+                *    (potential victim) which has TIF_SPEC_IB not set.
+                *
+                * 2) Switch from a user space task (potential attacker)
+                *    which has TIF_SPEC_IB not set to a user space task
+                *    (potential victim) which has TIF_SPEC_IB set.
+                *
+                * This could be done by unconditionally issuing IBPB when
+                * a task which has TIF_SPEC_IB set is either scheduled in
+                * or out. Though that results in two flushes when:
+                *
+                * - the same user space task is scheduled out and later
+                *   scheduled in again and only a kernel thread ran in
+                *   between.
+                *
+                * - a user space task belonging to the same process is
+                *   scheduled in after a kernel thread ran in between
+                *
+                * - a user space task belonging to the same process is
+                *   scheduled in immediately.
+                *
+                * Optimize this with reasonably small overhead for the
+                * above cases. Mangle the TIF_SPEC_IB bit into the mm
+                * pointer of the incoming task which is stored in
+                * cpu_tlbstate.last_user_mm_ibpb for comparison.
+                */
+               next_mm = mm_mangle_tif_spec_ib(next);
+               prev_mm = this_cpu_read(cpu_tlbstate.last_user_mm_ibpb);
+
+               /*
+                * Issue IBPB only if the mm's are different and one or
+                * both have the IBPB bit set.
+                */
+               if (next_mm != prev_mm &&
+                   (next_mm | prev_mm) & LAST_USER_MM_IBPB)
+                       indirect_branch_prediction_barrier();
+
+               this_cpu_write(cpu_tlbstate.last_user_mm_ibpb, next_mm);
+       }
+
+       if (static_branch_unlikely(&switch_mm_always_ibpb)) {
+               /*
+                * Only flush when switching to a user space task with a
+                * different context than the user space task which ran
+                * last on this CPU.
+                */
+               if (this_cpu_read(cpu_tlbstate.last_user_mm) != next->mm) {
+                       indirect_branch_prediction_barrier();
+                       this_cpu_write(cpu_tlbstate.last_user_mm, next->mm);
+               }
+       }
 }
 
 void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
@@ -292,22 +367,12 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
                new_asid = prev_asid;
                need_flush = true;
        } else {
-               u64 last_ctx_id = this_cpu_read(cpu_tlbstate.last_ctx_id);
-
                /*
                 * Avoid user/user BTB poisoning by flushing the branch
                 * predictor when switching between processes. This stops
                 * one process from doing Spectre-v2 attacks on another.
-                *
-                * As an optimization, flush indirect branches only when
-                * switching into a processes that can't be ptrace by the
-                * current one (as in such case, attacker has much more
-                * convenient way how to tamper with the next process than
-                * branch buffer poisoning).
                 */
-               if (static_cpu_has(X86_FEATURE_USE_IBPB) &&
-                               ibpb_needed(tsk, last_ctx_id))
-                       indirect_branch_prediction_barrier();
+               cond_ibpb(tsk);
 
                if (IS_ENABLED(CONFIG_VMAP_STACK)) {
                        /*
@@ -365,14 +430,6 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
                trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, 0);
        }
 
-       /*
-        * Record last user mm's context id, so we can avoid
-        * flushing branch buffer with IBPB if we switch back
-        * to the same user.
-        */
-       if (next != &init_mm)
-               this_cpu_write(cpu_tlbstate.last_ctx_id, next->context.ctx_id);
-
        /* Make sure we write CR3 before loaded_mm. */
        barrier();
 
@@ -441,7 +498,7 @@ void initialize_tlbstate_and_flush(void)
        write_cr3(build_cr3(mm->pgd, 0));
 
        /* Reinitialize tlbstate. */
-       this_cpu_write(cpu_tlbstate.last_ctx_id, mm->context.ctx_id);
+       this_cpu_write(cpu_tlbstate.last_user_mm_ibpb, LAST_USER_MM_IBPB);
        this_cpu_write(cpu_tlbstate.loaded_mm_asid, 0);
        this_cpu_write(cpu_tlbstate.next_asid, 1);
        this_cpu_write(cpu_tlbstate.ctxs[0].ctx_id, mm->context.ctx_id);
index 7476b3b..7138bc7 100644 (file)
@@ -183,7 +183,7 @@ early_efi_write(struct console *con, const char *str, unsigned int num)
                        num--;
                }
 
-               if (efi_x >= si->lfb_width) {
+               if (efi_x + font->width > si->lfb_width) {
                        efi_x = 0;
                        efi_y += font->height;
                }
index e996e8e..750f46a 100644 (file)
@@ -10,7 +10,6 @@
 #include <xen/xen.h>
 #include <xen/features.h>
 #include <xen/page.h>
-#include <xen/interface/memory.h>
 
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
@@ -346,80 +345,3 @@ void xen_arch_unregister_cpu(int num)
 }
 EXPORT_SYMBOL(xen_arch_unregister_cpu);
 #endif
-
-#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
-void __init arch_xen_balloon_init(struct resource *hostmem_resource)
-{
-       struct xen_memory_map memmap;
-       int rc;
-       unsigned int i, last_guest_ram;
-       phys_addr_t max_addr = PFN_PHYS(max_pfn);
-       struct e820_table *xen_e820_table;
-       const struct e820_entry *entry;
-       struct resource *res;
-
-       if (!xen_initial_domain())
-               return;
-
-       xen_e820_table = kmalloc(sizeof(*xen_e820_table), GFP_KERNEL);
-       if (!xen_e820_table)
-               return;
-
-       memmap.nr_entries = ARRAY_SIZE(xen_e820_table->entries);
-       set_xen_guest_handle(memmap.buffer, xen_e820_table->entries);
-       rc = HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap);
-       if (rc) {
-               pr_warn("%s: Can't read host e820 (%d)\n", __func__, rc);
-               goto out;
-       }
-
-       last_guest_ram = 0;
-       for (i = 0; i < memmap.nr_entries; i++) {
-               if (xen_e820_table->entries[i].addr >= max_addr)
-                       break;
-               if (xen_e820_table->entries[i].type == E820_TYPE_RAM)
-                       last_guest_ram = i;
-       }
-
-       entry = &xen_e820_table->entries[last_guest_ram];
-       if (max_addr >= entry->addr + entry->size)
-               goto out; /* No unallocated host RAM. */
-
-       hostmem_resource->start = max_addr;
-       hostmem_resource->end = entry->addr + entry->size;
-
-       /*
-        * Mark non-RAM regions between the end of dom0 RAM and end of host RAM
-        * as unavailable. The rest of that region can be used for hotplug-based
-        * ballooning.
-        */
-       for (; i < memmap.nr_entries; i++) {
-               entry = &xen_e820_table->entries[i];
-
-               if (entry->type == E820_TYPE_RAM)
-                       continue;
-
-               if (entry->addr >= hostmem_resource->end)
-                       break;
-
-               res = kzalloc(sizeof(*res), GFP_KERNEL);
-               if (!res)
-                       goto out;
-
-               res->name = "Unavailable host RAM";
-               res->start = entry->addr;
-               res->end = (entry->addr + entry->size < hostmem_resource->end) ?
-                           entry->addr + entry->size : hostmem_resource->end;
-               rc = insert_resource(hostmem_resource, res);
-               if (rc) {
-                       pr_warn("%s: Can't insert [%llx - %llx) (%d)\n",
-                               __func__, res->start, res->end, rc);
-                       kfree(res);
-                       goto  out;
-               }
-       }
-
- out:
-       kfree(xen_e820_table);
-}
-#endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */
index 2bce795..0766a08 100644 (file)
@@ -69,6 +69,11 @@ void xen_mc_flush(void)
 
        trace_xen_mc_flush(b->mcidx, b->argidx, b->cbidx);
 
+#if MC_DEBUG
+       memcpy(b->debug, b->entries,
+              b->mcidx * sizeof(struct multicall_entry));
+#endif
+
        switch (b->mcidx) {
        case 0:
                /* no-op */
@@ -87,32 +92,34 @@ void xen_mc_flush(void)
                break;
 
        default:
-#if MC_DEBUG
-               memcpy(b->debug, b->entries,
-                      b->mcidx * sizeof(struct multicall_entry));
-#endif
-
                if (HYPERVISOR_multicall(b->entries, b->mcidx) != 0)
                        BUG();
                for (i = 0; i < b->mcidx; i++)
                        if (b->entries[i].result < 0)
                                ret++;
+       }
 
+       if (WARN_ON(ret)) {
+               pr_err("%d of %d multicall(s) failed: cpu %d\n",
+                      ret, b->mcidx, smp_processor_id());
+               for (i = 0; i < b->mcidx; i++) {
+                       if (b->entries[i].result < 0) {
 #if MC_DEBUG
-               if (ret) {
-                       printk(KERN_ERR "%d multicall(s) failed: cpu %d\n",
-                              ret, smp_processor_id());
-                       dump_stack();
-                       for (i = 0; i < b->mcidx; i++) {
-                               printk(KERN_DEBUG "  call %2d/%d: op=%lu arg=[%lx] result=%ld\t%pF\n",
-                                      i+1, b->mcidx,
+                               pr_err("  call %2d: op=%lu arg=[%lx] result=%ld\t%pF\n",
+                                      i + 1,
                                       b->debug[i].op,
                                       b->debug[i].args[0],
                                       b->entries[i].result,
                                       b->caller[i]);
+#else
+                               pr_err("  call %2d: op=%lu arg=[%lx] result=%ld\n",
+                                      i + 1,
+                                      b->entries[i].op,
+                                      b->entries[i].args[0],
+                                      b->entries[i].result);
+#endif
                        }
                }
-#endif
        }
 
        b->mcidx = 0;
@@ -126,8 +133,6 @@ void xen_mc_flush(void)
        b->cbidx = 0;
 
        local_irq_restore(flags);
-
-       WARN_ON(ret);
 }
 
 struct multicall_space __xen_mc_entry(size_t args)
index 1163e33..075ed47 100644 (file)
@@ -808,6 +808,7 @@ char * __init xen_memory_setup(void)
        addr = xen_e820_table.entries[0].addr;
        size = xen_e820_table.entries[0].size;
        while (i < xen_e820_table.nr_entries) {
+               bool discard = false;
 
                chunk_size = size;
                type = xen_e820_table.entries[i].type;
@@ -823,10 +824,11 @@ char * __init xen_memory_setup(void)
                                xen_add_extra_mem(pfn_s, n_pfns);
                                xen_max_p2m_pfn = pfn_s + n_pfns;
                        } else
-                               type = E820_TYPE_UNUSABLE;
+                               discard = true;
                }
 
-               xen_align_and_add_e820_region(addr, chunk_size, type);
+               if (!discard)
+                       xen_align_and_add_e820_region(addr, chunk_size, type);
 
                addr += chunk_size;
                size -= chunk_size;
index 1c8a881..3776122 100644 (file)
@@ -3,22 +3,17 @@
  * Split spinlock implementation out into its own file, so it can be
  * compiled in a FTRACE-compatible way.
  */
-#include <linux/kernel_stat.h>
+#include <linux/kernel.h>
 #include <linux/spinlock.h>
-#include <linux/debugfs.h>
-#include <linux/log2.h>
-#include <linux/gfp.h>
 #include <linux/slab.h>
 #include <linux/atomic.h>
 
 #include <asm/paravirt.h>
 #include <asm/qspinlock.h>
 
-#include <xen/interface/xen.h>
 #include <xen/events.h>
 
 #include "xen-ops.h"
-#include "debugfs.h"
 
 static DEFINE_PER_CPU(int, lock_kicker_irq) = -1;
 static DEFINE_PER_CPU(char *, irq_name);
index 3a27d31..9733721 100644 (file)
@@ -638,7 +638,7 @@ static bool bfq_varied_queue_weights_or_active_groups(struct bfq_data *bfqd)
                 bfqd->queue_weights_tree.rb_node->rb_right)
 #ifdef CONFIG_BFQ_GROUP_IOSCHED
               ) ||
-               (bfqd->num_active_groups > 0
+               (bfqd->num_groups_with_pending_reqs > 0
 #endif
               );
 }
@@ -802,7 +802,21 @@ void bfq_weights_tree_remove(struct bfq_data *bfqd,
                         */
                        break;
                }
-               bfqd->num_active_groups--;
+
+               /*
+                * The decrement of num_groups_with_pending_reqs is
+                * not performed immediately upon the deactivation of
+                * entity, but it is delayed to when it also happens
+                * that the first leaf descendant bfqq of entity gets
+                * all its pending requests completed. The following
+                * instructions perform this delayed decrement, if
+                * needed. See the comments on
+                * num_groups_with_pending_reqs for details.
+                */
+               if (entity->in_groups_with_pending_reqs) {
+                       entity->in_groups_with_pending_reqs = false;
+                       bfqd->num_groups_with_pending_reqs--;
+               }
        }
 }
 
@@ -3529,27 +3543,44 @@ static bool bfq_better_to_idle(struct bfq_queue *bfqq)
         * fact, if there are active groups, then, for condition (i)
         * to become false, it is enough that an active group contains
         * more active processes or sub-groups than some other active
-        * group. We address this issue with the following bi-modal
-        * behavior, implemented in the function
+        * group. More precisely, for condition (i) to hold because of
+        * such a group, it is not even necessary that the group is
+        * (still) active: it is sufficient that, even if the group
+        * has become inactive, some of its descendant processes still
+        * have some request already dispatched but still waiting for
+        * completion. In fact, requests have still to be guaranteed
+        * their share of the throughput even after being
+        * dispatched. In this respect, it is easy to show that, if a
+        * group frequently becomes inactive while still having
+        * in-flight requests, and if, when this happens, the group is
+        * not considered in the calculation of whether the scenario
+        * is asymmetric, then the group may fail to be guaranteed its
+        * fair share of the throughput (basically because idling may
+        * not be performed for the descendant processes of the group,
+        * but it had to be).  We address this issue with the
+        * following bi-modal behavior, implemented in the function
         * bfq_symmetric_scenario().
         *
-        * If there are active groups, then the scenario is tagged as
+        * If there are groups with requests waiting for completion
+        * (as commented above, some of these groups may even be
+        * already inactive), then the scenario is tagged as
         * asymmetric, conservatively, without checking any of the
         * conditions (i) and (ii). So the device is idled for bfqq.
         * This behavior matches also the fact that groups are created
-        * exactly if controlling I/O (to preserve bandwidth and
-        * latency guarantees) is a primary concern.
+        * exactly if controlling I/O is a primary concern (to
+        * preserve bandwidth and latency guarantees).
         *
-        * On the opposite end, if there are no active groups, then
-        * only condition (i) is actually controlled, i.e., provided
-        * that condition (i) holds, idling is not performed,
-        * regardless of whether condition (ii) holds. In other words,
-        * only if condition (i) does not hold, then idling is
-        * allowed, and the device tends to be prevented from queueing
-        * many requests, possibly of several processes. Since there
-        * are no active groups, then, to control condition (i) it is
-        * enough to check whether all active queues have the same
-        * weight.
+        * On the opposite end, if there are no groups with requests
+        * waiting for completion, then only condition (i) is actually
+        * controlled, i.e., provided that condition (i) holds, idling
+        * is not performed, regardless of whether condition (ii)
+        * holds. In other words, only if condition (i) does not hold,
+        * then idling is allowed, and the device tends to be
+        * prevented from queueing many requests, possibly of several
+        * processes. Since there are no groups with requests waiting
+        * for completion, then, to control condition (i) it is enough
+        * to check just whether all the queues with requests waiting
+        * for completion also have the same weight.
         *
         * Not checking condition (ii) evidently exposes bfqq to the
         * risk of getting less throughput than its fair share.
@@ -3607,10 +3638,11 @@ static bool bfq_better_to_idle(struct bfq_queue *bfqq)
         * bfqq is weight-raised is checked explicitly here. More
         * precisely, the compound condition below takes into account
         * also the fact that, even if bfqq is being weight-raised,
-        * the scenario is still symmetric if all active queues happen
-        * to be weight-raised. Actually, we should be even more
-        * precise here, and differentiate between interactive weight
-        * raising and soft real-time weight raising.
+        * the scenario is still symmetric if all queues with requests
+        * waiting for completion happen to be
+        * weight-raised. Actually, we should be even more precise
+        * here, and differentiate between interactive weight raising
+        * and soft real-time weight raising.
         *
         * As a side note, it is worth considering that the above
         * device-idling countermeasures may however fail in the
@@ -5417,7 +5449,7 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
        bfqd->idle_slice_timer.function = bfq_idle_slice_timer;
 
        bfqd->queue_weights_tree = RB_ROOT;
-       bfqd->num_active_groups = 0;
+       bfqd->num_groups_with_pending_reqs = 0;
 
        INIT_LIST_HEAD(&bfqd->active_list);
        INIT_LIST_HEAD(&bfqd->idle_list);
index 77651d8..0b02bf3 100644 (file)
@@ -196,6 +196,9 @@ struct bfq_entity {
 
        /* flag, set to request a weight, ioprio or ioprio_class change  */
        int prio_changed;
+
+       /* flag, set if the entity is counted in groups_with_pending_reqs */
+       bool in_groups_with_pending_reqs;
 };
 
 struct bfq_group;
@@ -448,10 +451,54 @@ struct bfq_data {
         * bfq_weights_tree_[add|remove] for further details).
         */
        struct rb_root queue_weights_tree;
+
        /*
-        * number of groups with requests still waiting for completion
+        * Number of groups with at least one descendant process that
+        * has at least one request waiting for completion. Note that
+        * this accounts for also requests already dispatched, but not
+        * yet completed. Therefore this number of groups may differ
+        * (be larger) than the number of active groups, as a group is
+        * considered active only if its corresponding entity has
+        * descendant queues with at least one request queued. This
+        * number is used to decide whether a scenario is symmetric.
+        * For a detailed explanation see comments on the computation
+        * of the variable asymmetric_scenario in the function
+        * bfq_better_to_idle().
+        *
+        * However, it is hard to compute this number exactly, for
+        * groups with multiple descendant processes. Consider a group
+        * that is inactive, i.e., that has no descendant process with
+        * pending I/O inside BFQ queues. Then suppose that
+        * num_groups_with_pending_reqs is still accounting for this
+        * group, because the group has descendant processes with some
+        * I/O request still in flight. num_groups_with_pending_reqs
+        * should be decremented when the in-flight request of the
+        * last descendant process is finally completed (assuming that
+        * nothing else has changed for the group in the meantime, in
+        * terms of composition of the group and active/inactive state of child
+        * groups and processes). To accomplish this, an additional
+        * pending-request counter must be added to entities, and must
+        * be updated correctly. To avoid this additional field and operations,
+        * we resort to the following tradeoff between simplicity and
+        * accuracy: for an inactive group that is still counted in
+        * num_groups_with_pending_reqs, we decrement
+        * num_groups_with_pending_reqs when the first descendant
+        * process of the group remains with no request waiting for
+        * completion.
+        *
+        * Even this simpler decrement strategy requires a little
+        * carefulness: to avoid multiple decrements, we flag a group,
+        * more precisely an entity representing a group, as still
+        * counted in num_groups_with_pending_reqs when it becomes
+        * inactive. Then, when the first descendant queue of the
+        * entity remains with no request waiting for completion,
+        * num_groups_with_pending_reqs is decremented, and this flag
+        * is reset. After this flag is reset for the entity,
+        * num_groups_with_pending_reqs won't be decremented any
+        * longer in case a new descendant queue of the entity remains
+        * with no request waiting for completion.
         */
-       unsigned int num_active_groups;
+       unsigned int num_groups_with_pending_reqs;
 
        /*
         * Number of bfq_queues containing requests (including the
index 4b0d5fb..63e0f12 100644 (file)
@@ -1012,7 +1012,10 @@ static void __bfq_activate_entity(struct bfq_entity *entity,
                        container_of(entity, struct bfq_group, entity);
                struct bfq_data *bfqd = bfqg->bfqd;
 
-               bfqd->num_active_groups++;
+               if (!entity->in_groups_with_pending_reqs) {
+                       entity->in_groups_with_pending_reqs = true;
+                       bfqd->num_groups_with_pending_reqs++;
+               }
        }
 #endif
 
index e7696c4..7695034 100644 (file)
@@ -820,7 +820,7 @@ static struct request *attempt_merge(struct request_queue *q,
 
        req->__data_len += blk_rq_bytes(next);
 
-       if (req_op(req) != REQ_OP_DISCARD)
+       if (!blk_discard_mergable(req))
                elv_merge_requests(q, req, next);
 
        /*
index 3f91c6e..6a75662 100644 (file)
@@ -1764,7 +1764,7 @@ insert:
        if (bypass_insert)
                return BLK_STS_RESOURCE;
 
-       blk_mq_sched_insert_request(rq, false, run_queue, false);
+       blk_mq_request_bypass_insert(rq, run_queue);
        return BLK_STS_OK;
 }
 
@@ -1780,7 +1780,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
 
        ret = __blk_mq_try_issue_directly(hctx, rq, cookie, false);
        if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE)
-               blk_mq_sched_insert_request(rq, false, true, false);
+               blk_mq_request_bypass_insert(rq, true);
        else if (ret != BLK_STS_OK)
                blk_mq_end_request(rq, ret);
 
@@ -1815,7 +1815,8 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
                if (ret != BLK_STS_OK) {
                        if (ret == BLK_STS_RESOURCE ||
                                        ret == BLK_STS_DEV_RESOURCE) {
-                               list_add(&rq->queuelist, list);
+                               blk_mq_request_bypass_insert(rq,
+                                                       list_empty(list));
                                break;
                        }
                        blk_mq_end_request(rq, ret);
index f7a235d..05c91eb 100644 (file)
@@ -1812,7 +1812,7 @@ config CRYPTO_USER_API_AEAD
          cipher algorithms.
 
 config CRYPTO_STATS
-       bool "Crypto usage statistics for User-space"
+       bool
        help
          This option enables the gathering of crypto stats.
          This will collect:
index b761b1f..dd5f332 100644 (file)
@@ -140,9 +140,8 @@ static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb)
        spawn = skcipher_instance_ctx(inst);
        err = crypto_init_spawn(spawn, alg, skcipher_crypto_instance(inst),
                                CRYPTO_ALG_TYPE_MASK);
-       crypto_mod_put(alg);
        if (err)
-               goto err_free_inst;
+               goto err_put_alg;
 
        err = crypto_inst_setname(skcipher_crypto_instance(inst), "cbc", alg);
        if (err)
@@ -174,12 +173,15 @@ static int crypto_cbc_create(struct crypto_template *tmpl, struct rtattr **tb)
        err = skcipher_register_instance(tmpl, inst);
        if (err)
                goto err_drop_spawn;
+       crypto_mod_put(alg);
 
 out:
        return err;
 
 err_drop_spawn:
        crypto_drop_spawn(spawn);
+err_put_alg:
+       crypto_mod_put(alg);
 err_free_inst:
        kfree(inst);
        goto out;
index a0d68c0..20987d0 100644 (file)
@@ -286,9 +286,8 @@ static int crypto_cfb_create(struct crypto_template *tmpl, struct rtattr **tb)
        spawn = skcipher_instance_ctx(inst);
        err = crypto_init_spawn(spawn, alg, skcipher_crypto_instance(inst),
                                CRYPTO_ALG_TYPE_MASK);
-       crypto_mod_put(alg);
        if (err)
-               goto err_free_inst;
+               goto err_put_alg;
 
        err = crypto_inst_setname(skcipher_crypto_instance(inst), "cfb", alg);
        if (err)
@@ -317,12 +316,15 @@ static int crypto_cfb_create(struct crypto_template *tmpl, struct rtattr **tb)
        err = skcipher_register_instance(tmpl, inst);
        if (err)
                goto err_drop_spawn;
+       crypto_mod_put(alg);
 
 out:
        return err;
 
 err_drop_spawn:
        crypto_drop_spawn(spawn);
+err_put_alg:
+       crypto_mod_put(alg);
 err_free_inst:
        kfree(inst);
        goto out;
index ef802f6..8aa1014 100644 (file)
@@ -244,9 +244,8 @@ static int crypto_pcbc_create(struct crypto_template *tmpl, struct rtattr **tb)
        spawn = skcipher_instance_ctx(inst);
        err = crypto_init_spawn(spawn, alg, skcipher_crypto_instance(inst),
                                CRYPTO_ALG_TYPE_MASK);
-       crypto_mod_put(alg);
        if (err)
-               goto err_free_inst;
+               goto err_put_alg;
 
        err = crypto_inst_setname(skcipher_crypto_instance(inst), "pcbc", alg);
        if (err)
@@ -275,12 +274,15 @@ static int crypto_pcbc_create(struct crypto_template *tmpl, struct rtattr **tb)
        err = skcipher_register_instance(tmpl, inst);
        if (err)
                goto err_drop_spawn;
+       crypto_mod_put(alg);
 
 out:
        return err;
 
 err_drop_spawn:
        crypto_drop_spawn(spawn);
+err_put_alg:
+       crypto_mod_put(alg);
 err_free_inst:
        kfree(inst);
        goto out;
index 0d42f30..9920fac 100644 (file)
@@ -244,7 +244,6 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
 {
        acpi_status status;
        u32 buffer_length;
-       u32 data_length;
        void *buffer;
        union acpi_operand_object *buffer_desc;
        u32 function;
@@ -282,14 +281,12 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
        case ACPI_ADR_SPACE_SMBUS:
 
                buffer_length = ACPI_SMBUS_BUFFER_SIZE;
-               data_length = ACPI_SMBUS_DATA_SIZE;
                function = ACPI_WRITE | (obj_desc->field.attribute << 16);
                break;
 
        case ACPI_ADR_SPACE_IPMI:
 
                buffer_length = ACPI_IPMI_BUFFER_SIZE;
-               data_length = ACPI_IPMI_DATA_SIZE;
                function = ACPI_WRITE;
                break;
 
@@ -310,7 +307,6 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
                /* Add header length to get the full size of the buffer */
 
                buffer_length += ACPI_SERIAL_HEADER_SIZE;
-               data_length = source_desc->buffer.pointer[1];
                function = ACPI_WRITE | (accessor_type << 16);
                break;
 
@@ -318,20 +314,6 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
                return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
        }
 
-#if 0
-       OBSOLETE ?
-           /* Check for possible buffer overflow */
-           if (data_length > source_desc->buffer.length) {
-               ACPI_ERROR((AE_INFO,
-                           "Length in buffer header (%u)(%u) is greater than "
-                           "the physical buffer length (%u) and will overflow",
-                           data_length, buffer_length,
-                           source_desc->buffer.length));
-
-               return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
-       }
-#endif
-
        /* Create the transfer/bidirectional/return buffer */
 
        buffer_desc = acpi_ut_create_buffer_object(buffer_length);
@@ -342,7 +324,8 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
        /* Copy the input buffer data to the transfer buffer */
 
        buffer = buffer_desc->buffer.pointer;
-       memcpy(buffer, source_desc->buffer.pointer, data_length);
+       memcpy(buffer, source_desc->buffer.pointer,
+              min(buffer_length, source_desc->buffer.length));
 
        /* Lock entire transaction if requested */
 
index 2a361e2..70f4e80 100644 (file)
@@ -700,7 +700,7 @@ static void iort_set_device_domain(struct device *dev,
  */
 static struct irq_domain *iort_get_platform_device_domain(struct device *dev)
 {
-       struct acpi_iort_node *node, *msi_parent;
+       struct acpi_iort_node *node, *msi_parent = NULL;
        struct fwnode_handle *iort_fwnode;
        struct acpi_iort_its_group *its;
        int i;
index 14d9f5b..5912d30 100644 (file)
@@ -1308,7 +1308,7 @@ static ssize_t scrub_store(struct device *dev,
        if (nd_desc) {
                struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
 
-               rc = acpi_nfit_ars_rescan(acpi_desc, 0);
+               rc = acpi_nfit_ars_rescan(acpi_desc, ARS_REQ_LONG);
        }
        device_unlock(dev);
        if (rc)
index cb30a52..9f1000d 100644 (file)
@@ -2974,7 +2974,6 @@ static void binder_transaction(struct binder_proc *proc,
                t->buffer = NULL;
                goto err_binder_alloc_buf_failed;
        }
-       t->buffer->allow_user_free = 0;
        t->buffer->debug_id = t->debug_id;
        t->buffer->transaction = t;
        t->buffer->target_node = target_node;
@@ -3510,14 +3509,18 @@ static int binder_thread_write(struct binder_proc *proc,
 
                        buffer = binder_alloc_prepare_to_free(&proc->alloc,
                                                              data_ptr);
-                       if (buffer == NULL) {
-                               binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n",
-                                       proc->pid, thread->pid, (u64)data_ptr);
-                               break;
-                       }
-                       if (!buffer->allow_user_free) {
-                               binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n",
-                                       proc->pid, thread->pid, (u64)data_ptr);
+                       if (IS_ERR_OR_NULL(buffer)) {
+                               if (PTR_ERR(buffer) == -EPERM) {
+                                       binder_user_error(
+                                               "%d:%d BC_FREE_BUFFER u%016llx matched unreturned or currently freeing buffer\n",
+                                               proc->pid, thread->pid,
+                                               (u64)data_ptr);
+                               } else {
+                                       binder_user_error(
+                                               "%d:%d BC_FREE_BUFFER u%016llx no match\n",
+                                               proc->pid, thread->pid,
+                                               (u64)data_ptr);
+                               }
                                break;
                        }
                        binder_debug(BINDER_DEBUG_FREE_BUFFER,
index 64fd96e..030c98f 100644 (file)
@@ -151,16 +151,12 @@ static struct binder_buffer *binder_alloc_prepare_to_free_locked(
                else {
                        /*
                         * Guard against user threads attempting to
-                        * free the buffer twice
+                        * free the buffer when in use by kernel or
+                        * after it's already been freed.
                         */
-                       if (buffer->free_in_progress) {
-                               binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
-                                                  "%d:%d FREE_BUFFER u%016llx user freed buffer twice\n",
-                                                  alloc->pid, current->pid,
-                                                  (u64)user_ptr);
-                               return NULL;
-                       }
-                       buffer->free_in_progress = 1;
+                       if (!buffer->allow_user_free)
+                               return ERR_PTR(-EPERM);
+                       buffer->allow_user_free = 0;
                        return buffer;
                }
        }
@@ -500,7 +496,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
 
        rb_erase(best_fit, &alloc->free_buffers);
        buffer->free = 0;
-       buffer->free_in_progress = 0;
+       buffer->allow_user_free = 0;
        binder_insert_allocated_buffer_locked(alloc, buffer);
        binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
                     "%d: binder_alloc_buf size %zd got %pK\n",
index 9ef64e5..fb3238c 100644 (file)
@@ -50,8 +50,7 @@ struct binder_buffer {
        unsigned free:1;
        unsigned allow_user_free:1;
        unsigned async_transaction:1;
-       unsigned free_in_progress:1;
-       unsigned debug_id:28;
+       unsigned debug_id:29;
 
        struct binder_transaction *transaction;
 
index a7f5202..b8c3f9e 100644 (file)
@@ -4602,6 +4602,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "SSD*INTEL*",                 NULL,   ATA_HORKAGE_ZERO_AFTER_TRIM, },
        { "Samsung*SSD*",               NULL,   ATA_HORKAGE_ZERO_AFTER_TRIM, },
        { "SAMSUNG*SSD*",               NULL,   ATA_HORKAGE_ZERO_AFTER_TRIM, },
+       { "SAMSUNG*MZ7KM*",             NULL,   ATA_HORKAGE_ZERO_AFTER_TRIM, },
        { "ST[1248][0248]0[FH]*",       NULL,   ATA_HORKAGE_ZERO_AFTER_TRIM, },
 
        /*
index 4aaf00d..e038e2b 100644 (file)
@@ -26,8 +26,14 @@ struct devres_node {
 
 struct devres {
        struct devres_node              node;
-       /* -- 3 pointers */
-       unsigned long long              data[]; /* guarantee ull alignment */
+       /*
+        * Some archs want to perform DMA into kmalloc caches
+        * and need a guaranteed alignment larger than
+        * the alignment of a 64-bit integer.
+        * Thus we use ARCH_KMALLOC_MINALIGN here and get exactly the same
+        * buffer alignment as if it was allocated by plain kmalloc().
+        */
+       u8 __aligned(ARCH_KMALLOC_MINALIGN) data[];
 };
 
 struct devres_group {
index ad8d483..ca7d37e 100644 (file)
@@ -183,7 +183,7 @@ void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
                pr_err("CLK %d has invalid pointer %p\n", id, clk);
                return;
        }
-       if (id > unit->nr_clks) {
+       if (id >= unit->nr_clks) {
                pr_err("CLK %d is invalid\n", id);
                return;
        }
index 9781b1b..9235a33 100644 (file)
@@ -200,11 +200,11 @@ static struct clk_hw *cp110_of_clk_get(struct of_phandle_args *clkspec,
        unsigned int idx = clkspec->args[1];
 
        if (type == CP110_CLK_TYPE_CORE) {
-               if (idx > CP110_MAX_CORE_CLOCKS)
+               if (idx >= CP110_MAX_CORE_CLOCKS)
                        return ERR_PTR(-EINVAL);
                return clk_data->hws[idx];
        } else if (type == CP110_CLK_TYPE_GATABLE) {
-               if (idx > CP110_MAX_GATABLE_CLOCKS)
+               if (idx >= CP110_MAX_GATABLE_CLOCKS)
                        return ERR_PTR(-EINVAL);
                return clk_data->hws[CP110_MAX_CORE_CLOCKS + idx];
        }
index db9b247..0a48ed5 100644 (file)
@@ -191,6 +191,22 @@ int qcom_cc_register_sleep_clk(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(qcom_cc_register_sleep_clk);
 
+/* Drop 'protected-clocks' from the list of clocks to register */
+static void qcom_cc_drop_protected(struct device *dev, struct qcom_cc *cc)
+{
+       struct device_node *np = dev->of_node;
+       struct property *prop;
+       const __be32 *p;
+       u32 i;
+
+       of_property_for_each_u32(np, "protected-clocks", prop, p, i) {
+               if (i >= cc->num_rclks)
+                       continue;
+
+               cc->rclks[i] = NULL;
+       }
+}
+
 static struct clk_hw *qcom_cc_clk_hw_get(struct of_phandle_args *clkspec,
                                         void *data)
 {
@@ -251,6 +267,8 @@ int qcom_cc_really_probe(struct platform_device *pdev,
        cc->rclks = rclks;
        cc->num_rclks = num_clks;
 
+       qcom_cc_drop_protected(dev, cc);
+
        for (i = 0; i < num_clks; i++) {
                if (!rclks[i])
                        continue;
index 9d7d297..f65cc0f 100644 (file)
@@ -128,7 +128,7 @@ static const struct zynqmp_eemi_ops *eemi_ops;
  */
 static inline int zynqmp_is_valid_clock(u32 clk_id)
 {
-       if (clk_id > clock_max_idx)
+       if (clk_id >= clock_max_idx)
                return -ENODEV;
 
        return clock[clk_id].valid;
@@ -279,6 +279,9 @@ struct clk_hw *zynqmp_clk_register_fixed_factor(const char *name, u32 clk_id,
        qdata.arg1 = clk_id;
 
        ret = eemi_ops->query_data(qdata, ret_payload);
+       if (ret)
+               return ERR_PTR(ret);
+
        mult = ret_payload[1];
        div = ret_payload[2];
 
index 7cbac6e..01d936c 100644 (file)
@@ -1641,6 +1641,12 @@ static void atc_free_chan_resources(struct dma_chan *chan)
        atchan->descs_allocated = 0;
        atchan->status = 0;
 
+       /*
+        * Free atslave allocated in at_dma_xlate()
+        */
+       kfree(chan->private);
+       chan->private = NULL;
+
        dev_vdbg(chan2dev(chan), "free_chan_resources: done\n");
 }
 
@@ -1675,7 +1681,7 @@ static struct dma_chan *at_dma_xlate(struct of_phandle_args *dma_spec,
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE, mask);
 
-       atslave = devm_kzalloc(&dmac_pdev->dev, sizeof(*atslave), GFP_KERNEL);
+       atslave = kzalloc(sizeof(*atslave), GFP_KERNEL);
        if (!atslave)
                return NULL;
 
@@ -2000,6 +2006,8 @@ static int at_dma_remove(struct platform_device *pdev)
        struct resource         *io;
 
        at_dma_off(atdma);
+       if (pdev->dev.of_node)
+               of_dma_controller_free(pdev->dev.of_node);
        dma_async_device_unregister(&atdma->dma_common);
 
        dma_pool_destroy(atdma->memset_pool);
index d0c3e50..1fc488e 100644 (file)
@@ -1059,12 +1059,12 @@ static void dwc_issue_pending(struct dma_chan *chan)
 /*
  * Program FIFO size of channels.
  *
- * By default full FIFO (1024 bytes) is assigned to channel 0. Here we
+ * By default full FIFO (512 bytes) is assigned to channel 0. Here we
  * slice FIFO on equal parts between channels.
  */
 static void idma32_fifo_partition(struct dw_dma *dw)
 {
-       u64 value = IDMA32C_FP_PSIZE_CH0(128) | IDMA32C_FP_PSIZE_CH1(128) |
+       u64 value = IDMA32C_FP_PSIZE_CH0(64) | IDMA32C_FP_PSIZE_CH1(64) |
                    IDMA32C_FP_UPDATE;
        u64 fifo_partition = 0;
 
@@ -1077,7 +1077,7 @@ static void idma32_fifo_partition(struct dw_dma *dw)
        /* Fill FIFO_PARTITION high bits (Channels 2..3, 6..7) */
        fifo_partition |= value << 32;
 
-       /* Program FIFO Partition registers - 128 bytes for each channel */
+       /* Program FIFO Partition registers - 64 bytes per channel */
        idma32_writeq(dw, FIFO_PARTITION1, fifo_partition);
        idma32_writeq(dw, FIFO_PARTITION0, fifo_partition);
 }
index b4ec2d2..cb1b44d 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
-#include <linux/dmapool.h>
 #include <linux/firmware.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
@@ -33,6 +32,7 @@
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_dma.h>
+#include <linux/workqueue.h>
 
 #include <asm/irq.h>
 #include <linux/platform_data/dma-imx-sdma.h>
@@ -376,7 +376,7 @@ struct sdma_channel {
        u32                             shp_addr, per_addr;
        enum dma_status                 status;
        struct imx_dma_data             data;
-       struct dma_pool                 *bd_pool;
+       struct work_struct              terminate_worker;
 };
 
 #define IMX_DMA_SG_LOOP                BIT(0)
@@ -1027,31 +1027,49 @@ static int sdma_disable_channel(struct dma_chan *chan)
 
        return 0;
 }
-
-static int sdma_disable_channel_with_delay(struct dma_chan *chan)
+static void sdma_channel_terminate_work(struct work_struct *work)
 {
-       struct sdma_channel *sdmac = to_sdma_chan(chan);
+       struct sdma_channel *sdmac = container_of(work, struct sdma_channel,
+                                                 terminate_worker);
        unsigned long flags;
        LIST_HEAD(head);
 
-       sdma_disable_channel(chan);
-       spin_lock_irqsave(&sdmac->vc.lock, flags);
-       vchan_get_all_descriptors(&sdmac->vc, &head);
-       sdmac->desc = NULL;
-       spin_unlock_irqrestore(&sdmac->vc.lock, flags);
-       vchan_dma_desc_free_list(&sdmac->vc, &head);
-
        /*
         * According to NXP R&D team a delay of one BD SDMA cost time
         * (maximum is 1ms) should be added after disable of the channel
         * bit, to ensure SDMA core has really been stopped after SDMA
         * clients call .device_terminate_all.
         */
-       mdelay(1);
+       usleep_range(1000, 2000);
+
+       spin_lock_irqsave(&sdmac->vc.lock, flags);
+       vchan_get_all_descriptors(&sdmac->vc, &head);
+       sdmac->desc = NULL;
+       spin_unlock_irqrestore(&sdmac->vc.lock, flags);
+       vchan_dma_desc_free_list(&sdmac->vc, &head);
+}
+
+static int sdma_disable_channel_async(struct dma_chan *chan)
+{
+       struct sdma_channel *sdmac = to_sdma_chan(chan);
+
+       sdma_disable_channel(chan);
+
+       if (sdmac->desc)
+               schedule_work(&sdmac->terminate_worker);
 
        return 0;
 }
 
+static void sdma_channel_synchronize(struct dma_chan *chan)
+{
+       struct sdma_channel *sdmac = to_sdma_chan(chan);
+
+       vchan_synchronize(&sdmac->vc);
+
+       flush_work(&sdmac->terminate_worker);
+}
+
 static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac)
 {
        struct sdma_engine *sdma = sdmac->sdma;
@@ -1192,10 +1210,11 @@ out:
 
 static int sdma_alloc_bd(struct sdma_desc *desc)
 {
+       u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
        int ret = 0;
 
-       desc->bd = dma_pool_alloc(desc->sdmac->bd_pool, GFP_NOWAIT,
-                                 &desc->bd_phys);
+       desc->bd = dma_zalloc_coherent(NULL, bd_size, &desc->bd_phys,
+                                       GFP_NOWAIT);
        if (!desc->bd) {
                ret = -ENOMEM;
                goto out;
@@ -1206,7 +1225,9 @@ out:
 
 static void sdma_free_bd(struct sdma_desc *desc)
 {
-       dma_pool_free(desc->sdmac->bd_pool, desc->bd, desc->bd_phys);
+       u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
+
+       dma_free_coherent(NULL, bd_size, desc->bd, desc->bd_phys);
 }
 
 static void sdma_desc_free(struct virt_dma_desc *vd)
@@ -1272,10 +1293,6 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
        if (ret)
                goto disable_clk_ahb;
 
-       sdmac->bd_pool = dma_pool_create("bd_pool", chan->device->dev,
-                               sizeof(struct sdma_buffer_descriptor),
-                               32, 0);
-
        return 0;
 
 disable_clk_ahb:
@@ -1290,7 +1307,9 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
        struct sdma_channel *sdmac = to_sdma_chan(chan);
        struct sdma_engine *sdma = sdmac->sdma;
 
-       sdma_disable_channel_with_delay(chan);
+       sdma_disable_channel_async(chan);
+
+       sdma_channel_synchronize(chan);
 
        if (sdmac->event_id0)
                sdma_event_disable(sdmac, sdmac->event_id0);
@@ -1304,9 +1323,6 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
 
        clk_disable(sdma->clk_ipg);
        clk_disable(sdma->clk_ahb);
-
-       dma_pool_destroy(sdmac->bd_pool);
-       sdmac->bd_pool = NULL;
 }
 
 static struct sdma_desc *sdma_transfer_init(struct sdma_channel *sdmac,
@@ -1999,6 +2015,8 @@ static int sdma_probe(struct platform_device *pdev)
 
                sdmac->channel = i;
                sdmac->vc.desc_free = sdma_desc_free;
+               INIT_WORK(&sdmac->terminate_worker,
+                               sdma_channel_terminate_work);
                /*
                 * Add the channel to the DMAC list. Do not add channel 0 though
                 * because we need it internally in the SDMA driver. This also means
@@ -2050,7 +2068,8 @@ static int sdma_probe(struct platform_device *pdev)
        sdma->dma_device.device_prep_slave_sg = sdma_prep_slave_sg;
        sdma->dma_device.device_prep_dma_cyclic = sdma_prep_dma_cyclic;
        sdma->dma_device.device_config = sdma_config;
-       sdma->dma_device.device_terminate_all = sdma_disable_channel_with_delay;
+       sdma->dma_device.device_terminate_all = sdma_disable_channel_async;
+       sdma->dma_device.device_synchronize = sdma_channel_synchronize;
        sdma->dma_device.src_addr_widths = SDMA_DMA_BUSWIDTHS;
        sdma->dma_device.dst_addr_widths = SDMA_DMA_BUSWIDTHS;
        sdma->dma_device.directions = SDMA_DMA_DIRECTIONS;
index 1497da3..e507ec3 100644 (file)
@@ -723,8 +723,22 @@ static int cppi41_stop_chan(struct dma_chan *chan)
 
        desc_phys = lower_32_bits(c->desc_phys);
        desc_num = (desc_phys - cdd->descs_phys) / sizeof(struct cppi41_desc);
-       if (!cdd->chan_busy[desc_num])
+       if (!cdd->chan_busy[desc_num]) {
+               struct cppi41_channel *cc, *_ct;
+
+               /*
+                * channels might still be in the pendling list if
+                * cppi41_dma_issue_pending() is called after
+                * cppi41_runtime_suspend() is called
+                */
+               list_for_each_entry_safe(cc, _ct, &cdd->pending, node) {
+                       if (cc != c)
+                               continue;
+                       list_del(&cc->node);
+                       break;
+               }
                return 0;
+       }
 
        ret = cppi41_tear_down_chan(c);
        if (ret)
index fad7c62..415849b 100644 (file)
@@ -969,13 +969,33 @@ bool efi_is_table_address(unsigned long phys_addr)
 static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock);
 static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init;
 
-int efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
+static int __init efi_memreserve_map_root(void)
+{
+       if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
+               return -ENODEV;
+
+       efi_memreserve_root = memremap(efi.mem_reserve,
+                                      sizeof(*efi_memreserve_root),
+                                      MEMREMAP_WB);
+       if (WARN_ON_ONCE(!efi_memreserve_root))
+               return -ENOMEM;
+       return 0;
+}
+
+int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
 {
        struct linux_efi_memreserve *rsv;
+       int rc;
 
-       if (!efi_memreserve_root)
+       if (efi_memreserve_root == (void *)ULONG_MAX)
                return -ENODEV;
 
+       if (!efi_memreserve_root) {
+               rc = efi_memreserve_map_root();
+               if (rc)
+                       return rc;
+       }
+
        rsv = kmalloc(sizeof(*rsv), GFP_ATOMIC);
        if (!rsv)
                return -ENOMEM;
@@ -993,14 +1013,10 @@ int efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
 
 static int __init efi_memreserve_root_init(void)
 {
-       if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
-               return -ENODEV;
-
-       efi_memreserve_root = memremap(efi.mem_reserve,
-                                      sizeof(*efi_memreserve_root),
-                                      MEMREMAP_WB);
-       if (!efi_memreserve_root)
-               return -ENOMEM;
+       if (efi_memreserve_root)
+               return 0;
+       if (efi_memreserve_map_root())
+               efi_memreserve_root = (void *)ULONG_MAX;
        return 0;
 }
 early_initcall(efi_memreserve_root_init);
index af3a20d..99c99a5 100644 (file)
@@ -46,6 +46,7 @@ config FSI_MASTER_AST_CF
        tristate "FSI master based on Aspeed ColdFire coprocessor"
        depends on GPIOLIB
        depends on GPIO_ASPEED
+       select GENERIC_ALLOCATOR
        ---help---
        This option enables a FSI master using the AST2400 and AST2500 GPIO
        lines driven by the internal ColdFire coprocessor. This requires
index df94021..81dc01a 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/fs.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
-#include <linux/cdev.h>
 #include <linux/list.h>
 
 #include <uapi/linux/fsi.h>
index 71d014e..2c22836 100644 (file)
@@ -168,7 +168,7 @@ static int sirf_set_active(struct sirf_data *data, bool active)
        else
                timeout = SIRF_HIBERNATE_TIMEOUT;
 
-       while (retries-- > 0) {
+       do {
                sirf_pulse_on_off(data);
                ret = sirf_wait_for_power_state(data, active, timeout);
                if (ret < 0) {
@@ -179,9 +179,9 @@ static int sirf_set_active(struct sirf_data *data, bool active)
                }
 
                break;
-       }
+       } while (retries--);
 
-       if (retries == 0)
+       if (retries < 0)
                return -ETIMEDOUT;
 
        return 0;
index 5c1564f..bdb29e5 100644 (file)
@@ -258,7 +258,7 @@ static int davinci_gpio_probe(struct platform_device *pdev)
        chips->chip.set = davinci_gpio_set;
 
        chips->chip.ngpio = ngpio;
-       chips->chip.base = -1;
+       chips->chip.base = pdata->no_auto_base ? pdata->base : -1;
 
 #ifdef CONFIG_OF_GPIO
        chips->chip.of_gpio_n_cells = 2;
index 104b2e0..b0fc116 100644 (file)
@@ -233,7 +233,7 @@ enum amdgpu_kiq_irq {
 
 #define MAX_KIQ_REG_WAIT       5000 /* in usecs, 5ms */
 #define MAX_KIQ_REG_BAILOUT_INTERVAL   5 /* in msecs, 5ms */
-#define MAX_KIQ_REG_TRY 20
+#define MAX_KIQ_REG_TRY 80 /* 20 -> 80 */
 
 int amdgpu_device_ip_set_clockgating_state(void *dev,
                                           enum amd_ip_block_type block_type,
index f9b5423..95f4c41 100644 (file)
@@ -39,6 +39,7 @@ const unsigned int amdgpu_ctx_num_entities[AMDGPU_HW_IP_NUM] = {
        [AMDGPU_HW_IP_UVD_ENC]  =       1,
        [AMDGPU_HW_IP_VCN_DEC]  =       1,
        [AMDGPU_HW_IP_VCN_ENC]  =       1,
+       [AMDGPU_HW_IP_VCN_JPEG] =       1,
 };
 
 static int amdgput_ctx_total_num_entities(void)
index 81732a8..8f3d44e 100644 (file)
@@ -467,9 +467,6 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
        if (!info->return_size || !info->return_pointer)
                return -EINVAL;
 
-       /* Ensure IB tests are run on ring */
-       flush_delayed_work(&adev->late_init_work);
-
        switch (info->query) {
        case AMDGPU_INFO_ACCEL_WORKING:
                ui32 = adev->accel_working;
@@ -950,6 +947,9 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
        struct amdgpu_fpriv *fpriv;
        int r, pasid;
 
+       /* Ensure IB tests are run on ring */
+       flush_delayed_work(&adev->late_init_work);
+
        file_priv->driver_priv = NULL;
 
        r = pm_runtime_get_sync(dev->dev);
index dad0e23..0877ff9 100644 (file)
@@ -181,7 +181,7 @@ static unsigned amdgpu_vm_num_entries(struct amdgpu_device *adev,
 
        if (level == adev->vm_manager.root_level)
                /* For the root directory */
-               return round_up(adev->vm_manager.max_pfn, 1 << shift) >> shift;
+               return round_up(adev->vm_manager.max_pfn, 1ULL << shift) >> shift;
        else if (level != AMDGPU_VM_PTB)
                /* Everything in between */
                return 512;
@@ -1656,9 +1656,11 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
                        if (!amdgpu_vm_pt_descendant(adev, &cursor))
                                return -ENOENT;
                        continue;
-               } else if (frag >= parent_shift) {
+               } else if (frag >= parent_shift &&
+                          cursor.level - 1 != adev->vm_manager.root_level) {
                        /* If the fragment size is even larger than the parent
-                        * shift we should go up one level and check it again.
+                        * shift we should go up one level and check it again
+                        * unless one level up is the root level.
                         */
                        if (!amdgpu_vm_pt_ancestor(&cursor))
                                return -ENOENT;
@@ -1666,10 +1668,10 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
                }
 
                /* Looks good so far, calculate parameters for the update */
-               incr = AMDGPU_GPU_PAGE_SIZE << shift;
+               incr = (uint64_t)AMDGPU_GPU_PAGE_SIZE << shift;
                mask = amdgpu_vm_entries_mask(adev, cursor.level);
                pe_start = ((cursor.pfn >> shift) & mask) * 8;
-               entry_end = (mask + 1) << shift;
+               entry_end = (uint64_t)(mask + 1) << shift;
                entry_end += cursor.pfn & ~(entry_end - 1);
                entry_end = min(entry_end, end);
 
@@ -1682,7 +1684,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
                                              flags | AMDGPU_PTE_FRAG(frag));
 
                        pe_start += nptes * 8;
-                       dst += nptes * AMDGPU_GPU_PAGE_SIZE << shift;
+                       dst += (uint64_t)nptes * AMDGPU_GPU_PAGE_SIZE << shift;
 
                        frag_start = upd_end;
                        if (frag_start >= frag_end) {
index 6d7baf5..21363b2 100644 (file)
@@ -2440,12 +2440,13 @@ static void gfx_v9_0_rlc_start(struct amdgpu_device *adev)
 #endif
 
        WREG32_FIELD15(GC, 0, RLC_CNTL, RLC_ENABLE_F32, 1);
+       udelay(50);
 
        /* carrizo do enable cp interrupt after cp inited */
-       if (!(adev->flags & AMD_IS_APU))
+       if (!(adev->flags & AMD_IS_APU)) {
                gfx_v9_0_enable_gui_idle_interrupt(adev, true);
-
-       udelay(50);
+               udelay(50);
+       }
 
 #ifdef AMDGPU_RLC_DEBUG_RETRY
        /* RLC_GPM_GENERAL_6 : RLC Ucode version */
index 1d3265c..747c068 100644 (file)
@@ -56,6 +56,9 @@ MODULE_FIRMWARE("amdgpu/tonga_mc.bin");
 MODULE_FIRMWARE("amdgpu/polaris11_mc.bin");
 MODULE_FIRMWARE("amdgpu/polaris10_mc.bin");
 MODULE_FIRMWARE("amdgpu/polaris12_mc.bin");
+MODULE_FIRMWARE("amdgpu/polaris11_k_mc.bin");
+MODULE_FIRMWARE("amdgpu/polaris10_k_mc.bin");
+MODULE_FIRMWARE("amdgpu/polaris12_k_mc.bin");
 
 static const u32 golden_settings_tonga_a11[] =
 {
@@ -224,13 +227,39 @@ static int gmc_v8_0_init_microcode(struct amdgpu_device *adev)
                chip_name = "tonga";
                break;
        case CHIP_POLARIS11:
-               chip_name = "polaris11";
+               if (((adev->pdev->device == 0x67ef) &&
+                    ((adev->pdev->revision == 0xe0) ||
+                     (adev->pdev->revision == 0xe5))) ||
+                   ((adev->pdev->device == 0x67ff) &&
+                    ((adev->pdev->revision == 0xcf) ||
+                     (adev->pdev->revision == 0xef) ||
+                     (adev->pdev->revision == 0xff))))
+                       chip_name = "polaris11_k";
+               else if ((adev->pdev->device == 0x67ef) &&
+                        (adev->pdev->revision == 0xe2))
+                       chip_name = "polaris11_k";
+               else
+                       chip_name = "polaris11";
                break;
        case CHIP_POLARIS10:
-               chip_name = "polaris10";
+               if ((adev->pdev->device == 0x67df) &&
+                   ((adev->pdev->revision == 0xe1) ||
+                    (adev->pdev->revision == 0xf7)))
+                       chip_name = "polaris10_k";
+               else
+                       chip_name = "polaris10";
                break;
        case CHIP_POLARIS12:
-               chip_name = "polaris12";
+               if (((adev->pdev->device == 0x6987) &&
+                    ((adev->pdev->revision == 0xc0) ||
+                     (adev->pdev->revision == 0xc3))) ||
+                   ((adev->pdev->device == 0x6981) &&
+                    ((adev->pdev->revision == 0x00) ||
+                     (adev->pdev->revision == 0x01) ||
+                     (adev->pdev->revision == 0x10))))
+                       chip_name = "polaris12_k";
+               else
+                       chip_name = "polaris12";
                break;
        case CHIP_FIJI:
        case CHIP_CARRIZO:
@@ -337,7 +366,7 @@ static int gmc_v8_0_polaris_mc_load_microcode(struct amdgpu_device *adev)
        const struct mc_firmware_header_v1_0 *hdr;
        const __le32 *fw_data = NULL;
        const __le32 *io_mc_regs = NULL;
-       u32 data, vbios_version;
+       u32 data;
        int i, ucode_size, regs_size;
 
        /* Skip MC ucode loading on SR-IOV capable boards.
@@ -348,13 +377,6 @@ static int gmc_v8_0_polaris_mc_load_microcode(struct amdgpu_device *adev)
        if (amdgpu_sriov_bios(adev))
                return 0;
 
-       WREG32(mmMC_SEQ_IO_DEBUG_INDEX, 0x9F);
-       data = RREG32(mmMC_SEQ_IO_DEBUG_DATA);
-       vbios_version = data & 0xf;
-
-       if (vbios_version == 0)
-               return 0;
-
        if (!adev->gmc.fw)
                return -EINVAL;
 
index eae9092..322e09b 100644 (file)
@@ -48,6 +48,7 @@ static void vcn_v1_0_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v1_0_set_jpeg_ring_funcs(struct amdgpu_device *adev);
 static void vcn_v1_0_set_irq_funcs(struct amdgpu_device *adev);
 static void vcn_v1_0_jpeg_ring_set_patch_ring(struct amdgpu_ring *ring, uint32_t ptr);
+static int vcn_v1_0_set_powergating_state(void *handle, enum amd_powergating_state state);
 
 /**
  * vcn_v1_0_early_init - set function pointers
@@ -222,7 +223,7 @@ static int vcn_v1_0_hw_fini(void *handle)
        struct amdgpu_ring *ring = &adev->vcn.ring_dec;
 
        if (RREG32_SOC15(VCN, 0, mmUVD_STATUS))
-               vcn_v1_0_stop(adev);
+               vcn_v1_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
 
        ring->ready = false;
 
index ca92520..5a6edf6 100644 (file)
@@ -2554,9 +2554,9 @@ static void fill_audio_info(struct audio_info *audio_info,
 
        cea_revision = drm_connector->display_info.cea_rev;
 
-       strncpy(audio_info->display_name,
+       strscpy(audio_info->display_name,
                edid_caps->display_name,
-               AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS - 1);
+               AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS);
 
        if (cea_revision >= 3) {
                audio_info->mode_count = edid_caps->audio_mode_count;
@@ -3042,6 +3042,7 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector)
                state->underscan_enable = false;
                state->underscan_hborder = 0;
                state->underscan_vborder = 0;
+               state->max_bpc = 8;
 
                __drm_atomic_helper_connector_reset(connector, &state->base);
        }
@@ -3063,6 +3064,7 @@ amdgpu_dm_connector_atomic_duplicate_state(struct drm_connector *connector)
 
        new_state->freesync_capable = state->freesync_capable;
        new_state->freesync_enable = state->freesync_enable;
+       new_state->max_bpc = state->max_bpc;
 
        return &new_state->base;
 }
@@ -3650,7 +3652,7 @@ amdgpu_dm_create_common_mode(struct drm_encoder *encoder,
        mode->hdisplay = hdisplay;
        mode->vdisplay = vdisplay;
        mode->type &= ~DRM_MODE_TYPE_PREFERRED;
-       strncpy(mode->name, name, DRM_DISPLAY_MODE_LEN);
+       strscpy(mode->name, name, DRM_DISPLAY_MODE_LEN);
 
        return mode;
 
index d02c32a..1b0d209 100644 (file)
@@ -342,10 +342,9 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
                master->connector_id);
 
        aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master);
+       drm_connector_attach_encoder(&aconnector->base,
+                                    &aconnector->mst_encoder->base);
 
-       /*
-        * TODO: understand why this one is needed
-        */
        drm_object_attach_property(
                &connector->base,
                dev->mode_config.path_property,
index b459867..a6bcb90 100644 (file)
@@ -2512,6 +2512,8 @@ static void pplib_apply_display_requirements(
                        dc,
                        context->bw.dce.sclk_khz);
 
+       pp_display_cfg->min_dcfclock_khz = pp_display_cfg->min_engine_clock_khz;
+
        pp_display_cfg->min_engine_clock_deep_sleep_khz
                        = context->bw.dce.sclk_deep_sleep_khz;
 
index 85119c2..a2a7e0e 100644 (file)
@@ -80,7 +80,9 @@ int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr)
        PHM_FUNC_CHECK(hwmgr);
        adev = hwmgr->adev;
 
-       if (smum_is_dpm_running(hwmgr) && !amdgpu_passthrough(adev)) {
+       /* Skip for suspend/resume case */
+       if (smum_is_dpm_running(hwmgr) && !amdgpu_passthrough(adev)
+               && adev->in_suspend) {
                pr_info("dpm has been enabled\n");
                return 0;
        }
index 47ac923..0173d04 100644 (file)
@@ -352,6 +352,9 @@ int hwmgr_handle_task(struct pp_hwmgr *hwmgr, enum amd_pp_task task_id,
 
        switch (task_id) {
        case AMD_PP_TASK_DISPLAY_CONFIG_CHANGE:
+               ret = phm_pre_display_configuration_changed(hwmgr);
+               if (ret)
+                       return ret;
                ret = phm_set_cpu_power_state(hwmgr);
                if (ret)
                        return ret;
index 91ffb7b..5643786 100644 (file)
@@ -265,8 +265,6 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip,
        if (skip)
                return 0;
 
-       phm_pre_display_configuration_changed(hwmgr);
-
        phm_display_configuration_changed(hwmgr);
 
        if (hwmgr->ps)
index 88f6b35..b61a01f 100644 (file)
@@ -3589,8 +3589,10 @@ static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, cons
        }
 
        if (i >= sclk_table->count) {
-               data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
-               sclk_table->dpm_levels[i-1].value = sclk;
+               if (sclk > sclk_table->dpm_levels[i-1].value) {
+                       data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
+                       sclk_table->dpm_levels[i-1].value = sclk;
+               }
        } else {
        /* TODO: Check SCLK in DAL's minimum clocks
         * in case DeepSleep divider update is required.
@@ -3607,8 +3609,10 @@ static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, cons
        }
 
        if (i >= mclk_table->count) {
-               data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
-               mclk_table->dpm_levels[i-1].value = mclk;
+               if (mclk > mclk_table->dpm_levels[i-1].value) {
+                       data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
+                       mclk_table->dpm_levels[i-1].value = mclk;
+               }
        }
 
        if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
index e2bc6e0..79c8624 100644 (file)
@@ -3266,8 +3266,10 @@ static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, co
        }
 
        if (i >= sclk_table->count) {
-               data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
-               sclk_table->dpm_levels[i-1].value = sclk;
+               if (sclk > sclk_table->dpm_levels[i-1].value) {
+                       data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
+                       sclk_table->dpm_levels[i-1].value = sclk;
+               }
        }
 
        for (i = 0; i < mclk_table->count; i++) {
@@ -3276,8 +3278,10 @@ static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, co
        }
 
        if (i >= mclk_table->count) {
-               data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
-               mclk_table->dpm_levels[i-1].value = mclk;
+               if (mclk > mclk_table->dpm_levels[i-1].value) {
+                       data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
+                       mclk_table->dpm_levels[i-1].value = mclk;
+               }
        }
 
        if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display)
index b4eadd4..3367dd3 100644 (file)
@@ -1660,14 +1660,15 @@ static uint32_t vega20_find_highest_dpm_level(
        return i;
 }
 
-static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr)
+static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask)
 {
        struct vega20_hwmgr *data =
                        (struct vega20_hwmgr *)(hwmgr->backend);
        uint32_t min_freq;
        int ret = 0;
 
-       if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
+       if (data->smu_features[GNLD_DPM_GFXCLK].enabled &&
+          (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
                min_freq = data->dpm_table.gfx_table.dpm_state.soft_min_level;
                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
                                        hwmgr, PPSMC_MSG_SetSoftMinByFreq,
@@ -1676,7 +1677,8 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr)
                                        return ret);
        }
 
-       if (data->smu_features[GNLD_DPM_UCLK].enabled) {
+       if (data->smu_features[GNLD_DPM_UCLK].enabled &&
+          (feature_mask & FEATURE_DPM_UCLK_MASK)) {
                min_freq = data->dpm_table.mem_table.dpm_state.soft_min_level;
                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
                                        hwmgr, PPSMC_MSG_SetSoftMinByFreq,
@@ -1692,7 +1694,8 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr)
                                        return ret);
        }
 
-       if (data->smu_features[GNLD_DPM_UVD].enabled) {
+       if (data->smu_features[GNLD_DPM_UVD].enabled &&
+          (feature_mask & FEATURE_DPM_UVD_MASK)) {
                min_freq = data->dpm_table.vclk_table.dpm_state.soft_min_level;
 
                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
@@ -1710,7 +1713,8 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr)
                                        return ret);
        }
 
-       if (data->smu_features[GNLD_DPM_VCE].enabled) {
+       if (data->smu_features[GNLD_DPM_VCE].enabled &&
+          (feature_mask & FEATURE_DPM_VCE_MASK)) {
                min_freq = data->dpm_table.eclk_table.dpm_state.soft_min_level;
 
                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
@@ -1720,7 +1724,8 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr)
                                        return ret);
        }
 
-       if (data->smu_features[GNLD_DPM_SOCCLK].enabled) {
+       if (data->smu_features[GNLD_DPM_SOCCLK].enabled &&
+          (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
                min_freq = data->dpm_table.soc_table.dpm_state.soft_min_level;
 
                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
@@ -1733,14 +1738,15 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr)
        return ret;
 }
 
-static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
+static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask)
 {
        struct vega20_hwmgr *data =
                        (struct vega20_hwmgr *)(hwmgr->backend);
        uint32_t max_freq;
        int ret = 0;
 
-       if (data->smu_features[GNLD_DPM_GFXCLK].enabled) {
+       if (data->smu_features[GNLD_DPM_GFXCLK].enabled &&
+          (feature_mask & FEATURE_DPM_GFXCLK_MASK)) {
                max_freq = data->dpm_table.gfx_table.dpm_state.soft_max_level;
 
                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
@@ -1750,7 +1756,8 @@ static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
                                        return ret);
        }
 
-       if (data->smu_features[GNLD_DPM_UCLK].enabled) {
+       if (data->smu_features[GNLD_DPM_UCLK].enabled &&
+          (feature_mask & FEATURE_DPM_UCLK_MASK)) {
                max_freq = data->dpm_table.mem_table.dpm_state.soft_max_level;
 
                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
@@ -1760,7 +1767,8 @@ static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
                                        return ret);
        }
 
-       if (data->smu_features[GNLD_DPM_UVD].enabled) {
+       if (data->smu_features[GNLD_DPM_UVD].enabled &&
+          (feature_mask & FEATURE_DPM_UVD_MASK)) {
                max_freq = data->dpm_table.vclk_table.dpm_state.soft_max_level;
 
                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
@@ -1777,7 +1785,8 @@ static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
                                        return ret);
        }
 
-       if (data->smu_features[GNLD_DPM_VCE].enabled) {
+       if (data->smu_features[GNLD_DPM_VCE].enabled &&
+          (feature_mask & FEATURE_DPM_VCE_MASK)) {
                max_freq = data->dpm_table.eclk_table.dpm_state.soft_max_level;
 
                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
@@ -1787,7 +1796,8 @@ static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
                                        return ret);
        }
 
-       if (data->smu_features[GNLD_DPM_SOCCLK].enabled) {
+       if (data->smu_features[GNLD_DPM_SOCCLK].enabled &&
+          (feature_mask & FEATURE_DPM_SOCCLK_MASK)) {
                max_freq = data->dpm_table.soc_table.dpm_state.soft_max_level;
 
                PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
@@ -2126,12 +2136,12 @@ static int vega20_force_dpm_highest(struct pp_hwmgr *hwmgr)
                data->dpm_table.mem_table.dpm_state.soft_max_level =
                data->dpm_table.mem_table.dpm_levels[soft_level].value;
 
-       ret = vega20_upload_dpm_min_level(hwmgr);
+       ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload boot level to highest!",
                        return ret);
 
-       ret = vega20_upload_dpm_max_level(hwmgr);
+       ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload dpm max level to highest!",
                        return ret);
@@ -2158,12 +2168,12 @@ static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr)
                data->dpm_table.mem_table.dpm_state.soft_max_level =
                data->dpm_table.mem_table.dpm_levels[soft_level].value;
 
-       ret = vega20_upload_dpm_min_level(hwmgr);
+       ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload boot level to highest!",
                        return ret);
 
-       ret = vega20_upload_dpm_max_level(hwmgr);
+       ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload dpm max level to highest!",
                        return ret);
@@ -2176,12 +2186,12 @@ static int vega20_unforce_dpm_levels(struct pp_hwmgr *hwmgr)
 {
        int ret = 0;
 
-       ret = vega20_upload_dpm_min_level(hwmgr);
+       ret = vega20_upload_dpm_min_level(hwmgr, 0xFFFFFFFF);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload DPM Bootup Levels!",
                        return ret);
 
-       ret = vega20_upload_dpm_max_level(hwmgr);
+       ret = vega20_upload_dpm_max_level(hwmgr, 0xFFFFFFFF);
        PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload DPM Max Levels!",
                        return ret);
@@ -2239,12 +2249,12 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
                data->dpm_table.gfx_table.dpm_state.soft_max_level =
                        data->dpm_table.gfx_table.dpm_levels[soft_max_level].value;
 
-               ret = vega20_upload_dpm_min_level(hwmgr);
+               ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK);
                PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload boot level to lowest!",
                        return ret);
 
-               ret = vega20_upload_dpm_max_level(hwmgr);
+               ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK);
                PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload dpm max level to highest!",
                        return ret);
@@ -2259,12 +2269,12 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
                data->dpm_table.mem_table.dpm_state.soft_max_level =
                        data->dpm_table.mem_table.dpm_levels[soft_max_level].value;
 
-               ret = vega20_upload_dpm_min_level(hwmgr);
+               ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_UCLK_MASK);
                PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload boot level to lowest!",
                        return ret);
 
-               ret = vega20_upload_dpm_max_level(hwmgr);
+               ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_UCLK_MASK);
                PP_ASSERT_WITH_CODE(!ret,
                        "Failed to upload dpm max level to highest!",
                        return ret);
index 0cd827e..de26df0 100644 (file)
@@ -263,6 +263,7 @@ static void ast_fbdev_destroy(struct drm_device *dev,
 {
        struct ast_framebuffer *afb = &afbdev->afb;
 
+       drm_crtc_force_disable_all(dev);
        drm_fb_helper_unregister_fbi(&afbdev->helper);
 
        if (afb->obj) {
index dac3558..373700c 100644 (file)
@@ -583,7 +583,8 @@ void ast_driver_unload(struct drm_device *dev)
        drm_mode_config_cleanup(dev);
 
        ast_mm_fini(ast);
-       pci_iounmap(dev->pdev, ast->ioregs);
+       if (ast->ioregs != ast->regs + AST_IO_MM_OFFSET)
+               pci_iounmap(dev->pdev, ast->ioregs);
        pci_iounmap(dev->pdev, ast->regs);
        kfree(ast);
 }
index 7c6ac3c..8bb355d 100644 (file)
@@ -973,9 +973,21 @@ static int get_clock(void *i2c_priv)
 {
        struct ast_i2c_chan *i2c = i2c_priv;
        struct ast_private *ast = i2c->dev->dev_private;
-       uint32_t val;
+       uint32_t val, val2, count, pass;
+
+       count = 0;
+       pass = 0;
+       val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
+       do {
+               val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
+               if (val == val2) {
+                       pass++;
+               } else {
+                       pass = 0;
+                       val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
+               }
+       } while ((pass < 5) && (count++ < 0x10000));
 
-       val = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4;
        return val & 1 ? 1 : 0;
 }
 
@@ -983,9 +995,21 @@ static int get_data(void *i2c_priv)
 {
        struct ast_i2c_chan *i2c = i2c_priv;
        struct ast_private *ast = i2c->dev->dev_private;
-       uint32_t val;
+       uint32_t val, val2, count, pass;
+
+       count = 0;
+       pass = 0;
+       val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
+       do {
+               val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
+               if (val == val2) {
+                       pass++;
+               } else {
+                       pass = 0;
+                       val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
+               }
+       } while ((pass < 5) && (count++ < 0x10000));
 
-       val = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5;
        return val & 1 ? 1 : 0;
 }
 
@@ -998,7 +1022,7 @@ static void set_clock(void *i2c_priv, int clock)
 
        for (i = 0; i < 0x10000; i++) {
                ujcrb7 = ((clock & 0x01) ? 0 : 1);
-               ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xfe, ujcrb7);
+               ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf4, ujcrb7);
                jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01);
                if (ujcrb7 == jtemp)
                        break;
@@ -1014,7 +1038,7 @@ static void set_data(void *i2c_priv, int data)
 
        for (i = 0; i < 0x10000; i++) {
                ujcrb7 = ((data & 0x01) ? 0 : 1) << 2;
-               ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xfb, ujcrb7);
+               ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf1, ujcrb7);
                jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04);
                if (ujcrb7 == jtemp)
                        break;
index 680566d..1024396 100644 (file)
@@ -54,7 +54,7 @@
 #define SN_AUX_ADDR_7_0_REG                    0x76
 #define SN_AUX_LENGTH_REG                      0x77
 #define SN_AUX_CMD_REG                         0x78
-#define  AUX_CMD_SEND                          BIT(1)
+#define  AUX_CMD_SEND                          BIT(0)
 #define  AUX_CMD_REQ(x)                                ((x) << 4)
 #define SN_AUX_RDATA_REG(x)                    (0x79 + (x))
 #define SN_SSC_CONFIG_REG                      0x93
index d9c0f75..1669c42 100644 (file)
@@ -142,6 +142,7 @@ static int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
 
        lockdep_assert_held_once(&dev->master_mutex);
 
+       WARN_ON(fpriv->is_master);
        old_master = fpriv->master;
        fpriv->master = drm_master_create(dev);
        if (!fpriv->master) {
@@ -170,6 +171,7 @@ out_err:
        /* drop references and restore old master on failure */
        drm_master_put(&fpriv->master);
        fpriv->master = old_master;
+       fpriv->is_master = 0;
 
        return ret;
 }
index dd852a2..9d64f87 100644 (file)
@@ -71,7 +71,7 @@ MODULE_PARM_DESC(drm_fbdev_overalloc,
 #if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
 static bool drm_leak_fbdev_smem = false;
 module_param_unsafe(drm_leak_fbdev_smem, bool, 0600);
-MODULE_PARM_DESC(fbdev_emulation,
+MODULE_PARM_DESC(drm_leak_fbdev_smem,
                 "Allow unsafe leaking fbdev physical smem address [default=false]");
 #endif
 
index 0c4eb4a..51e06de 100644 (file)
@@ -104,6 +104,8 @@ struct device *drm_sysfs_minor_alloc(struct drm_minor *minor);
 int drm_sysfs_connector_add(struct drm_connector *connector);
 void drm_sysfs_connector_remove(struct drm_connector *connector);
 
+void drm_sysfs_lease_event(struct drm_device *dev);
+
 /* drm_gem.c */
 int drm_gem_init(struct drm_device *dev);
 void drm_gem_destroy(struct drm_device *dev);
index 24a177e..c61680a 100644 (file)
@@ -296,7 +296,7 @@ void drm_lease_destroy(struct drm_master *master)
 
        if (master->lessor) {
                /* Tell the master to check the lessee list */
-               drm_sysfs_hotplug_event(dev);
+               drm_sysfs_lease_event(dev);
                drm_master_put(&master->lessor);
        }
 
index b3c1daa..ecb7b33 100644 (file)
@@ -301,6 +301,16 @@ void drm_sysfs_connector_remove(struct drm_connector *connector)
        connector->kdev = NULL;
 }
 
+void drm_sysfs_lease_event(struct drm_device *dev)
+{
+       char *event_string = "LEASE=1";
+       char *envp[] = { event_string, NULL };
+
+       DRM_DEBUG("generating lease event\n");
+
+       kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
+}
+
 /**
  * drm_sysfs_hotplug_event - generate a DRM uevent
  * @dev: DRM device
index fe75402..359d37d 100644 (file)
@@ -61,10 +61,12 @@ static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm)
        }
 
        mutex_lock(&dev_priv->drm.struct_mutex);
+       mmio_hw_access_pre(dev_priv);
        ret = i915_gem_gtt_insert(&dev_priv->ggtt.vm, node,
                                  size, I915_GTT_PAGE_SIZE,
                                  I915_COLOR_UNEVICTABLE,
                                  start, end, flags);
+       mmio_hw_access_post(dev_priv);
        mutex_unlock(&dev_priv->drm.struct_mutex);
        if (ret)
                gvt_err("fail to alloc %s gm space from host\n",
index 58e166e..c7103dd 100644 (file)
@@ -2447,10 +2447,11 @@ static void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu)
 
 static void intel_vgpu_destroy_ggtt_mm(struct intel_vgpu *vgpu)
 {
-       struct intel_gvt_partial_pte *pos;
+       struct intel_gvt_partial_pte *pos, *next;
 
-       list_for_each_entry(pos,
-                       &vgpu->gtt.ggtt_mm->ggtt_mm.partial_pte_list, list) {
+       list_for_each_entry_safe(pos, next,
+                                &vgpu->gtt.ggtt_mm->ggtt_mm.partial_pte_list,
+                                list) {
                gvt_dbg_mm("partial PTE update on hold 0x%lx : 0x%llx\n",
                        pos->offset, pos->data);
                kfree(pos);
index 36a5147..d6e02c1 100644 (file)
@@ -158,6 +158,8 @@ static void load_render_mocs(struct drm_i915_private *dev_priv)
        int ring_id, i;
 
        for (ring_id = 0; ring_id < ARRAY_SIZE(regs); ring_id++) {
+               if (!HAS_ENGINE(dev_priv, ring_id))
+                       continue;
                offset.reg = regs[ring_id];
                for (i = 0; i < GEN9_MOCS_SIZE; i++) {
                        gen9_render_mocs.control_table[ring_id][i] =
index 0552020..191b314 100644 (file)
@@ -45,6 +45,7 @@ struct meson_crtc {
        struct drm_crtc base;
        struct drm_pending_vblank_event *event;
        struct meson_drm *priv;
+       bool enabled;
 };
 #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
 
@@ -80,8 +81,7 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {
 
 };
 
-static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
-                                    struct drm_crtc_state *old_state)
+static void meson_crtc_enable(struct drm_crtc *crtc)
 {
        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
        struct drm_crtc_state *crtc_state = crtc->state;
@@ -101,6 +101,22 @@ static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
        writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
                            priv->io_base + _REG(VPP_MISC));
 
+       drm_crtc_vblank_on(crtc);
+
+       meson_crtc->enabled = true;
+}
+
+static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
+                                    struct drm_crtc_state *old_state)
+{
+       struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+       struct meson_drm *priv = meson_crtc->priv;
+
+       DRM_DEBUG_DRIVER("\n");
+
+       if (!meson_crtc->enabled)
+               meson_crtc_enable(crtc);
+
        priv->viu.osd1_enabled = true;
 }
 
@@ -110,6 +126,8 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
        struct meson_drm *priv = meson_crtc->priv;
 
+       drm_crtc_vblank_off(crtc);
+
        priv->viu.osd1_enabled = false;
        priv->viu.osd1_commit = false;
 
@@ -124,6 +142,8 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
 
                crtc->state->event = NULL;
        }
+
+       meson_crtc->enabled = false;
 }
 
 static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -132,6 +152,9 @@ static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
        unsigned long flags;
 
+       if (crtc->state->enable && !meson_crtc->enabled)
+               meson_crtc_enable(crtc);
+
        if (crtc->state->event) {
                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 
index df7247c..2cb2ad2 100644 (file)
@@ -706,6 +706,7 @@ static const struct regmap_config meson_dw_hdmi_regmap_config = {
        .reg_read = meson_dw_hdmi_reg_read,
        .reg_write = meson_dw_hdmi_reg_write,
        .max_register = 0x10000,
+       .fast_io = true,
 };
 
 static bool meson_hdmi_connector_is_available(struct device *dev)
index acbbad3..be76f3d 100644 (file)
@@ -71,6 +71,7 @@
  */
 
 /* HHI Registers */
+#define HHI_GCLK_MPEG2         0x148 /* 0x52 offset in data sheet */
 #define HHI_VDAC_CNTL0         0x2F4 /* 0xbd offset in data sheet */
 #define HHI_VDAC_CNTL1         0x2F8 /* 0xbe offset in data sheet */
 #define HHI_HDMI_PHY_CNTL0     0x3a0 /* 0xe8 offset in data sheet */
@@ -714,6 +715,7 @@ struct meson_hdmi_venc_vic_mode {
        { 5, &meson_hdmi_encp_mode_1080i60 },
        { 20, &meson_hdmi_encp_mode_1080i50 },
        { 32, &meson_hdmi_encp_mode_1080p24 },
+       { 33, &meson_hdmi_encp_mode_1080p50 },
        { 34, &meson_hdmi_encp_mode_1080p30 },
        { 31, &meson_hdmi_encp_mode_1080p50 },
        { 16, &meson_hdmi_encp_mode_1080p60 },
@@ -1530,10 +1532,12 @@ unsigned int meson_venci_get_field(struct meson_drm *priv)
 void meson_venc_enable_vsync(struct meson_drm *priv)
 {
        writel_relaxed(2, priv->io_base + _REG(VENC_INTCTRL));
+       regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), BIT(25));
 }
 
 void meson_venc_disable_vsync(struct meson_drm *priv)
 {
+       regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), 0);
        writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL));
 }
 
index 6bcfa52..26a0857 100644 (file)
@@ -184,18 +184,18 @@ void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
        if (lut_sel == VIU_LUT_OSD_OETF) {
                writel(0, priv->io_base + _REG(addr_port));
 
-               for (i = 0; i < 20; i++)
+               for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
                        writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
                                priv->io_base + _REG(data_port));
 
                writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
                        priv->io_base + _REG(data_port));
 
-               for (i = 0; i < 20; i++)
+               for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
                        writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
                                priv->io_base + _REG(data_port));
 
-               for (i = 0; i < 20; i++)
+               for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
                        writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
                                priv->io_base + _REG(data_port));
 
@@ -211,18 +211,18 @@ void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
        } else if (lut_sel == VIU_LUT_OSD_EOTF) {
                writel(0, priv->io_base + _REG(addr_port));
 
-               for (i = 0; i < 20; i++)
+               for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
                        writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
                                priv->io_base + _REG(data_port));
 
                writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
                        priv->io_base + _REG(data_port));
 
-               for (i = 0; i < 20; i++)
+               for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
                        writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
                                priv->io_base + _REG(data_port));
 
-               for (i = 0; i < 20; i++)
+               for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
                        writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
                                priv->io_base + _REG(data_port));
 
index d4530d6..ca169f0 100644 (file)
@@ -1594,7 +1594,6 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
                                NULL);
 
        drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs);
-       plane->crtc = crtc;
 
        /* save user friendly CRTC name for later */
        snprintf(dpu_crtc->name, DPU_CRTC_NAME_SIZE, "crtc%u", crtc->base.id);
index 96cdf06..d31d828 100644 (file)
@@ -488,8 +488,6 @@ static void dpu_encoder_destroy(struct drm_encoder *drm_enc)
 
        drm_encoder_cleanup(drm_enc);
        mutex_destroy(&dpu_enc->enc_lock);
-
-       kfree(dpu_enc);
 }
 
 void dpu_encoder_helper_split_config(
index bfcd165..d743e7c 100644 (file)
@@ -216,7 +216,7 @@ static const struct dpu_format dpu_format_map[] = {
        INTERLEAVED_RGB_FMT(XBGR8888,
                COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
                C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
-               true, 4, 0,
+               false, 4, 0,
                DPU_FETCH_LINEAR, 1),
 
        INTERLEAVED_RGB_FMT(RGBA8888,
index 4c03f0b..41bec57 100644 (file)
@@ -39,6 +39,8 @@
 #define DSI_PIXEL_PLL_CLK              1
 #define NUM_PROVIDED_CLKS              2
 
+#define VCO_REF_CLK_RATE               19200000
+
 struct dsi_pll_regs {
        u32 pll_prop_gain_rate;
        u32 pll_lockdet_rate;
@@ -316,7 +318,7 @@ static int dsi_pll_10nm_vco_set_rate(struct clk_hw *hw, unsigned long rate,
            parent_rate);
 
        pll_10nm->vco_current_rate = rate;
-       pll_10nm->vco_ref_clk_rate = parent_rate;
+       pll_10nm->vco_ref_clk_rate = VCO_REF_CLK_RATE;
 
        dsi_pll_setup_config(pll_10nm);
 
index c79659c..adbdce3 100644 (file)
@@ -332,6 +332,12 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
                goto fail;
        }
 
+       ret = msm_hdmi_hpd_enable(hdmi->connector);
+       if (ret < 0) {
+               DRM_DEV_ERROR(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
+               goto fail;
+       }
+
        encoder->bridge = hdmi->bridge;
 
        priv->bridges[priv->num_bridges++]       = hdmi->bridge;
@@ -571,7 +577,7 @@ static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
        struct drm_device *drm = dev_get_drvdata(master);
        struct msm_drm_private *priv = drm->dev_private;
-       static struct hdmi_platform_config *hdmi_cfg;
+       struct hdmi_platform_config *hdmi_cfg;
        struct hdmi *hdmi;
        struct device_node *of_node = dev->of_node;
        int i, err;
index accc9a6..5c5df6a 100644 (file)
@@ -245,6 +245,7 @@ void msm_hdmi_bridge_destroy(struct drm_bridge *bridge);
 
 void msm_hdmi_connector_irq(struct drm_connector *connector);
 struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi);
+int msm_hdmi_hpd_enable(struct drm_connector *connector);
 
 /*
  * i2c adapter for ddc:
index e9c9a0a..30e908d 100644 (file)
@@ -167,8 +167,9 @@ static void enable_hpd_clocks(struct hdmi *hdmi, bool enable)
        }
 }
 
-static int hpd_enable(struct hdmi_connector *hdmi_connector)
+int msm_hdmi_hpd_enable(struct drm_connector *connector)
 {
+       struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
        struct hdmi *hdmi = hdmi_connector->hdmi;
        const struct hdmi_platform_config *config = hdmi->config;
        struct device *dev = &hdmi->pdev->dev;
@@ -450,7 +451,6 @@ struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
 {
        struct drm_connector *connector = NULL;
        struct hdmi_connector *hdmi_connector;
-       int ret;
 
        hdmi_connector = kzalloc(sizeof(*hdmi_connector), GFP_KERNEL);
        if (!hdmi_connector)
@@ -471,12 +471,6 @@ struct drm_connector *msm_hdmi_connector_init(struct hdmi *hdmi)
        connector->interlace_allowed = 0;
        connector->doublescan_allowed = 0;
 
-       ret = hpd_enable(hdmi_connector);
-       if (ret) {
-               dev_err(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
-               return ERR_PTR(ret);
-       }
-
        drm_connector_attach_encoder(connector, hdmi->encoder);
 
        return connector;
index 4bcdeca..2088a20 100644 (file)
@@ -34,7 +34,12 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev,
                if (!new_crtc_state->active)
                        continue;
 
+               if (drm_crtc_vblank_get(crtc))
+                       continue;
+
                kms->funcs->wait_for_crtc_commit_done(kms, crtc);
+
+               drm_crtc_vblank_put(crtc);
        }
 }
 
index f0da0d3..d756436 100644 (file)
@@ -84,7 +84,7 @@ static int msm_gpu_open(struct inode *inode, struct file *file)
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
        if (ret)
-               return ret;
+               goto free_priv;
 
        pm_runtime_get_sync(&gpu->pdev->dev);
        show_priv->state = gpu->funcs->gpu_state_get(gpu);
@@ -94,13 +94,20 @@ static int msm_gpu_open(struct inode *inode, struct file *file)
 
        if (IS_ERR(show_priv->state)) {
                ret = PTR_ERR(show_priv->state);
-               kfree(show_priv);
-               return ret;
+               goto free_priv;
        }
 
        show_priv->dev = dev;
 
-       return single_open(file, msm_gpu_show, show_priv);
+       ret = single_open(file, msm_gpu_show, show_priv);
+       if (ret)
+               goto free_priv;
+
+       return 0;
+
+free_priv:
+       kfree(show_priv);
+       return ret;
 }
 
 static const struct file_operations msm_gpu_fops = {
index 4904d0d..dcff812 100644 (file)
@@ -553,17 +553,18 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
                        kthread_run(kthread_worker_fn,
                                &priv->disp_thread[i].worker,
                                "crtc_commit:%d", priv->disp_thread[i].crtc_id);
-               ret = sched_setscheduler(priv->disp_thread[i].thread,
-                                                       SCHED_FIFO, &param);
-               if (ret)
-                       pr_warn("display thread priority update failed: %d\n",
-                                                                       ret);
-
                if (IS_ERR(priv->disp_thread[i].thread)) {
                        dev_err(dev, "failed to create crtc_commit kthread\n");
                        priv->disp_thread[i].thread = NULL;
+                       goto err_msm_uninit;
                }
 
+               ret = sched_setscheduler(priv->disp_thread[i].thread,
+                                        SCHED_FIFO, &param);
+               if (ret)
+                       dev_warn(dev, "disp_thread set priority failed: %d\n",
+                                ret);
+
                /* initialize event thread */
                priv->event_thread[i].crtc_id = priv->crtcs[i]->base.id;
                kthread_init_worker(&priv->event_thread[i].worker);
@@ -572,6 +573,12 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
                        kthread_run(kthread_worker_fn,
                                &priv->event_thread[i].worker,
                                "crtc_event:%d", priv->event_thread[i].crtc_id);
+               if (IS_ERR(priv->event_thread[i].thread)) {
+                       dev_err(dev, "failed to create crtc_event kthread\n");
+                       priv->event_thread[i].thread = NULL;
+                       goto err_msm_uninit;
+               }
+
                /**
                 * event thread should also run at same priority as disp_thread
                 * because it is handling frame_done events. A lower priority
@@ -580,34 +587,10 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
                 * failure at crtc commit level.
                 */
                ret = sched_setscheduler(priv->event_thread[i].thread,
-                                                       SCHED_FIFO, &param);
+                                        SCHED_FIFO, &param);
                if (ret)
-                       pr_warn("display event thread priority update failed: %d\n",
-                                                                       ret);
-
-               if (IS_ERR(priv->event_thread[i].thread)) {
-                       dev_err(dev, "failed to create crtc_event kthread\n");
-                       priv->event_thread[i].thread = NULL;
-               }
-
-               if ((!priv->disp_thread[i].thread) ||
-                               !priv->event_thread[i].thread) {
-                       /* clean up previously created threads if any */
-                       for ( ; i >= 0; i--) {
-                               if (priv->disp_thread[i].thread) {
-                                       kthread_stop(
-                                               priv->disp_thread[i].thread);
-                                       priv->disp_thread[i].thread = NULL;
-                               }
-
-                               if (priv->event_thread[i].thread) {
-                                       kthread_stop(
-                                               priv->event_thread[i].thread);
-                                       priv->event_thread[i].thread = NULL;
-                               }
-                       }
-                       goto err_msm_uninit;
-               }
+                       dev_warn(dev, "event_thread set priority failed:%d\n",
+                                ret);
        }
 
        ret = drm_vblank_init(ddev, priv->num_crtcs);
index 7a7923e..6942604 100644 (file)
@@ -317,6 +317,9 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
        uint32_t *ptr;
        int ret = 0;
 
+       if (!nr_relocs)
+               return 0;
+
        if (offset % 4) {
                DRM_ERROR("non-aligned cmdstream buffer: %u\n", offset);
                return -EINVAL;
@@ -410,7 +413,6 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
        struct msm_file_private *ctx = file->driver_priv;
        struct msm_gem_submit *submit;
        struct msm_gpu *gpu = priv->gpu;
-       struct dma_fence *in_fence = NULL;
        struct sync_file *sync_file = NULL;
        struct msm_gpu_submitqueue *queue;
        struct msm_ringbuffer *ring;
@@ -443,6 +445,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
        ring = gpu->rb[queue->prio];
 
        if (args->flags & MSM_SUBMIT_FENCE_FD_IN) {
+               struct dma_fence *in_fence;
+
                in_fence = sync_file_get_fence(args->fence_fd);
 
                if (!in_fence)
@@ -452,11 +456,13 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
                 * Wait if the fence is from a foreign context, or if the fence
                 * array contains any fence from a foreign context.
                 */
-               if (!dma_fence_match_context(in_fence, ring->fctx->context)) {
+               ret = 0;
+               if (!dma_fence_match_context(in_fence, ring->fctx->context))
                        ret = dma_fence_wait(in_fence, true);
-                       if (ret)
-                               return ret;
-               }
+
+               dma_fence_put(in_fence);
+               if (ret)
+                       return ret;
        }
 
        ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -582,8 +588,6 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
        }
 
 out:
-       if (in_fence)
-               dma_fence_put(in_fence);
        submit_cleanup(submit);
        if (ret)
                msm_gem_submit_free(submit);
index 11aac83..2b7c894 100644 (file)
@@ -345,6 +345,10 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
 {
        struct msm_gpu_state *state;
 
+       /* Check if the target supports capturing crash state */
+       if (!gpu->funcs->gpu_state_get)
+               return;
+
        /* Only save one crash state at a time */
        if (gpu->crashstate)
                return;
@@ -434,10 +438,9 @@ static void recover_worker(struct work_struct *work)
        if (submit) {
                struct task_struct *task;
 
-               rcu_read_lock();
-               task = pid_task(submit->pid, PIDTYPE_PID);
+               task = get_pid_task(submit->pid, PIDTYPE_PID);
                if (task) {
-                       comm = kstrdup(task->comm, GFP_ATOMIC);
+                       comm = kstrdup(task->comm, GFP_KERNEL);
 
                        /*
                         * So slightly annoying, in other paths like
@@ -450,10 +453,10 @@ static void recover_worker(struct work_struct *work)
                         * about the submit going away.
                         */
                        mutex_unlock(&dev->struct_mutex);
-                       cmd = kstrdup_quotable_cmdline(task, GFP_ATOMIC);
+                       cmd = kstrdup_quotable_cmdline(task, GFP_KERNEL);
+                       put_task_struct(task);
                        mutex_lock(&dev->struct_mutex);
                }
-               rcu_read_unlock();
 
                if (comm && cmd) {
                        dev_err(dev->dev, "%s: offending task: %s (%s)\n",
index b23d336..2a90aa4 100644 (file)
@@ -66,7 +66,7 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
 //     pm_runtime_get_sync(mmu->dev);
        ret = iommu_map_sg(iommu->domain, iova, sgt->sgl, sgt->nents, prot);
 //     pm_runtime_put_sync(mmu->dev);
-       WARN_ON(ret < 0);
+       WARN_ON(!ret);
 
        return (ret == len) ? 0 : -EINVAL;
 }
index cca9334..0c2c8d2 100644 (file)
@@ -316,10 +316,11 @@ static void snapshot_buf(struct msm_rd_state *rd,
                uint64_t iova, uint32_t size)
 {
        struct msm_gem_object *obj = submit->bos[idx].obj;
+       unsigned offset = 0;
        const char *buf;
 
        if (iova) {
-               buf += iova - submit->bos[idx].iova;
+               offset = iova - submit->bos[idx].iova;
        } else {
                iova = submit->bos[idx].iova;
                size = obj->base.size;
@@ -340,6 +341,8 @@ static void snapshot_buf(struct msm_rd_state *rd,
        if (IS_ERR(buf))
                return;
 
+       buf += offset;
+
        rd_write_section(rd, RD_BUFFER_CONTENTS, buf, size);
 
        msm_gem_put_vaddr(&obj->base);
index 1f8161b..4651208 100644 (file)
@@ -177,6 +177,7 @@ static int panel_dpi_probe(struct platform_device *pdev)
        dssdev->type = OMAP_DISPLAY_TYPE_DPI;
        dssdev->owner = THIS_MODULE;
        dssdev->of_ports = BIT(0);
+       drm_bus_flags_from_videomode(&ddata->vm, &dssdev->bus_flags);
 
        omapdss_display_init(dssdev);
        omapdss_device_register(dssdev);
index 0a485c5..00a9c2a 100644 (file)
@@ -5418,9 +5418,15 @@ static int dsi_probe(struct platform_device *pdev)
                dsi->num_lanes_supported = 3;
        }
 
+       r = of_platform_populate(dev->of_node, NULL, NULL, dev);
+       if (r) {
+               DSSERR("Failed to populate DSI child devices: %d\n", r);
+               goto err_pm_disable;
+       }
+
        r = dsi_init_output(dsi);
        if (r)
-               goto err_pm_disable;
+               goto err_of_depopulate;
 
        r = dsi_probe_of(dsi);
        if (r) {
@@ -5428,22 +5434,16 @@ static int dsi_probe(struct platform_device *pdev)
                goto err_uninit_output;
        }
 
-       r = of_platform_populate(dev->of_node, NULL, NULL, dev);
-       if (r) {
-               DSSERR("Failed to populate DSI child devices: %d\n", r);
-               goto err_uninit_output;
-       }
-
        r = component_add(&pdev->dev, &dsi_component_ops);
        if (r)
-               goto err_of_depopulate;
+               goto err_uninit_output;
 
        return 0;
 
-err_of_depopulate:
-       of_platform_depopulate(dev);
 err_uninit_output:
        dsi_uninit_output(dsi);
+err_of_depopulate:
+       of_platform_depopulate(dev);
 err_pm_disable:
        pm_runtime_disable(dev);
        return r;
index 1f698a9..33e15cb 100644 (file)
@@ -432,7 +432,7 @@ struct omap_dss_device {
        const struct omap_dss_driver *driver;
        const struct omap_dss_device_ops *ops;
        unsigned long ops_flags;
-       unsigned long bus_flags;
+       u32 bus_flags;
 
        /* helper variable for driver suspend/resume */
        bool activate_after_resume;
index 452e625..933ebc9 100644 (file)
@@ -52,17 +52,44 @@ static const struct drm_encoder_funcs omap_encoder_funcs = {
        .destroy = omap_encoder_destroy,
 };
 
+static void omap_encoder_hdmi_mode_set(struct drm_encoder *encoder,
+                                      struct drm_display_mode *adjusted_mode)
+{
+       struct drm_device *dev = encoder->dev;
+       struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+       struct omap_dss_device *dssdev = omap_encoder->output;
+       struct drm_connector *connector;
+       bool hdmi_mode;
+
+       hdmi_mode = false;
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               if (connector->encoder == encoder) {
+                       hdmi_mode = omap_connector_get_hdmi_mode(connector);
+                       break;
+               }
+       }
+
+       if (dssdev->ops->hdmi.set_hdmi_mode)
+               dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode);
+
+       if (hdmi_mode && dssdev->ops->hdmi.set_infoframe) {
+               struct hdmi_avi_infoframe avi;
+               int r;
+
+               r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode,
+                                                            false);
+               if (r == 0)
+                       dssdev->ops->hdmi.set_infoframe(dssdev, &avi);
+       }
+}
+
 static void omap_encoder_mode_set(struct drm_encoder *encoder,
                                  struct drm_display_mode *mode,
                                  struct drm_display_mode *adjusted_mode)
 {
-       struct drm_device *dev = encoder->dev;
        struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-       struct drm_connector *connector;
        struct omap_dss_device *dssdev;
        struct videomode vm = { 0 };
-       bool hdmi_mode;
-       int r;
 
        drm_display_mode_to_videomode(adjusted_mode, &vm);
 
@@ -112,27 +139,8 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
        }
 
        /* Set the HDMI mode and HDMI infoframe if applicable. */
-       hdmi_mode = false;
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               if (connector->encoder == encoder) {
-                       hdmi_mode = omap_connector_get_hdmi_mode(connector);
-                       break;
-               }
-       }
-
-       dssdev = omap_encoder->output;
-
-       if (dssdev->ops->hdmi.set_hdmi_mode)
-               dssdev->ops->hdmi.set_hdmi_mode(dssdev, hdmi_mode);
-
-       if (hdmi_mode && dssdev->ops->hdmi.set_infoframe) {
-               struct hdmi_avi_infoframe avi;
-
-               r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode,
-                                                            false);
-               if (r == 0)
-                       dssdev->ops->hdmi.set_infoframe(dssdev, &avi);
-       }
+       if (omap_encoder->output->output_type == OMAP_DISPLAY_TYPE_HDMI)
+               omap_encoder_hdmi_mode_set(encoder, adjusted_mode);
 }
 
 static void omap_encoder_disable(struct drm_encoder *encoder)
index d85f0a1..cebf313 100644 (file)
@@ -202,10 +202,25 @@ void rcar_du_group_put(struct rcar_du_group *rgrp)
 
 static void __rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
 {
-       struct rcar_du_crtc *rcrtc = &rgrp->dev->crtcs[rgrp->index * 2];
+       struct rcar_du_device *rcdu = rgrp->dev;
+
+       /*
+        * Group start/stop is controlled by the DRES and DEN bits of DSYSR0
+        * for the first group and DSYSR2 for the second group. On most DU
+        * instances, this maps to the first CRTC of the group, and we can just
+        * use rcar_du_crtc_dsysr_clr_set() to access the correct DSYSR. On
+        * M3-N, however, DU2 doesn't exist, but DSYSR2 does. We thus need to
+        * access the register directly using group read/write.
+        */
+       if (rcdu->info->channels_mask & BIT(rgrp->index * 2)) {
+               struct rcar_du_crtc *rcrtc = &rgrp->dev->crtcs[rgrp->index * 2];
 
-       rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_DRES | DSYSR_DEN,
-                                  start ? DSYSR_DEN : DSYSR_DRES);
+               rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_DRES | DSYSR_DEN,
+                                          start ? DSYSR_DEN : DSYSR_DRES);
+       } else {
+               rcar_du_group_write(rgrp, DSYSR,
+                                   start ? DSYSR_DEN : DSYSR_DRES);
+       }
 }
 
 void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
index ba80150..895d77d 100644 (file)
@@ -492,8 +492,10 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo,
        if (!fbo)
                return -ENOMEM;
 
-       ttm_bo_get(bo);
        fbo->base = *bo;
+       fbo->base.mem.placement |= TTM_PL_FLAG_NO_EVICT;
+
+       ttm_bo_get(bo);
        fbo->bo = bo;
 
        /**
index b372854..704049e 100644 (file)
@@ -309,7 +309,7 @@ static void mousevsc_on_receive(struct hv_device *device,
                hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,
                                 input_dev->input_buf, len, 1);
 
-               pm_wakeup_event(&input_dev->device->device, 0);
+               pm_wakeup_hard_event(&input_dev->device->device);
 
                break;
        default:
index e8a1141..bb012bc 100644 (file)
@@ -358,7 +358,7 @@ static ssize_t show_value(struct device *dev, struct device_attribute *attr,
                                                sensor_inst->hsdev,
                                                sensor_inst->hsdev->usage,
                                                usage, report_id,
-                                               SENSOR_HUB_SYNC);
+                                               SENSOR_HUB_SYNC, false);
        } else if (!strncmp(name, "units", strlen("units")))
                value = sensor_inst->fields[field_index].attribute.units;
        else if (!strncmp(name, "unit-expo", strlen("unit-expo")))
index 2b63487..4256fdc 100644 (file)
@@ -299,7 +299,8 @@ EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
 int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
                                        u32 usage_id,
                                        u32 attr_usage_id, u32 report_id,
-                                       enum sensor_hub_read_flags flag)
+                                       enum sensor_hub_read_flags flag,
+                                       bool is_signed)
 {
        struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
        unsigned long flags;
@@ -331,10 +332,16 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
                                                &hsdev->pending.ready, HZ*5);
                switch (hsdev->pending.raw_size) {
                case 1:
-                       ret_val = *(u8 *)hsdev->pending.raw_data;
+                       if (is_signed)
+                               ret_val = *(s8 *)hsdev->pending.raw_data;
+                       else
+                               ret_val = *(u8 *)hsdev->pending.raw_data;
                        break;
                case 2:
-                       ret_val = *(u16 *)hsdev->pending.raw_data;
+                       if (is_signed)
+                               ret_val = *(s16 *)hsdev->pending.raw_data;
+                       else
+                               ret_val = *(u16 *)hsdev->pending.raw_data;
                        break;
                case 4:
                        ret_val = *(u32 *)hsdev->pending.raw_data;
index de8193f..fe00b12 100644 (file)
@@ -516,6 +516,14 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
        }
        wait_for_completion(&msginfo->waitevent);
 
+       if (msginfo->response.gpadl_created.creation_status != 0) {
+               pr_err("Failed to establish GPADL: err = 0x%x\n",
+                      msginfo->response.gpadl_created.creation_status);
+
+               ret = -EDQUOT;
+               goto cleanup;
+       }
+
        if (channel->rescind) {
                ret = -ENODEV;
                goto cleanup;
index 6277597..edd34c1 100644 (file)
@@ -435,61 +435,16 @@ void vmbus_free_channels(void)
        }
 }
 
-/*
- * vmbus_process_offer - Process the offer by creating a channel/device
- * associated with this offer
- */
-static void vmbus_process_offer(struct vmbus_channel *newchannel)
+/* Note: the function can run concurrently for primary/sub channels. */
+static void vmbus_add_channel_work(struct work_struct *work)
 {
-       struct vmbus_channel *channel;
-       bool fnew = true;
+       struct vmbus_channel *newchannel =
+               container_of(work, struct vmbus_channel, add_channel_work);
+       struct vmbus_channel *primary_channel = newchannel->primary_channel;
        unsigned long flags;
        u16 dev_type;
        int ret;
 
-       /* Make sure this is a new offer */
-       mutex_lock(&vmbus_connection.channel_mutex);
-
-       /*
-        * Now that we have acquired the channel_mutex,
-        * we can release the potentially racing rescind thread.
-        */
-       atomic_dec(&vmbus_connection.offer_in_progress);
-
-       list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
-               if (!uuid_le_cmp(channel->offermsg.offer.if_type,
-                       newchannel->offermsg.offer.if_type) &&
-                       !uuid_le_cmp(channel->offermsg.offer.if_instance,
-                               newchannel->offermsg.offer.if_instance)) {
-                       fnew = false;
-                       break;
-               }
-       }
-
-       if (fnew)
-               list_add_tail(&newchannel->listentry,
-                             &vmbus_connection.chn_list);
-
-       mutex_unlock(&vmbus_connection.channel_mutex);
-
-       if (!fnew) {
-               /*
-                * Check to see if this is a sub-channel.
-                */
-               if (newchannel->offermsg.offer.sub_channel_index != 0) {
-                       /*
-                        * Process the sub-channel.
-                        */
-                       newchannel->primary_channel = channel;
-                       spin_lock_irqsave(&channel->lock, flags);
-                       list_add_tail(&newchannel->sc_list, &channel->sc_list);
-                       channel->num_sc++;
-                       spin_unlock_irqrestore(&channel->lock, flags);
-               } else {
-                       goto err_free_chan;
-               }
-       }
-
        dev_type = hv_get_dev_type(newchannel);
 
        init_vp_index(newchannel, dev_type);
@@ -507,27 +462,26 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
        /*
         * This state is used to indicate a successful open
         * so that when we do close the channel normally, we
-        * can cleanup properly
+        * can cleanup properly.
         */
        newchannel->state = CHANNEL_OPEN_STATE;
 
-       if (!fnew) {
-               struct hv_device *dev
-                       = newchannel->primary_channel->device_obj;
+       if (primary_channel != NULL) {
+               /* newchannel is a sub-channel. */
+               struct hv_device *dev = primary_channel->device_obj;
 
                if (vmbus_add_channel_kobj(dev, newchannel))
-                       goto err_free_chan;
+                       goto err_deq_chan;
+
+               if (primary_channel->sc_creation_callback != NULL)
+                       primary_channel->sc_creation_callback(newchannel);
 
-               if (channel->sc_creation_callback != NULL)
-                       channel->sc_creation_callback(newchannel);
                newchannel->probe_done = true;
                return;
        }
 
        /*
-        * Start the process of binding this offer to the driver
-        * We need to set the DeviceObject field before calling
-        * vmbus_child_dev_add()
+        * Start the process of binding the primary channel to the driver
         */
        newchannel->device_obj = vmbus_device_create(
                &newchannel->offermsg.offer.if_type,
@@ -556,13 +510,28 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
 
 err_deq_chan:
        mutex_lock(&vmbus_connection.channel_mutex);
-       list_del(&newchannel->listentry);
+
+       /*
+        * We need to set the flag, otherwise
+        * vmbus_onoffer_rescind() can be blocked.
+        */
+       newchannel->probe_done = true;
+
+       if (primary_channel == NULL) {
+               list_del(&newchannel->listentry);
+       } else {
+               spin_lock_irqsave(&primary_channel->lock, flags);
+               list_del(&newchannel->sc_list);
+               spin_unlock_irqrestore(&primary_channel->lock, flags);
+       }
+
        mutex_unlock(&vmbus_connection.channel_mutex);
 
        if (newchannel->target_cpu != get_cpu()) {
                put_cpu();
                smp_call_function_single(newchannel->target_cpu,
-                                        percpu_channel_deq, newchannel, true);
+                                        percpu_channel_deq,
+                                        newchannel, true);
        } else {
                percpu_channel_deq(newchannel);
                put_cpu();
@@ -570,14 +539,104 @@ err_deq_chan:
 
        vmbus_release_relid(newchannel->offermsg.child_relid);
 
-err_free_chan:
        free_channel(newchannel);
 }
 
+/*
+ * vmbus_process_offer - Process the offer by creating a channel/device
+ * associated with this offer
+ */
+static void vmbus_process_offer(struct vmbus_channel *newchannel)
+{
+       struct vmbus_channel *channel;
+       struct workqueue_struct *wq;
+       unsigned long flags;
+       bool fnew = true;
+
+       mutex_lock(&vmbus_connection.channel_mutex);
+
+       /*
+        * Now that we have acquired the channel_mutex,
+        * we can release the potentially racing rescind thread.
+        */
+       atomic_dec(&vmbus_connection.offer_in_progress);
+
+       list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
+               if (!uuid_le_cmp(channel->offermsg.offer.if_type,
+                                newchannel->offermsg.offer.if_type) &&
+                   !uuid_le_cmp(channel->offermsg.offer.if_instance,
+                                newchannel->offermsg.offer.if_instance)) {
+                       fnew = false;
+                       break;
+               }
+       }
+
+       if (fnew)
+               list_add_tail(&newchannel->listentry,
+                             &vmbus_connection.chn_list);
+       else {
+               /*
+                * Check to see if this is a valid sub-channel.
+                */
+               if (newchannel->offermsg.offer.sub_channel_index == 0) {
+                       mutex_unlock(&vmbus_connection.channel_mutex);
+                       /*
+                        * Don't call free_channel(), because newchannel->kobj
+                        * is not initialized yet.
+                        */
+                       kfree(newchannel);
+                       WARN_ON_ONCE(1);
+                       return;
+               }
+               /*
+                * Process the sub-channel.
+                */
+               newchannel->primary_channel = channel;
+               spin_lock_irqsave(&channel->lock, flags);
+               list_add_tail(&newchannel->sc_list, &channel->sc_list);
+               spin_unlock_irqrestore(&channel->lock, flags);
+       }
+
+       mutex_unlock(&vmbus_connection.channel_mutex);
+
+       /*
+        * vmbus_process_offer() mustn't call channel->sc_creation_callback()
+        * directly for sub-channels, because sc_creation_callback() ->
+        * vmbus_open() may never get the host's response to the
+        * OPEN_CHANNEL message (the host may rescind a channel at any time,
+        * e.g. in the case of hot removing a NIC), and vmbus_onoffer_rescind()
+        * may not wake up the vmbus_open() as it's blocked due to a non-zero
+        * vmbus_connection.offer_in_progress, and finally we have a deadlock.
+        *
+        * The above is also true for primary channels, if the related device
+        * drivers use sync probing mode by default.
+        *
+        * And, usually the handling of primary channels and sub-channels can
+        * depend on each other, so we should offload them to different
+        * workqueues to avoid possible deadlock, e.g. in sync-probing mode,
+        * NIC1's netvsc_subchan_work() can race with NIC2's netvsc_probe() ->
+        * rtnl_lock(), and causes deadlock: the former gets the rtnl_lock
+        * and waits for all the sub-channels to appear, but the latter
+        * can't get the rtnl_lock and this blocks the handling of
+        * sub-channels.
+        */
+       INIT_WORK(&newchannel->add_channel_work, vmbus_add_channel_work);
+       wq = fnew ? vmbus_connection.handle_primary_chan_wq :
+                   vmbus_connection.handle_sub_chan_wq;
+       queue_work(wq, &newchannel->add_channel_work);
+}
+
 /*
  * We use this state to statically distribute the channel interrupt load.
  */
 static int next_numa_node_id;
+/*
+ * init_vp_index() accesses global variables like next_numa_node_id, and
+ * it can run concurrently for primary channels and sub-channels: see
+ * vmbus_process_offer(), so we need the lock to protect the global
+ * variables.
+ */
+static DEFINE_SPINLOCK(bind_channel_to_cpu_lock);
 
 /*
  * Starting with Win8, we can statically distribute the incoming
@@ -613,6 +672,8 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type)
                return;
        }
 
+       spin_lock(&bind_channel_to_cpu_lock);
+
        /*
         * Based on the channel affinity policy, we will assign the NUMA
         * nodes.
@@ -695,6 +756,8 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type)
        channel->target_cpu = cur_cpu;
        channel->target_vp = hv_cpu_number_to_vp_number(cur_cpu);
 
+       spin_unlock(&bind_channel_to_cpu_lock);
+
        free_cpumask_var(available_mask);
 }
 
index f4d08c8..4fe117b 100644 (file)
@@ -190,6 +190,20 @@ int vmbus_connect(void)
                goto cleanup;
        }
 
+       vmbus_connection.handle_primary_chan_wq =
+               create_workqueue("hv_pri_chan");
+       if (!vmbus_connection.handle_primary_chan_wq) {
+               ret = -ENOMEM;
+               goto cleanup;
+       }
+
+       vmbus_connection.handle_sub_chan_wq =
+               create_workqueue("hv_sub_chan");
+       if (!vmbus_connection.handle_sub_chan_wq) {
+               ret = -ENOMEM;
+               goto cleanup;
+       }
+
        INIT_LIST_HEAD(&vmbus_connection.chn_msg_list);
        spin_lock_init(&vmbus_connection.channelmsg_lock);
 
@@ -280,10 +294,14 @@ void vmbus_disconnect(void)
         */
        vmbus_initiate_unload(false);
 
-       if (vmbus_connection.work_queue) {
-               drain_workqueue(vmbus_connection.work_queue);
+       if (vmbus_connection.handle_sub_chan_wq)
+               destroy_workqueue(vmbus_connection.handle_sub_chan_wq);
+
+       if (vmbus_connection.handle_primary_chan_wq)
+               destroy_workqueue(vmbus_connection.handle_primary_chan_wq);
+
+       if (vmbus_connection.work_queue)
                destroy_workqueue(vmbus_connection.work_queue);
-       }
 
        if (vmbus_connection.int_page) {
                free_pages((unsigned long)vmbus_connection.int_page, 0);
index 72eaba3..87d3d7d 100644 (file)
@@ -335,7 +335,14 @@ struct vmbus_connection {
        struct list_head chn_list;
        struct mutex channel_mutex;
 
+       /*
+        * An offer message is handled first on the work_queue, and then
+        * is further handled on handle_primary_chan_wq or
+        * handle_sub_chan_wq.
+        */
        struct workqueue_struct *work_queue;
+       struct workqueue_struct *handle_primary_chan_wq;
+       struct workqueue_struct *handle_sub_chan_wq;
 };
 
 
index 8e60048..51d3495 100644 (file)
@@ -74,8 +74,7 @@
                                 MST_STATUS_ND)
 #define   MST_STATUS_ERR       (MST_STATUS_NAK | \
                                 MST_STATUS_AL  | \
-                                MST_STATUS_IP  | \
-                                MST_STATUS_TSS)
+                                MST_STATUS_IP)
 #define MST_TX_BYTES_XFRD      0x50
 #define MST_RX_BYTES_XFRD      0x54
 #define SCL_HIGH_PERIOD                0x80
@@ -241,7 +240,7 @@ static int axxia_i2c_empty_rx_fifo(struct axxia_i2c_dev *idev)
                         */
                        if (c <= 0 || c > I2C_SMBUS_BLOCK_MAX) {
                                idev->msg_err = -EPROTO;
-                               i2c_int_disable(idev, ~0);
+                               i2c_int_disable(idev, ~MST_STATUS_TSS);
                                complete(&idev->msg_complete);
                                break;
                        }
@@ -299,14 +298,19 @@ static irqreturn_t axxia_i2c_isr(int irq, void *_dev)
 
        if (status & MST_STATUS_SCC) {
                /* Stop completed */
-               i2c_int_disable(idev, ~0);
+               i2c_int_disable(idev, ~MST_STATUS_TSS);
                complete(&idev->msg_complete);
        } else if (status & MST_STATUS_SNS) {
                /* Transfer done */
-               i2c_int_disable(idev, ~0);
+               i2c_int_disable(idev, ~MST_STATUS_TSS);
                if (i2c_m_rd(idev->msg) && idev->msg_xfrd < idev->msg->len)
                        axxia_i2c_empty_rx_fifo(idev);
                complete(&idev->msg_complete);
+       } else if (status & MST_STATUS_TSS) {
+               /* Transfer timeout */
+               idev->msg_err = -ETIMEDOUT;
+               i2c_int_disable(idev, ~MST_STATUS_TSS);
+               complete(&idev->msg_complete);
        } else if (unlikely(status & MST_STATUS_ERR)) {
                /* Transfer error */
                i2c_int_disable(idev, ~0);
@@ -339,10 +343,10 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
        u32 rx_xfer, tx_xfer;
        u32 addr_1, addr_2;
        unsigned long time_left;
+       unsigned int wt_value;
 
        idev->msg = msg;
        idev->msg_xfrd = 0;
-       idev->msg_err = 0;
        reinit_completion(&idev->msg_complete);
 
        if (i2c_m_ten(msg)) {
@@ -383,9 +387,18 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
        else if (axxia_i2c_fill_tx_fifo(idev) != 0)
                int_mask |= MST_STATUS_TFL;
 
+       wt_value = WT_VALUE(readl(idev->base + WAIT_TIMER_CONTROL));
+       /* Disable wait timer temporarly */
+       writel(wt_value, idev->base + WAIT_TIMER_CONTROL);
+       /* Check if timeout error happened */
+       if (idev->msg_err)
+               goto out;
+
        /* Start manual mode */
        writel(CMD_MANUAL, idev->base + MST_COMMAND);
 
+       writel(WT_EN | wt_value, idev->base + WAIT_TIMER_CONTROL);
+
        i2c_int_enable(idev, int_mask);
 
        time_left = wait_for_completion_timeout(&idev->msg_complete,
@@ -396,13 +409,15 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
        if (readl(idev->base + MST_COMMAND) & CMD_BUSY)
                dev_warn(idev->dev, "busy after xfer\n");
 
-       if (time_left == 0)
+       if (time_left == 0) {
                idev->msg_err = -ETIMEDOUT;
-
-       if (idev->msg_err == -ETIMEDOUT)
                i2c_recover_bus(&idev->adapter);
+               axxia_i2c_init(idev);
+       }
 
-       if (unlikely(idev->msg_err) && idev->msg_err != -ENXIO)
+out:
+       if (unlikely(idev->msg_err) && idev->msg_err != -ENXIO &&
+                       idev->msg_err != -ETIMEDOUT)
                axxia_i2c_init(idev);
 
        return idev->msg_err;
@@ -410,7 +425,7 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
 
 static int axxia_i2c_stop(struct axxia_i2c_dev *idev)
 {
-       u32 int_mask = MST_STATUS_ERR | MST_STATUS_SCC;
+       u32 int_mask = MST_STATUS_ERR | MST_STATUS_SCC | MST_STATUS_TSS;
        unsigned long time_left;
 
        reinit_completion(&idev->msg_complete);
@@ -437,6 +452,9 @@ axxia_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        int i;
        int ret = 0;
 
+       idev->msg_err = 0;
+       i2c_int_enable(idev, MST_STATUS_TSS);
+
        for (i = 0; ret == 0 && i < num; ++i)
                ret = axxia_i2c_xfer_msg(idev, &msgs[i]);
 
index 8822357..e99c3bb 100644 (file)
@@ -89,7 +89,7 @@ static int gpu_i2c_check_status(struct gpu_i2c_dev *i2cd)
 
        if (time_is_before_jiffies(target)) {
                dev_err(i2cd->dev, "i2c timeout error %x\n", val);
-               return -ETIME;
+               return -ETIMEDOUT;
        }
 
        val = readl(i2cd->regs + I2C_MST_CNTL);
@@ -97,9 +97,9 @@ static int gpu_i2c_check_status(struct gpu_i2c_dev *i2cd)
        case I2C_MST_CNTL_STATUS_OKAY:
                return 0;
        case I2C_MST_CNTL_STATUS_NO_ACK:
-               return -EIO;
+               return -ENXIO;
        case I2C_MST_CNTL_STATUS_TIMEOUT:
-               return -ETIME;
+               return -ETIMEDOUT;
        default:
                return 0;
        }
@@ -218,6 +218,7 @@ stop:
 
 static const struct i2c_adapter_quirks gpu_i2c_quirks = {
        .max_read_len = 4,
+       .max_comb_2nd_msg_len = 4,
        .flags = I2C_AQ_COMB_WRITE_THEN_READ,
 };
 
index 4aa7dde..254e621 100644 (file)
@@ -779,6 +779,11 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
 
        pm_runtime_get_sync(dev);
 
+       /* Check bus state before init otherwise bus busy info will be lost */
+       ret = rcar_i2c_bus_barrier(priv);
+       if (ret < 0)
+               goto out;
+
        /* Gen3 needs a reset before allowing RXDMA once */
        if (priv->devtype == I2C_RCAR_GEN3) {
                priv->flags |= ID_P_NO_RXDMA;
@@ -791,10 +796,6 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
 
        rcar_i2c_init(priv);
 
-       ret = rcar_i2c_bus_barrier(priv);
-       if (ret < 0)
-               goto out;
-
        for (i = 0; i < num; i++)
                rcar_i2c_request_dma(priv, msgs + i);
 
index 7e9a2bb..ff3f455 100644 (file)
@@ -367,6 +367,7 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
 {
        struct acpi_smbus_cmi *smbus_cmi;
        const struct acpi_device_id *id;
+       int ret;
 
        smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL);
        if (!smbus_cmi)
@@ -388,8 +389,10 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
        acpi_walk_namespace(ACPI_TYPE_METHOD, smbus_cmi->handle, 1,
                            acpi_smbus_cmi_query_methods, NULL, smbus_cmi, NULL);
 
-       if (smbus_cmi->cap_info == 0)
+       if (smbus_cmi->cap_info == 0) {
+               ret = -ENODEV;
                goto err;
+       }
 
        snprintf(smbus_cmi->adapter.name, sizeof(smbus_cmi->adapter.name),
                "SMBus CMI adapter %s",
@@ -400,7 +403,8 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
        smbus_cmi->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        smbus_cmi->adapter.dev.parent = &device->dev;
 
-       if (i2c_add_adapter(&smbus_cmi->adapter)) {
+       ret = i2c_add_adapter(&smbus_cmi->adapter);
+       if (ret) {
                dev_err(&device->dev, "Couldn't register adapter!\n");
                goto err;
        }
@@ -410,7 +414,7 @@ static int acpi_smbus_cmi_add(struct acpi_device *device)
 err:
        kfree(smbus_cmi);
        device->driver_data = NULL;
-       return -EIO;
+       return ret;
 }
 
 static int acpi_smbus_cmi_remove(struct acpi_device *device)
index dd38474..03da4a5 100644 (file)
@@ -173,8 +173,6 @@ static irqreturn_t uniphier_fi2c_interrupt(int irq, void *dev_id)
                "interrupt: enabled_irqs=%04x, irq_status=%04x\n",
                priv->enabled_irqs, irq_status);
 
-       uniphier_fi2c_clear_irqs(priv, irq_status);
-
        if (irq_status & UNIPHIER_FI2C_INT_STOP)
                goto complete;
 
@@ -214,7 +212,13 @@ static irqreturn_t uniphier_fi2c_interrupt(int irq, void *dev_id)
 
        if (irq_status & (UNIPHIER_FI2C_INT_RF | UNIPHIER_FI2C_INT_RB)) {
                uniphier_fi2c_drain_rxfifo(priv);
-               if (!priv->len)
+               /*
+                * If the number of bytes to read is multiple of the FIFO size
+                * (msg->len == 8, 16, 24, ...), the INT_RF bit is set a little
+                * earlier than INT_RB. We wait for INT_RB to confirm the
+                * completion of the current message.
+                */
+               if (!priv->len && (irq_status & UNIPHIER_FI2C_INT_RB))
                        goto data_done;
 
                if (unlikely(priv->flags & UNIPHIER_FI2C_MANUAL_NACK)) {
@@ -253,12 +257,20 @@ complete:
        }
 
 handled:
+       /*
+        * This controller makes a pause while any bit of the IRQ status is
+        * asserted. Clear the asserted bit to kick the controller just before
+        * exiting the handler.
+        */
+       uniphier_fi2c_clear_irqs(priv, irq_status);
+
        spin_unlock(&priv->lock);
 
        return IRQ_HANDLED;
 }
 
-static void uniphier_fi2c_tx_init(struct uniphier_fi2c_priv *priv, u16 addr)
+static void uniphier_fi2c_tx_init(struct uniphier_fi2c_priv *priv, u16 addr,
+                                 bool repeat)
 {
        priv->enabled_irqs |= UNIPHIER_FI2C_INT_TE;
        uniphier_fi2c_set_irqs(priv);
@@ -268,8 +280,12 @@ static void uniphier_fi2c_tx_init(struct uniphier_fi2c_priv *priv, u16 addr)
        /* set slave address */
        writel(UNIPHIER_FI2C_DTTX_CMD | addr << 1,
               priv->membase + UNIPHIER_FI2C_DTTX);
-       /* first chunk of data */
-       uniphier_fi2c_fill_txfifo(priv, true);
+       /*
+        * First chunk of data. For a repeated START condition, do not write
+        * data to the TX fifo here to avoid the timing issue.
+        */
+       if (!repeat)
+               uniphier_fi2c_fill_txfifo(priv, true);
 }
 
 static void uniphier_fi2c_rx_init(struct uniphier_fi2c_priv *priv, u16 addr)
@@ -350,7 +366,7 @@ static int uniphier_fi2c_master_xfer_one(struct i2c_adapter *adap,
        if (is_read)
                uniphier_fi2c_rx_init(priv, msg->addr);
        else
-               uniphier_fi2c_tx_init(priv, msg->addr);
+               uniphier_fi2c_tx_init(priv, msg->addr, repeat);
 
        dev_dbg(&adap->dev, "start condition\n");
        /*
@@ -502,9 +518,26 @@ static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv)
 
        uniphier_fi2c_reset(priv);
 
+       /*
+        *  Standard-mode: tLOW + tHIGH = 10 us
+        *  Fast-mode:     tLOW + tHIGH = 2.5 us
+        */
        writel(cyc, priv->membase + UNIPHIER_FI2C_CYC);
-       writel(cyc / 2, priv->membase + UNIPHIER_FI2C_LCTL);
+       /*
+        *  Standard-mode: tLOW = 4.7 us, tHIGH = 4.0 us, tBUF = 4.7 us
+        *  Fast-mode:     tLOW = 1.3 us, tHIGH = 0.6 us, tBUF = 1.3 us
+        * "tLow/tHIGH = 5/4" meets both.
+        */
+       writel(cyc * 5 / 9, priv->membase + UNIPHIER_FI2C_LCTL);
+       /*
+        *  Standard-mode: tHD;STA = 4.0 us, tSU;STA = 4.7 us, tSU;STO = 4.0 us
+        *  Fast-mode:     tHD;STA = 0.6 us, tSU;STA = 0.6 us, tSU;STO = 0.6 us
+        */
        writel(cyc / 2, priv->membase + UNIPHIER_FI2C_SSUT);
+       /*
+        *  Standard-mode: tSU;DAT = 250 ns
+        *  Fast-mode:     tSU;DAT = 100 ns
+        */
        writel(cyc / 16, priv->membase + UNIPHIER_FI2C_DSUT);
 
        uniphier_fi2c_prepare_operation(priv);
index 454f914..c488e55 100644 (file)
@@ -320,7 +320,13 @@ static void uniphier_i2c_hw_init(struct uniphier_i2c_priv *priv)
 
        uniphier_i2c_reset(priv, true);
 
-       writel((cyc / 2 << 16) | cyc, priv->membase + UNIPHIER_I2C_CLK);
+       /*
+        * Bit30-16: clock cycles of tLOW.
+        *  Standard-mode: tLOW = 4.7 us, tHIGH = 4.0 us
+        *  Fast-mode:     tLOW = 1.3 us, tHIGH = 0.6 us
+        * "tLow/tHIGH = 5/4" meets both.
+        */
+       writel((cyc * 5 / 9 << 16) | cyc, priv->membase + UNIPHIER_I2C_CLK);
 
        uniphier_i2c_reset(priv, false);
 }
index 45c9974..4c8c7a6 100644 (file)
@@ -614,18 +614,7 @@ static int ide_drivers_show(struct seq_file *s, void *p)
        return 0;
 }
 
-static int ide_drivers_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, &ide_drivers_show, NULL);
-}
-
-static const struct file_operations ide_drivers_operations = {
-       .owner          = THIS_MODULE,
-       .open           = ide_drivers_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(ide_drivers);
 
 void proc_ide_create(void)
 {
@@ -634,7 +623,7 @@ void proc_ide_create(void)
        if (!proc_ide_root)
                return;
 
-       proc_create("drivers", 0, proc_ide_root, &ide_drivers_operations);
+       proc_create("drivers", 0, proc_ide_root, &ide_drivers_fops);
 }
 
 void proc_ide_destroy(void)
index c5b902b..203ed4a 100644 (file)
@@ -920,6 +920,7 @@ static u8 pmac_ide_cable_detect(ide_hwif_t *hwif)
        struct device_node *root = of_find_node_by_path("/");
        const char *model = of_get_property(root, "model", NULL);
 
+       of_node_put(root);
        /* Get cable type from device-tree. */
        if (cable && !strncmp(cable, "80-", 3)) {
                /* Some drives fail to detect 80c cable in PowerBook */
index 41d97fa..38ff374 100644 (file)
@@ -149,6 +149,7 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
        struct hid_sensor_hub_device *hsdev =
                                        accel_state->common_attributes.hsdev;
 
@@ -158,12 +159,14 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_RAW:
                hid_sensor_power_state(&accel_state->common_attributes, true);
                report_id = accel_state->accel[chan->scan_index].report_id;
+               min = accel_state->accel[chan->scan_index].logical_minimum;
                address = accel_3d_addresses[chan->scan_index];
                if (report_id >= 0)
                        *val = sensor_hub_input_attr_get_raw_value(
                                        accel_state->common_attributes.hsdev,
                                        hsdev->usage, address, report_id,
-                                       SENSOR_HUB_SYNC);
+                                       SENSOR_HUB_SYNC,
+                                       min < 0);
                else {
                        *val = 0;
                        hid_sensor_power_state(&accel_state->common_attributes,
index 36941e6..88e857c 100644 (file)
@@ -111,6 +111,7 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
 
        *val = 0;
        *val2 = 0;
@@ -118,13 +119,15 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_RAW:
                hid_sensor_power_state(&gyro_state->common_attributes, true);
                report_id = gyro_state->gyro[chan->scan_index].report_id;
+               min = gyro_state->gyro[chan->scan_index].logical_minimum;
                address = gyro_3d_addresses[chan->scan_index];
                if (report_id >= 0)
                        *val = sensor_hub_input_attr_get_raw_value(
                                        gyro_state->common_attributes.hsdev,
                                        HID_USAGE_SENSOR_GYRO_3D, address,
                                        report_id,
-                                       SENSOR_HUB_SYNC);
+                                       SENSOR_HUB_SYNC,
+                                       min < 0);
                else {
                        *val = 0;
                        hid_sensor_power_state(&gyro_state->common_attributes,
index beab6d6..4bc95f3 100644 (file)
@@ -75,7 +75,8 @@ static int humidity_read_raw(struct iio_dev *indio_dev,
                                HID_USAGE_SENSOR_HUMIDITY,
                                HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
                                humid_st->humidity_attr.report_id,
-                               SENSOR_HUB_SYNC);
+                               SENSOR_HUB_SYNC,
+                               humid_st->humidity_attr.logical_minimum < 0);
                hid_sensor_power_state(&humid_st->common_attributes, false);
 
                return IIO_VAL_INT;
index 406caae..94f3325 100644 (file)
@@ -93,6 +93,7 @@ static int als_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
 
        *val = 0;
        *val2 = 0;
@@ -102,8 +103,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
                case  CHANNEL_SCAN_INDEX_INTENSITY:
                case  CHANNEL_SCAN_INDEX_ILLUM:
                        report_id = als_state->als_illum.report_id;
-                       address =
-                       HID_USAGE_SENSOR_LIGHT_ILLUM;
+                       min = als_state->als_illum.logical_minimum;
+                       address = HID_USAGE_SENSOR_LIGHT_ILLUM;
                        break;
                default:
                        report_id = -1;
@@ -116,7 +117,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
                                        als_state->common_attributes.hsdev,
                                        HID_USAGE_SENSOR_ALS, address,
                                        report_id,
-                                       SENSOR_HUB_SYNC);
+                                       SENSOR_HUB_SYNC,
+                                       min < 0);
                        hid_sensor_power_state(&als_state->common_attributes,
                                                false);
                } else {
index 45107f7..cf5a0c2 100644 (file)
@@ -73,6 +73,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
 
        *val = 0;
        *val2 = 0;
@@ -81,8 +82,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
                switch (chan->scan_index) {
                case  CHANNEL_SCAN_INDEX_PRESENCE:
                        report_id = prox_state->prox_attr.report_id;
-                       address =
-                       HID_USAGE_SENSOR_HUMAN_PRESENCE;
+                       min = prox_state->prox_attr.logical_minimum;
+                       address = HID_USAGE_SENSOR_HUMAN_PRESENCE;
                        break;
                default:
                        report_id = -1;
@@ -95,7 +96,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
                                prox_state->common_attributes.hsdev,
                                HID_USAGE_SENSOR_PROX, address,
                                report_id,
-                               SENSOR_HUB_SYNC);
+                               SENSOR_HUB_SYNC,
+                               min < 0);
                        hid_sensor_power_state(&prox_state->common_attributes,
                                                false);
                } else {
index d55c488..f3c0d41 100644 (file)
@@ -163,21 +163,23 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
 
        *val = 0;
        *val2 = 0;
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
                hid_sensor_power_state(&magn_state->magn_flux_attributes, true);
-               report_id =
-                       magn_state->magn[chan->address].report_id;
+               report_id = magn_state->magn[chan->address].report_id;
+               min = magn_state->magn[chan->address].logical_minimum;
                address = magn_3d_addresses[chan->address];
                if (report_id >= 0)
                        *val = sensor_hub_input_attr_get_raw_value(
                                magn_state->magn_flux_attributes.hsdev,
                                HID_USAGE_SENSOR_COMPASS_3D, address,
                                report_id,
-                               SENSOR_HUB_SYNC);
+                               SENSOR_HUB_SYNC,
+                               min < 0);
                else {
                        *val = 0;
                        hid_sensor_power_state(
index 0a9e8fa..37ab305 100644 (file)
@@ -30,11 +30,6 @@ int st_magn_trig_set_state(struct iio_trigger *trig, bool state)
        return st_sensors_set_dataready_irq(indio_dev, state);
 }
 
-static int st_magn_buffer_preenable(struct iio_dev *indio_dev)
-{
-       return st_sensors_set_enable(indio_dev, true);
-}
-
 static int st_magn_buffer_postenable(struct iio_dev *indio_dev)
 {
        int err;
@@ -50,7 +45,7 @@ static int st_magn_buffer_postenable(struct iio_dev *indio_dev)
        if (err < 0)
                goto st_magn_buffer_postenable_error;
 
-       return err;
+       return st_sensors_set_enable(indio_dev, true);
 
 st_magn_buffer_postenable_error:
        kfree(mdata->buffer_data);
@@ -63,11 +58,11 @@ static int st_magn_buffer_predisable(struct iio_dev *indio_dev)
        int err;
        struct st_sensor_data *mdata = iio_priv(indio_dev);
 
-       err = iio_triggered_buffer_predisable(indio_dev);
+       err = st_sensors_set_enable(indio_dev, false);
        if (err < 0)
                goto st_magn_buffer_predisable_error;
 
-       err = st_sensors_set_enable(indio_dev, false);
+       err = iio_triggered_buffer_predisable(indio_dev);
 
 st_magn_buffer_predisable_error:
        kfree(mdata->buffer_data);
@@ -75,7 +70,6 @@ st_magn_buffer_predisable_error:
 }
 
 static const struct iio_buffer_setup_ops st_magn_buffer_setup_ops = {
-       .preenable = &st_magn_buffer_preenable,
        .postenable = &st_magn_buffer_postenable,
        .predisable = &st_magn_buffer_predisable,
 };
index 1e5451d..bdc5e45 100644 (file)
@@ -111,21 +111,23 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
 
        *val = 0;
        *val2 = 0;
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
                hid_sensor_power_state(&incl_state->common_attributes, true);
-               report_id =
-                       incl_state->incl[chan->scan_index].report_id;
+               report_id = incl_state->incl[chan->scan_index].report_id;
+               min = incl_state->incl[chan->scan_index].logical_minimum;
                address = incl_3d_addresses[chan->scan_index];
                if (report_id >= 0)
                        *val = sensor_hub_input_attr_get_raw_value(
                                incl_state->common_attributes.hsdev,
                                HID_USAGE_SENSOR_INCLINOMETER_3D, address,
                                report_id,
-                               SENSOR_HUB_SYNC);
+                               SENSOR_HUB_SYNC,
+                               min < 0);
                else {
                        hid_sensor_power_state(&incl_state->common_attributes,
                                                false);
index 4c43791..d7b1c00 100644 (file)
@@ -77,6 +77,7 @@ static int press_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
 
        *val = 0;
        *val2 = 0;
@@ -85,8 +86,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
                switch (chan->scan_index) {
                case  CHANNEL_SCAN_INDEX_PRESSURE:
                        report_id = press_state->press_attr.report_id;
-                       address =
-                       HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
+                       min = press_state->press_attr.logical_minimum;
+                       address = HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
                        break;
                default:
                        report_id = -1;
@@ -99,7 +100,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
                                press_state->common_attributes.hsdev,
                                HID_USAGE_SENSOR_PRESSURE, address,
                                report_id,
-                               SENSOR_HUB_SYNC);
+                               SENSOR_HUB_SYNC,
+                               min < 0);
                        hid_sensor_power_state(&press_state->common_attributes,
                                                false);
                } else {
index beaf6fd..b592fc4 100644 (file)
@@ -76,7 +76,8 @@ static int temperature_read_raw(struct iio_dev *indio_dev,
                        HID_USAGE_SENSOR_TEMPERATURE,
                        HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
                        temp_st->temperature_attr.report_id,
-                       SENSOR_HUB_SYNC);
+                       SENSOR_HUB_SYNC,
+                       temp_st->temperature_attr.logical_minimum < 0);
                hid_sensor_power_state(
                                &temp_st->common_attributes,
                                false);
index ee36619..25d43c8 100644 (file)
@@ -767,8 +767,10 @@ static int netdevice_event(struct notifier_block *this, unsigned long event,
 
        case NETDEV_CHANGEADDR:
                cmds[0] = netdev_del_cmd;
-               cmds[1] = add_default_gid_cmd;
-               cmds[2] = add_cmd;
+               if (ndev->reg_state == NETREG_REGISTERED) {
+                       cmds[1] = add_default_gid_cmd;
+                       cmds[2] = add_cmd;
+               }
                break;
 
        case NETDEV_CHANGEUPPER:
index 2b4c5e7..676c1fd 100644 (file)
@@ -137,15 +137,6 @@ static void ib_umem_notifier_release(struct mmu_notifier *mn,
        up_read(&per_mm->umem_rwsem);
 }
 
-static int invalidate_page_trampoline(struct ib_umem_odp *item, u64 start,
-                                     u64 end, void *cookie)
-{
-       ib_umem_notifier_start_account(item);
-       item->umem.context->invalidate_range(item, start, start + PAGE_SIZE);
-       ib_umem_notifier_end_account(item);
-       return 0;
-}
-
 static int invalidate_range_start_trampoline(struct ib_umem_odp *item,
                                             u64 start, u64 end, void *cookie)
 {
@@ -553,12 +544,13 @@ out:
                put_page(page);
 
        if (remove_existing_mapping && umem->context->invalidate_range) {
-               invalidate_page_trampoline(
+               ib_umem_notifier_start_account(umem_odp);
+               umem->context->invalidate_range(
                        umem_odp,
-                       ib_umem_start(umem) + (page_index >> umem->page_shift),
-                       ib_umem_start(umem) + ((page_index + 1) >>
-                                              umem->page_shift),
-                       NULL);
+                       ib_umem_start(umem) + (page_index << umem->page_shift),
+                       ib_umem_start(umem) +
+                               ((page_index + 1) << umem->page_shift));
+               ib_umem_notifier_end_account(umem_odp);
                ret = -EAGAIN;
        }
 
index cf22826..77f095e 100644 (file)
@@ -1268,6 +1268,7 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
        /* Registered a new RoCE device instance to netdev */
        rc = bnxt_re_register_netdev(rdev);
        if (rc) {
+               rtnl_unlock();
                pr_err("Failed to register with netedev: %#x\n", rc);
                return -EINVAL;
        }
@@ -1466,6 +1467,7 @@ static void bnxt_re_task(struct work_struct *work)
                                "Failed to register with IB: %#x", rc);
                        bnxt_re_remove_one(rdev);
                        bnxt_re_dev_unreg(rdev);
+                       goto exit;
                }
                break;
        case NETDEV_UP:
@@ -1489,6 +1491,7 @@ static void bnxt_re_task(struct work_struct *work)
        }
        smp_mb__before_atomic();
        atomic_dec(&rdev->sched_count);
+exit:
        kfree(re_work);
 }
 
index a4c62ae..3beb152 100644 (file)
@@ -1756,10 +1756,9 @@ static int hns_roce_v2_set_mac(struct hns_roce_dev *hr_dev, u8 phy_port,
        return hns_roce_cmq_send(hr_dev, &desc, 1);
 }
 
-static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
-                                 unsigned long mtpt_idx)
+static int set_mtpt_pbl(struct hns_roce_v2_mpt_entry *mpt_entry,
+                       struct hns_roce_mr *mr)
 {
-       struct hns_roce_v2_mpt_entry *mpt_entry;
        struct scatterlist *sg;
        u64 page_addr;
        u64 *pages;
@@ -1767,6 +1766,53 @@ static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
        int len;
        int entry;
 
+       mpt_entry->pbl_size = cpu_to_le32(mr->pbl_size);
+       mpt_entry->pbl_ba_l = cpu_to_le32(lower_32_bits(mr->pbl_ba >> 3));
+       roce_set_field(mpt_entry->byte_48_mode_ba,
+                      V2_MPT_BYTE_48_PBL_BA_H_M, V2_MPT_BYTE_48_PBL_BA_H_S,
+                      upper_32_bits(mr->pbl_ba >> 3));
+
+       pages = (u64 *)__get_free_page(GFP_KERNEL);
+       if (!pages)
+               return -ENOMEM;
+
+       i = 0;
+       for_each_sg(mr->umem->sg_head.sgl, sg, mr->umem->nmap, entry) {
+               len = sg_dma_len(sg) >> PAGE_SHIFT;
+               for (j = 0; j < len; ++j) {
+                       page_addr = sg_dma_address(sg) +
+                               (j << mr->umem->page_shift);
+                       pages[i] = page_addr >> 6;
+                       /* Record the first 2 entry directly to MTPT table */
+                       if (i >= HNS_ROCE_V2_MAX_INNER_MTPT_NUM - 1)
+                               goto found;
+                       i++;
+               }
+       }
+found:
+       mpt_entry->pa0_l = cpu_to_le32(lower_32_bits(pages[0]));
+       roce_set_field(mpt_entry->byte_56_pa0_h, V2_MPT_BYTE_56_PA0_H_M,
+                      V2_MPT_BYTE_56_PA0_H_S, upper_32_bits(pages[0]));
+
+       mpt_entry->pa1_l = cpu_to_le32(lower_32_bits(pages[1]));
+       roce_set_field(mpt_entry->byte_64_buf_pa1, V2_MPT_BYTE_64_PA1_H_M,
+                      V2_MPT_BYTE_64_PA1_H_S, upper_32_bits(pages[1]));
+       roce_set_field(mpt_entry->byte_64_buf_pa1,
+                      V2_MPT_BYTE_64_PBL_BUF_PG_SZ_M,
+                      V2_MPT_BYTE_64_PBL_BUF_PG_SZ_S,
+                      mr->pbl_buf_pg_sz + PG_SHIFT_OFFSET);
+
+       free_page((unsigned long)pages);
+
+       return 0;
+}
+
+static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
+                                 unsigned long mtpt_idx)
+{
+       struct hns_roce_v2_mpt_entry *mpt_entry;
+       int ret;
+
        mpt_entry = mb_buf;
        memset(mpt_entry, 0, sizeof(*mpt_entry));
 
@@ -1781,7 +1827,6 @@ static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
                       mr->pbl_ba_pg_sz + PG_SHIFT_OFFSET);
        roce_set_field(mpt_entry->byte_4_pd_hop_st, V2_MPT_BYTE_4_PD_M,
                       V2_MPT_BYTE_4_PD_S, mr->pd);
-       mpt_entry->byte_4_pd_hop_st = cpu_to_le32(mpt_entry->byte_4_pd_hop_st);
 
        roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_RA_EN_S, 0);
        roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_R_INV_EN_S, 1);
@@ -1796,13 +1841,11 @@ static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
                     (mr->access & IB_ACCESS_REMOTE_WRITE ? 1 : 0));
        roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_LW_EN_S,
                     (mr->access & IB_ACCESS_LOCAL_WRITE ? 1 : 0));
-       mpt_entry->byte_8_mw_cnt_en = cpu_to_le32(mpt_entry->byte_8_mw_cnt_en);
 
        roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_PA_S,
                     mr->type == MR_TYPE_MR ? 0 : 1);
        roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_INNER_PA_VLD_S,
                     1);
-       mpt_entry->byte_12_mw_pa = cpu_to_le32(mpt_entry->byte_12_mw_pa);
 
        mpt_entry->len_l = cpu_to_le32(lower_32_bits(mr->size));
        mpt_entry->len_h = cpu_to_le32(upper_32_bits(mr->size));
@@ -1813,53 +1856,9 @@ static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
        if (mr->type == MR_TYPE_DMA)
                return 0;
 
-       mpt_entry->pbl_size = cpu_to_le32(mr->pbl_size);
-
-       mpt_entry->pbl_ba_l = cpu_to_le32(lower_32_bits(mr->pbl_ba >> 3));
-       roce_set_field(mpt_entry->byte_48_mode_ba, V2_MPT_BYTE_48_PBL_BA_H_M,
-                      V2_MPT_BYTE_48_PBL_BA_H_S,
-                      upper_32_bits(mr->pbl_ba >> 3));
-       mpt_entry->byte_48_mode_ba = cpu_to_le32(mpt_entry->byte_48_mode_ba);
-
-       pages = (u64 *)__get_free_page(GFP_KERNEL);
-       if (!pages)
-               return -ENOMEM;
-
-       i = 0;
-       for_each_sg(mr->umem->sg_head.sgl, sg, mr->umem->nmap, entry) {
-               len = sg_dma_len(sg) >> PAGE_SHIFT;
-               for (j = 0; j < len; ++j) {
-                       page_addr = sg_dma_address(sg) +
-                                   (j << mr->umem->page_shift);
-                       pages[i] = page_addr >> 6;
-
-                       /* Record the first 2 entry directly to MTPT table */
-                       if (i >= HNS_ROCE_V2_MAX_INNER_MTPT_NUM - 1)
-                               goto found;
-                       i++;
-               }
-       }
-
-found:
-       mpt_entry->pa0_l = cpu_to_le32(lower_32_bits(pages[0]));
-       roce_set_field(mpt_entry->byte_56_pa0_h, V2_MPT_BYTE_56_PA0_H_M,
-                      V2_MPT_BYTE_56_PA0_H_S,
-                      upper_32_bits(pages[0]));
-       mpt_entry->byte_56_pa0_h = cpu_to_le32(mpt_entry->byte_56_pa0_h);
-
-       mpt_entry->pa1_l = cpu_to_le32(lower_32_bits(pages[1]));
-       roce_set_field(mpt_entry->byte_64_buf_pa1, V2_MPT_BYTE_64_PA1_H_M,
-                      V2_MPT_BYTE_64_PA1_H_S, upper_32_bits(pages[1]));
+       ret = set_mtpt_pbl(mpt_entry, mr);
 
-       free_page((unsigned long)pages);
-
-       roce_set_field(mpt_entry->byte_64_buf_pa1,
-                      V2_MPT_BYTE_64_PBL_BUF_PG_SZ_M,
-                      V2_MPT_BYTE_64_PBL_BUF_PG_SZ_S,
-                      mr->pbl_buf_pg_sz + PG_SHIFT_OFFSET);
-       mpt_entry->byte_64_buf_pa1 = cpu_to_le32(mpt_entry->byte_64_buf_pa1);
-
-       return 0;
+       return ret;
 }
 
 static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,
@@ -1868,6 +1867,7 @@ static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,
                                        u64 size, void *mb_buf)
 {
        struct hns_roce_v2_mpt_entry *mpt_entry = mb_buf;
+       int ret = 0;
 
        if (flags & IB_MR_REREG_PD) {
                roce_set_field(mpt_entry->byte_4_pd_hop_st, V2_MPT_BYTE_4_PD_M,
@@ -1880,14 +1880,14 @@ static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,
                             V2_MPT_BYTE_8_BIND_EN_S,
                             (mr_access_flags & IB_ACCESS_MW_BIND ? 1 : 0));
                roce_set_bit(mpt_entry->byte_8_mw_cnt_en,
-                          V2_MPT_BYTE_8_ATOMIC_EN_S,
-                          (mr_access_flags & IB_ACCESS_REMOTE_ATOMIC ? 1 : 0));
+                            V2_MPT_BYTE_8_ATOMIC_EN_S,
+                            mr_access_flags & IB_ACCESS_REMOTE_ATOMIC ? 1 : 0);
                roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_RR_EN_S,
-                            (mr_access_flags & IB_ACCESS_REMOTE_READ ? 1 : 0));
+                            mr_access_flags & IB_ACCESS_REMOTE_READ ? 1 : 0);
                roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_RW_EN_S,
-                           (mr_access_flags & IB_ACCESS_REMOTE_WRITE ? 1 : 0));
+                            mr_access_flags & IB_ACCESS_REMOTE_WRITE ? 1 : 0);
                roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_LW_EN_S,
-                            (mr_access_flags & IB_ACCESS_LOCAL_WRITE ? 1 : 0));
+                            mr_access_flags & IB_ACCESS_LOCAL_WRITE ? 1 : 0);
        }
 
        if (flags & IB_MR_REREG_TRANS) {
@@ -1896,21 +1896,13 @@ static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,
                mpt_entry->len_l = cpu_to_le32(lower_32_bits(size));
                mpt_entry->len_h = cpu_to_le32(upper_32_bits(size));
 
-               mpt_entry->pbl_size = cpu_to_le32(mr->pbl_size);
-               mpt_entry->pbl_ba_l =
-                               cpu_to_le32(lower_32_bits(mr->pbl_ba >> 3));
-               roce_set_field(mpt_entry->byte_48_mode_ba,
-                              V2_MPT_BYTE_48_PBL_BA_H_M,
-                              V2_MPT_BYTE_48_PBL_BA_H_S,
-                              upper_32_bits(mr->pbl_ba >> 3));
-               mpt_entry->byte_48_mode_ba =
-                               cpu_to_le32(mpt_entry->byte_48_mode_ba);
-
                mr->iova = iova;
                mr->size = size;
+
+               ret = set_mtpt_pbl(mpt_entry, mr);
        }
 
-       return 0;
+       return ret;
 }
 
 static int hns_roce_v2_frmr_write_mtpt(void *mb_buf, struct hns_roce_mr *mr)
index e9c4280..3569fda 100644 (file)
@@ -1094,31 +1094,26 @@ enum mlx5_ib_width {
        MLX5_IB_WIDTH_12X       = 1 << 4
 };
 
-static int translate_active_width(struct ib_device *ibdev, u8 active_width,
+static void translate_active_width(struct ib_device *ibdev, u8 active_width,
                                  u8 *ib_width)
 {
        struct mlx5_ib_dev *dev = to_mdev(ibdev);
-       int err = 0;
 
-       if (active_width & MLX5_IB_WIDTH_1X) {
+       if (active_width & MLX5_IB_WIDTH_1X)
                *ib_width = IB_WIDTH_1X;
-       } else if (active_width & MLX5_IB_WIDTH_2X) {
-               mlx5_ib_dbg(dev, "active_width %d is not supported by IB spec\n",
-                           (int)active_width);
-               err = -EINVAL;
-       } else if (active_width & MLX5_IB_WIDTH_4X) {
+       else if (active_width & MLX5_IB_WIDTH_4X)
                *ib_width = IB_WIDTH_4X;
-       } else if (active_width & MLX5_IB_WIDTH_8X) {
+       else if (active_width & MLX5_IB_WIDTH_8X)
                *ib_width = IB_WIDTH_8X;
-       } else if (active_width & MLX5_IB_WIDTH_12X) {
+       else if (active_width & MLX5_IB_WIDTH_12X)
                *ib_width = IB_WIDTH_12X;
-       else {
-               mlx5_ib_dbg(dev, "Invalid active_width %d\n",
+       else {
+               mlx5_ib_dbg(dev, "Invalid active_width %d, setting width to default value: 4x\n",
                            (int)active_width);
-               err = -EINVAL;
+               *ib_width = IB_WIDTH_4X;
        }
 
-       return err;
+       return;
 }
 
 static int mlx5_mtu_to_ib_mtu(int mtu)
@@ -1225,10 +1220,8 @@ static int mlx5_query_hca_port(struct ib_device *ibdev, u8 port,
        if (err)
                goto out;
 
-       err = translate_active_width(ibdev, ib_link_width_oper,
-                                    &props->active_width);
-       if (err)
-               goto out;
+       translate_active_width(ibdev, ib_link_width_oper, &props->active_width);
+
        err = mlx5_query_port_ib_proto_oper(mdev, &props->active_speed, port);
        if (err)
                goto out;
index b04eb67..2cc3d69 100644 (file)
@@ -674,6 +674,15 @@ next_mr:
                        goto srcu_unlock;
                }
 
+               if (!mr->umem->is_odp) {
+                       mlx5_ib_dbg(dev, "skipping non ODP MR (lkey=0x%06x) in page fault handler.\n",
+                                   key);
+                       if (bytes_mapped)
+                               *bytes_mapped += bcnt;
+                       ret = 0;
+                       goto srcu_unlock;
+               }
+
                ret = pagefault_mr(dev, mr, io_virt, bcnt, bytes_mapped);
                if (ret < 0)
                        goto srcu_unlock;
@@ -735,6 +744,7 @@ next_mr:
                        head = frame;
 
                        bcnt -= frame->bcnt;
+                       offset = 0;
                }
                break;
 
index 6841c0f..3747cc6 100644 (file)
@@ -2633,8 +2633,7 @@ static int to_mlx5_access_flags(struct mlx5_ib_qp *qp,
 
        if (access_flags & IB_ACCESS_REMOTE_READ)
                *hw_access_flags |= MLX5_QP_BIT_RRE;
-       if ((access_flags & IB_ACCESS_REMOTE_ATOMIC) &&
-           qp->ibqp.qp_type == IB_QPT_RC) {
+       if (access_flags & IB_ACCESS_REMOTE_ATOMIC) {
                int atomic_mode;
 
                atomic_mode = get_atomic_mode(dev, qp->ibqp.qp_type);
@@ -4678,17 +4677,18 @@ static int _mlx5_ib_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
                        goto out;
                }
 
-               if (wr->opcode == IB_WR_LOCAL_INV ||
-                   wr->opcode == IB_WR_REG_MR) {
+               if (wr->opcode == IB_WR_REG_MR) {
                        fence = dev->umr_fence;
                        next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
-               } else if (wr->send_flags & IB_SEND_FENCE) {
-                       if (qp->next_fence)
-                               fence = MLX5_FENCE_MODE_SMALL_AND_FENCE;
-                       else
-                               fence = MLX5_FENCE_MODE_FENCE;
-               } else {
-                       fence = qp->next_fence;
+               } else  {
+                       if (wr->send_flags & IB_SEND_FENCE) {
+                               if (qp->next_fence)
+                                       fence = MLX5_FENCE_MODE_SMALL_AND_FENCE;
+                               else
+                                       fence = MLX5_FENCE_MODE_FENCE;
+                       } else {
+                               fence = qp->next_fence;
+                       }
                }
 
                switch (ibqp->qp_type) {
index 89ec0f6..084bb4b 100644 (file)
@@ -91,13 +91,15 @@ EXPORT_SYMBOL(rvt_check_ah);
  * rvt_create_ah - create an address handle
  * @pd: the protection domain
  * @ah_attr: the attributes of the AH
+ * @udata: pointer to user's input output buffer information.
  *
  * This may be called from interrupt context.
  *
  * Return: newly allocated ah
  */
 struct ib_ah *rvt_create_ah(struct ib_pd *pd,
-                           struct rdma_ah_attr *ah_attr)
+                           struct rdma_ah_attr *ah_attr,
+                           struct ib_udata *udata)
 {
        struct rvt_ah *ah;
        struct rvt_dev_info *dev = ib_to_rvt(pd->device);
index 16105af..25271b4 100644 (file)
@@ -51,7 +51,8 @@
 #include <rdma/rdma_vt.h>
 
 struct ib_ah *rvt_create_ah(struct ib_pd *pd,
-                           struct rdma_ah_attr *ah_attr);
+                           struct rdma_ah_attr *ah_attr,
+                           struct ib_udata *udata);
 int rvt_destroy_ah(struct ib_ah *ibah);
 int rvt_modify_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);
 int rvt_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);
index 946b623..4ff3d98 100644 (file)
@@ -1124,7 +1124,9 @@ u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,
                                         IB_MR_CHECK_SIG_STATUS, &mr_status);
                if (ret) {
                        pr_err("ib_check_mr_status failed, ret %d\n", ret);
-                       goto err;
+                       /* Not a lot we can do, return ambiguous guard error */
+                       *sector = 0;
+                       return 0x1;
                }
 
                if (mr_status.fail_status & IB_MR_CHECK_SIG_STATUS) {
@@ -1152,9 +1154,6 @@ u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,
        }
 
        return 0;
-err:
-       /* Not alot we can do here, return ambiguous guard error */
-       return 0x1;
 }
 
 void iser_err_comp(struct ib_wc *wc, const char *type)
index d4b9db4..cfc8b94 100644 (file)
@@ -480,18 +480,18 @@ static const u8 xboxone_hori_init[] = {
 };
 
 /*
- * This packet is required for some of the PDP pads to start
+ * This packet is required for most (all?) of the PDP pads to start
  * sending input reports. These pads include: (0x0e6f:0x02ab),
- * (0x0e6f:0x02a4).
+ * (0x0e6f:0x02a4), (0x0e6f:0x02a6).
  */
 static const u8 xboxone_pdp_init1[] = {
        0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14
 };
 
 /*
- * This packet is required for some of the PDP pads to start
+ * This packet is required for most (all?) of the PDP pads to start
  * sending input reports. These pads include: (0x0e6f:0x02ab),
- * (0x0e6f:0x02a4).
+ * (0x0e6f:0x02a4), (0x0e6f:0x02a6).
  */
 static const u8 xboxone_pdp_init2[] = {
        0x06, 0x20, 0x00, 0x02, 0x01, 0x00
@@ -527,12 +527,8 @@ static const struct xboxone_init_packet xboxone_init_packets[] = {
        XBOXONE_INIT_PKT(0x0e6f, 0x0165, xboxone_hori_init),
        XBOXONE_INIT_PKT(0x0f0d, 0x0067, xboxone_hori_init),
        XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init),
-       XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init1),
-       XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init2),
-       XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init1),
-       XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init2),
-       XBOXONE_INIT_PKT(0x0e6f, 0x02a6, xboxone_pdp_init1),
-       XBOXONE_INIT_PKT(0x0e6f, 0x02a6, xboxone_pdp_init2),
+       XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init1),
+       XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init2),
        XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init),
        XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init),
        XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init),
index 7e75835..850bb25 100644 (file)
@@ -841,7 +841,7 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra
        if (param[0] != 3) {
                param[0] = 2;
                if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET))
-               return 2;
+                       return 2;
        }
 
        ps2_command(ps2dev, param, ATKBD_CMD_SETALL_MBR);
index 81be6f7..d560011 100644 (file)
@@ -493,7 +493,8 @@ static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev)
        for (i = 0; i < ARRAY_SIZE(cros_ec_keyb_bs); i++) {
                const struct cros_ec_bs_map *map = &cros_ec_keyb_bs[i];
 
-               if (buttons & BIT(map->bit))
+               if ((map->ev_type == EV_KEY && (buttons & BIT(map->bit))) ||
+                   (map->ev_type == EV_SW && (switches & BIT(map->bit))))
                        input_set_capability(idev, map->ev_type, map->code);
        }
 
index f51ae09..403452e 100644 (file)
@@ -407,7 +407,7 @@ matrix_keypad_parse_dt(struct device *dev)
        struct matrix_keypad_platform_data *pdata;
        struct device_node *np = dev->of_node;
        unsigned int *gpios;
-       int i, nrow, ncol;
+       int ret, i, nrow, ncol;
 
        if (!np) {
                dev_err(dev, "device lacks DT data\n");
@@ -452,12 +452,19 @@ matrix_keypad_parse_dt(struct device *dev)
                return ERR_PTR(-ENOMEM);
        }
 
-       for (i = 0; i < pdata->num_row_gpios; i++)
-               gpios[i] = of_get_named_gpio(np, "row-gpios", i);
+       for (i = 0; i < nrow; i++) {
+               ret = of_get_named_gpio(np, "row-gpios", i);
+               if (ret < 0)
+                       return ERR_PTR(ret);
+               gpios[i] = ret;
+       }
 
-       for (i = 0; i < pdata->num_col_gpios; i++)
-               gpios[pdata->num_row_gpios + i] =
-                       of_get_named_gpio(np, "col-gpios", i);
+       for (i = 0; i < ncol; i++) {
+               ret = of_get_named_gpio(np, "col-gpios", i);
+               if (ret < 0)
+                       return ERR_PTR(ret);
+               gpios[nrow + i] = ret;
+       }
 
        pdata->row_gpios = gpios;
        pdata->col_gpios = &gpios[pdata->num_row_gpios];
@@ -484,10 +491,8 @@ static int matrix_keypad_probe(struct platform_device *pdev)
        pdata = dev_get_platdata(&pdev->dev);
        if (!pdata) {
                pdata = matrix_keypad_parse_dt(&pdev->dev);
-               if (IS_ERR(pdata)) {
-                       dev_err(&pdev->dev, "no platform data defined\n");
+               if (IS_ERR(pdata))
                        return PTR_ERR(pdata);
-               }
        } else if (!pdata->keymap_data) {
                dev_err(&pdev->dev, "no keymap data defined\n");
                return -EINVAL;
index 4640634..a7dc286 100644 (file)
 
 /* OMAP4 values */
 #define OMAP4_VAL_IRQDISABLE           0x0
-#define OMAP4_VAL_DEBOUNCINGTIME       0x7
-#define OMAP4_VAL_PVT                  0x7
+
+/*
+ * Errata i689: If a key is released for a time shorter than debounce time,
+ * the keyboard will idle and never detect the key release. The workaround
+ * is to use at least a 12ms debounce time. See omap5432 TRM chapter
+ * "26.4.6.2 Keyboard Controller Timer" for more information.
+ */
+#define OMAP4_KEYPAD_PTV_DIV_128        0x6
+#define OMAP4_KEYPAD_DEBOUNCINGTIME_MS(dbms, ptv)     \
+       ((((dbms) * 1000) / ((1 << ((ptv) + 1)) * (1000000 / 32768))) - 1)
+#define OMAP4_VAL_DEBOUNCINGTIME_16MS                                  \
+       OMAP4_KEYPAD_DEBOUNCINGTIME_MS(16, OMAP4_KEYPAD_PTV_DIV_128)
 
 enum {
        KBD_REVISION_OMAP4 = 0,
@@ -181,9 +191,9 @@ static int omap4_keypad_open(struct input_dev *input)
 
        kbd_writel(keypad_data, OMAP4_KBD_CTRL,
                        OMAP4_DEF_CTRL_NOSOFTMODE |
-                       (OMAP4_VAL_PVT << OMAP4_DEF_CTRL_PTV_SHIFT));
+                       (OMAP4_KEYPAD_PTV_DIV_128 << OMAP4_DEF_CTRL_PTV_SHIFT));
        kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME,
-                       OMAP4_VAL_DEBOUNCINGTIME);
+                       OMAP4_VAL_DEBOUNCINGTIME_16MS);
        /* clear pending interrupts */
        kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
                         kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
index b0f9d19..a94b649 100644 (file)
@@ -1348,6 +1348,9 @@ static const struct acpi_device_id elan_acpi_id[] = {
        { "ELAN0618", 0 },
        { "ELAN061C", 0 },
        { "ELAN061D", 0 },
+       { "ELAN061E", 0 },
+       { "ELAN0620", 0 },
+       { "ELAN0621", 0 },
        { "ELAN0622", 0 },
        { "ELAN1000", 0 },
        { }
index 5e85f3c..2bd5bb1 100644 (file)
@@ -170,6 +170,7 @@ static const char * const smbus_pnp_ids[] = {
        "LEN0048", /* X1 Carbon 3 */
        "LEN0046", /* X250 */
        "LEN004a", /* W541 */
+       "LEN005b", /* P50 */
        "LEN0071", /* T480 */
        "LEN0072", /* X1 Carbon Gen 5 (2017) - Elan/ALPS trackpoint */
        "LEN0073", /* X1 Carbon G5 (Elantech) */
@@ -177,6 +178,7 @@ static const char * const smbus_pnp_ids[] = {
        "LEN0096", /* X280 */
        "LEN0097", /* X280 -> ALPS trackpoint */
        "LEN200f", /* T450s */
+       "SYN3221", /* HP 15-ay000 */
        NULL
 };
 
index 47a0e81..a8b9be3 100644 (file)
@@ -177,7 +177,7 @@ static void hv_kbd_on_receive(struct hv_device *hv_dev,
                 * state because the Enter-UP can trigger a wakeup at once.
                 */
                if (!(info & IS_BREAK))
-                       pm_wakeup_event(&hv_dev->device, 0);
+                       pm_wakeup_hard_event(&hv_dev->device);
 
                break;
 
index 02fb119..42d3fd7 100644 (file)
@@ -1,23 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Touch Screen driver for Renesas MIGO-R Platform
  *
  * Copyright (c) 2008 Magnus Damm
  * Copyright (c) 2007 Ujjwal Pande <ujjwal@kenati.com>,
  *  Kenati Technologies Pvt Ltd.
- *
- * This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU  General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This file is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
index b716739..11ff32c 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * ST1232 Touchscreen Controller Driver
  *
@@ -7,15 +8,6 @@
  * Using code from:
  *  - android.git.kernel.org: projects/kernel/common.git: synaptics_i2c_rmi.c
  *     Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/delay.h>
@@ -295,4 +287,4 @@ module_i2c_driver(st1232_ts_driver);
 
 MODULE_AUTHOR("Tony SIM <chinyeow.sim.xt@renesas.com>");
 MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
index 6d4b2ee..29836c1 100644 (file)
@@ -80,8 +80,8 @@ struct dvb_pll_desc {
 
 static const struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
        .name  = "Thomson dtt7579",
-       .min   = 177000000,
-       .max   = 858000000,
+       .min   = 177 * MHz,
+       .max   = 858 * MHz,
        .iffreq= 36166667,
        .sleepdata = (u8[]){ 2, 0xb4, 0x03 },
        .count = 4,
@@ -102,8 +102,8 @@ static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf)
 
 static const struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
        .name  = "Thomson dtt759x",
-       .min   = 177000000,
-       .max   = 896000000,
+       .min   = 177 * MHz,
+       .max   = 896 * MHz,
        .set   = thomson_dtt759x_bw,
        .iffreq= 36166667,
        .sleepdata = (u8[]){ 2, 0x84, 0x03 },
@@ -126,8 +126,8 @@ static void thomson_dtt7520x_bw(struct dvb_frontend *fe, u8 *buf)
 
 static const struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
        .name  = "Thomson dtt7520x",
-       .min   = 185000000,
-       .max   = 900000000,
+       .min   = 185 * MHz,
+       .max   = 900 * MHz,
        .set   = thomson_dtt7520x_bw,
        .iffreq = 36166667,
        .count = 7,
@@ -144,8 +144,8 @@ static const struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
 
 static const struct dvb_pll_desc dvb_pll_lg_z201 = {
        .name  = "LG z201",
-       .min   = 174000000,
-       .max   = 862000000,
+       .min   = 174 * MHz,
+       .max   = 862 * MHz,
        .iffreq= 36166667,
        .sleepdata = (u8[]){ 2, 0xbc, 0x03 },
        .count = 5,
@@ -160,8 +160,8 @@ static const struct dvb_pll_desc dvb_pll_lg_z201 = {
 
 static const struct dvb_pll_desc dvb_pll_unknown_1 = {
        .name  = "unknown 1", /* used by dntv live dvb-t */
-       .min   = 174000000,
-       .max   = 862000000,
+       .min   = 174 * MHz,
+       .max   = 862 * MHz,
        .iffreq= 36166667,
        .count = 9,
        .entries = {
@@ -182,8 +182,8 @@ static const struct dvb_pll_desc dvb_pll_unknown_1 = {
  */
 static const struct dvb_pll_desc dvb_pll_tua6010xs = {
        .name  = "Infineon TUA6010XS",
-       .min   =  44250000,
-       .max   = 858000000,
+       .min   = 44250 * kHz,
+       .max   = 858 * MHz,
        .iffreq= 36125000,
        .count = 3,
        .entries = {
@@ -196,8 +196,8 @@ static const struct dvb_pll_desc dvb_pll_tua6010xs = {
 /* Panasonic env57h1xd5 (some Philips PLL ?) */
 static const struct dvb_pll_desc dvb_pll_env57h1xd5 = {
        .name  = "Panasonic ENV57H1XD5",
-       .min   =  44250000,
-       .max   = 858000000,
+       .min   = 44250 * kHz,
+       .max   = 858 * MHz,
        .iffreq= 36125000,
        .count = 4,
        .entries = {
@@ -220,8 +220,8 @@ static void tda665x_bw(struct dvb_frontend *fe, u8 *buf)
 
 static const struct dvb_pll_desc dvb_pll_tda665x = {
        .name  = "Philips TDA6650/TDA6651",
-       .min   =  44250000,
-       .max   = 858000000,
+       .min   = 44250 * kHz,
+       .max   = 858 * MHz,
        .set   = tda665x_bw,
        .iffreq= 36166667,
        .initdata = (u8[]){ 4, 0x0b, 0xf5, 0x85, 0xab },
@@ -254,8 +254,8 @@ static void tua6034_bw(struct dvb_frontend *fe, u8 *buf)
 
 static const struct dvb_pll_desc dvb_pll_tua6034 = {
        .name  = "Infineon TUA6034",
-       .min   =  44250000,
-       .max   = 858000000,
+       .min   = 44250 * kHz,
+       .max   = 858 * MHz,
        .iffreq= 36166667,
        .count = 3,
        .set   = tua6034_bw,
@@ -278,8 +278,8 @@ static void tded4_bw(struct dvb_frontend *fe, u8 *buf)
 
 static const struct dvb_pll_desc dvb_pll_tded4 = {
        .name = "ALPS TDED4",
-       .min = 47000000,
-       .max = 863000000,
+       .min =  47 * MHz,
+       .max = 863 * MHz,
        .iffreq= 36166667,
        .set   = tded4_bw,
        .count = 4,
@@ -296,8 +296,8 @@ static const struct dvb_pll_desc dvb_pll_tded4 = {
  */
 static const struct dvb_pll_desc dvb_pll_tdhu2 = {
        .name = "ALPS TDHU2",
-       .min = 54000000,
-       .max = 864000000,
+       .min =  54 * MHz,
+       .max = 864 * MHz,
        .iffreq= 44000000,
        .count = 4,
        .entries = {
@@ -313,8 +313,8 @@ static const struct dvb_pll_desc dvb_pll_tdhu2 = {
  */
 static const struct dvb_pll_desc dvb_pll_samsung_tbmv = {
        .name = "Samsung TBMV30111IN / TBMV30712IN1",
-       .min = 54000000,
-       .max = 860000000,
+       .min =  54 * MHz,
+       .max = 860 * MHz,
        .iffreq= 44000000,
        .count = 6,
        .entries = {
@@ -332,8 +332,8 @@ static const struct dvb_pll_desc dvb_pll_samsung_tbmv = {
  */
 static const struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
        .name  = "Philips SD1878",
-       .min   =  950000,
-       .max   = 2150000,
+       .min   =  950 * MHz,
+       .max   = 2150 * MHz,
        .iffreq= 249, /* zero-IF, offset 249 is to round up */
        .count = 4,
        .entries = {
@@ -398,8 +398,8 @@ static void opera1_bw(struct dvb_frontend *fe, u8 *buf)
 
 static const struct dvb_pll_desc dvb_pll_opera1 = {
        .name  = "Opera Tuner",
-       .min   =  900000,
-       .max   = 2250000,
+       .min   =  900 * MHz,
+       .max   = 2250 * MHz,
        .initdata = (u8[]){ 4, 0x08, 0xe5, 0xe1, 0x00 },
        .initdata2 = (u8[]){ 4, 0x08, 0xe5, 0xe5, 0x00 },
        .iffreq= 0,
@@ -445,8 +445,8 @@ static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf)
 /* unknown pll used in Samsung DTOS403IH102A DVB-C tuner */
 static const struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
        .name   = "Samsung DTOS403IH102A",
-       .min    =  44250000,
-       .max    = 858000000,
+       .min    = 44250 * kHz,
+       .max    = 858 * MHz,
        .iffreq =  36125000,
        .count  = 8,
        .set    = samsung_dtos403ih102a_set,
@@ -465,8 +465,8 @@ static const struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
 /* Samsung TDTC9251DH0 DVB-T NIM, as used on AirStar 2 */
 static const struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {
        .name   = "Samsung TDTC9251DH0",
-       .min    =  48000000,
-       .max    = 863000000,
+       .min    =  48 * MHz,
+       .max    = 863 * MHz,
        .iffreq =  36166667,
        .count  = 3,
        .entries = {
@@ -479,8 +479,8 @@ static const struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {
 /* Samsung TBDU18132 DVB-S NIM with TSA5059 PLL, used in SkyStar2 DVB-S 2.3 */
 static const struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {
        .name = "Samsung TBDU18132",
-       .min    =  950000,
-       .max    = 2150000, /* guesses */
+       .min    =  950 * MHz,
+       .max    = 2150 * MHz, /* guesses */
        .iffreq = 0,
        .count = 2,
        .entries = {
@@ -500,8 +500,8 @@ static const struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {
 /* Samsung TBMU24112 DVB-S NIM with SL1935 zero-IF tuner */
 static const struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {
        .name = "Samsung TBMU24112",
-       .min    =  950000,
-       .max    = 2150000, /* guesses */
+       .min    =  950 * MHz,
+       .max    = 2150 * MHz, /* guesses */
        .iffreq = 0,
        .count = 2,
        .entries = {
@@ -521,8 +521,8 @@ static const struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {
  * 822 - 862   1  *  0   0   1   0   0   0   0x88 */
 static const struct dvb_pll_desc dvb_pll_alps_tdee4 = {
        .name = "ALPS TDEE4",
-       .min    =  47000000,
-       .max    = 862000000,
+       .min    =  47 * MHz,
+       .max    = 862 * MHz,
        .iffreq =  36125000,
        .count = 4,
        .entries = {
@@ -537,8 +537,8 @@ static const struct dvb_pll_desc dvb_pll_alps_tdee4 = {
 /* CP cur. 50uA, AGC takeover: 103dBuV, PORT3 on */
 static const struct dvb_pll_desc dvb_pll_tua6034_friio = {
        .name   = "Infineon TUA6034 ISDB-T (Friio)",
-       .min    =  90000000,
-       .max    = 770000000,
+       .min    =  90 * MHz,
+       .max    = 770 * MHz,
        .iffreq =  57000000,
        .initdata = (u8[]){ 4, 0x9a, 0x50, 0xb2, 0x08 },
        .sleepdata = (u8[]){ 4, 0x9a, 0x70, 0xb3, 0x0b },
@@ -553,8 +553,8 @@ static const struct dvb_pll_desc dvb_pll_tua6034_friio = {
 /* Philips TDA6651 ISDB-T, used in Earthsoft PT1 */
 static const struct dvb_pll_desc dvb_pll_tda665x_earth_pt1 = {
        .name   = "Philips TDA6651 ISDB-T (EarthSoft PT1)",
-       .min    =  90000000,
-       .max    = 770000000,
+       .min    =  90 * MHz,
+       .max    = 770 * MHz,
        .iffreq =  57000000,
        .initdata = (u8[]){ 5, 0x0e, 0x7f, 0xc1, 0x80, 0x80 },
        .count = 10,
@@ -610,9 +610,6 @@ static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
        u32 div;
        int i;
 
-       if (frequency && (frequency < desc->min || frequency > desc->max))
-               return -EINVAL;
-
        for (i = 0; i < desc->count; i++) {
                if (frequency > desc->entries[i].limit)
                        continue;
@@ -799,7 +796,6 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
        struct dvb_pll_priv *priv = NULL;
        int ret;
        const struct dvb_pll_desc *desc;
-       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
        b1 = kmalloc(1, GFP_KERNEL);
        if (!b1)
@@ -845,18 +841,12 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
 
        strncpy(fe->ops.tuner_ops.info.name, desc->name,
                sizeof(fe->ops.tuner_ops.info.name));
-       switch (c->delivery_system) {
-       case SYS_DVBS:
-       case SYS_DVBS2:
-       case SYS_TURBO:
-       case SYS_ISDBS:
-               fe->ops.tuner_ops.info.frequency_min_hz = desc->min * kHz;
-               fe->ops.tuner_ops.info.frequency_max_hz = desc->max * kHz;
-               break;
-       default:
-               fe->ops.tuner_ops.info.frequency_min_hz = desc->min;
-               fe->ops.tuner_ops.info.frequency_max_hz = desc->max;
-       }
+
+       fe->ops.tuner_ops.info.frequency_min_hz = desc->min;
+       fe->ops.tuner_ops.info.frequency_max_hz = desc->max;
+
+       dprintk("%s tuner, frequency range: %u...%u\n",
+               desc->name, desc->min, desc->max);
 
        if (!desc->initdata)
                fe->ops.tuner_ops.init = NULL;
index 4e9db1f..c71a34a 100644 (file)
@@ -238,6 +238,9 @@ static const struct file_operations request_fops = {
        .owner = THIS_MODULE,
        .poll = media_request_poll,
        .unlocked_ioctl = media_request_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = media_request_ioctl,
+#endif /* CONFIG_COMPAT */
        .release = media_request_close,
 };
 
index b292cff..013cdeb 100644 (file)
@@ -304,7 +304,8 @@ restart:
                for (; p < p_out + sz; p++) {
                        u32 copy;
 
-                       p = memchr(p, magic[ctx->comp_magic_cnt], sz);
+                       p = memchr(p, magic[ctx->comp_magic_cnt],
+                                  p_out + sz - p);
                        if (!p) {
                                ctx->comp_magic_cnt = 0;
                                break;
index fce9d6f..3137f5d 100644 (file)
@@ -426,10 +426,10 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,
 
        /* append the packet to the frame buffer */
        if (len > 0) {
-               if (gspca_dev->image_len + len > gspca_dev->pixfmt.sizeimage) {
+               if (gspca_dev->image_len + len > PAGE_ALIGN(gspca_dev->pixfmt.sizeimage)) {
                        gspca_err(gspca_dev, "frame overflow %d > %d\n",
                                  gspca_dev->image_len + len,
-                                 gspca_dev->pixfmt.sizeimage);
+                                 PAGE_ALIGN(gspca_dev->pixfmt.sizeimage));
                        packet_type = DISCARD_PACKET;
                } else {
 /* !! image is NULL only when last pkt is LAST or DISCARD
@@ -1297,18 +1297,19 @@ static int gspca_queue_setup(struct vb2_queue *vq,
                             unsigned int sizes[], struct device *alloc_devs[])
 {
        struct gspca_dev *gspca_dev = vb2_get_drv_priv(vq);
+       unsigned int size = PAGE_ALIGN(gspca_dev->pixfmt.sizeimage);
 
        if (*nplanes)
-               return sizes[0] < gspca_dev->pixfmt.sizeimage ? -EINVAL : 0;
+               return sizes[0] < size ? -EINVAL : 0;
        *nplanes = 1;
-       sizes[0] = gspca_dev->pixfmt.sizeimage;
+       sizes[0] = size;
        return 0;
 }
 
 static int gspca_buffer_prepare(struct vb2_buffer *vb)
 {
        struct gspca_dev *gspca_dev = vb2_get_drv_priv(vb->vb2_queue);
-       unsigned long size = gspca_dev->pixfmt.sizeimage;
+       unsigned long size = PAGE_ALIGN(gspca_dev->pixfmt.sizeimage);
 
        if (vb2_plane_size(vb, 0) < size) {
                gspca_err(gspca_dev, "buffer too small (%lu < %lu)\n",
index 8f9d696..b99a194 100644 (file)
@@ -263,6 +263,11 @@ static const struct file_operations fops = {
 #endif
 };
 
+static void cros_ec_class_release(struct device *dev)
+{
+       kfree(to_cros_ec_dev(dev));
+}
+
 static void cros_ec_sensors_register(struct cros_ec_dev *ec)
 {
        /*
@@ -395,7 +400,7 @@ static int ec_device_probe(struct platform_device *pdev)
        int retval = -ENOMEM;
        struct device *dev = &pdev->dev;
        struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
-       struct cros_ec_dev *ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL);
+       struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
 
        if (!ec)
                return retval;
@@ -417,6 +422,7 @@ static int ec_device_probe(struct platform_device *pdev)
        ec->class_dev.devt = MKDEV(ec_major, pdev->id);
        ec->class_dev.class = &cros_class;
        ec->class_dev.parent = dev;
+       ec->class_dev.release = cros_ec_class_release;
 
        retval = dev_set_name(&ec->class_dev, "%s", ec_platform->ec_name);
        if (retval) {
index c824329..0e4193c 100644 (file)
@@ -416,7 +416,7 @@ static int scif_create_remote_lookup(struct scif_dev *remote_dev,
                if (err)
                        goto error_window;
                err = scif_map_page(&window->num_pages_lookup.lookup[j],
-                                   vmalloc_dma_phys ?
+                                   vmalloc_num_pages ?
                                    vmalloc_to_page(&window->num_pages[i]) :
                                    virt_to_page(&window->num_pages[i]),
                                    remote_dev);
index 56cde38..044adf9 100644 (file)
@@ -27,7 +27,8 @@ int nanddev_bbt_init(struct nand_device *nand)
        unsigned int nwords = DIV_ROUND_UP(nblocks * bits_per_block,
                                           BITS_PER_LONG);
 
-       nand->bbt.cache = kzalloc(nwords, GFP_KERNEL);
+       nand->bbt.cache = kcalloc(nwords, sizeof(*nand->bbt.cache),
+                                 GFP_KERNEL);
        if (!nand->bbt.cache)
                return -ENOMEM;
 
index 93c9bc8..1fdd283 100644 (file)
@@ -2995,12 +2995,13 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
                                              const u32 *smpt)
 {
        struct spi_nor_erase_map *map = &nor->erase_map;
-       const struct spi_nor_erase_type *erase = map->erase_type;
+       struct spi_nor_erase_type *erase = map->erase_type;
        struct spi_nor_erase_region *region;
        u64 offset;
        u32 region_count;
        int i, j;
-       u8 erase_type, uniform_erase_type;
+       u8 uniform_erase_type, save_uniform_erase_type;
+       u8 erase_type, regions_erase_type;
 
        region_count = SMPT_MAP_REGION_COUNT(*smpt);
        /*
@@ -3014,6 +3015,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
        map->regions = region;
 
        uniform_erase_type = 0xff;
+       regions_erase_type = 0;
        offset = 0;
        /* Populate regions. */
        for (i = 0; i < region_count; i++) {
@@ -3030,13 +3032,38 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
                 */
                uniform_erase_type &= erase_type;
 
+               /*
+                * regions_erase_type mask will indicate all the erase types
+                * supported in this configuration map.
+                */
+               regions_erase_type |= erase_type;
+
                offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) +
                         region[i].size;
        }
 
+       save_uniform_erase_type = map->uniform_erase_type;
        map->uniform_erase_type = spi_nor_sort_erase_mask(map,
                                                          uniform_erase_type);
 
+       if (!regions_erase_type) {
+               /*
+                * Roll back to the previous uniform_erase_type mask, SMPT is
+                * broken.
+                */
+               map->uniform_erase_type = save_uniform_erase_type;
+               return -EINVAL;
+       }
+
+       /*
+        * BFPT advertises all the erase types supported by all the possible
+        * map configurations. Mask out the erase types that are not supported
+        * by the current map configuration.
+        */
+       for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
+               if (!(regions_erase_type & BIT(erase[i].idx)))
+                       spi_nor_set_erase_type(&erase[i], 0, 0xFF);
+
        spi_nor_region_mark_end(&region[i - 1]);
 
        return 0;
index 182258f..d0c621b 100644 (file)
@@ -111,6 +111,8 @@ resource_size_t nd_pmem_available_dpa(struct nd_region *nd_region,
                struct nd_mapping *nd_mapping, resource_size_t *overlap);
 resource_size_t nd_blk_available_dpa(struct nd_region *nd_region);
 resource_size_t nd_region_available_dpa(struct nd_region *nd_region);
+int nd_region_conflict(struct nd_region *nd_region, resource_size_t start,
+               resource_size_t size);
 resource_size_t nvdimm_allocated_dpa(struct nvdimm_drvdata *ndd,
                struct nd_label_id *label_id);
 int alias_dpa_busy(struct device *dev, void *data);
index 24c6409..6f22272 100644 (file)
@@ -649,14 +649,47 @@ static u64 phys_pmem_align_down(struct nd_pfn *nd_pfn, u64 phys)
                        ALIGN_DOWN(phys, nd_pfn->align));
 }
 
+/*
+ * Check if pmem collides with 'System RAM', or other regions when
+ * section aligned.  Trim it accordingly.
+ */
+static void trim_pfn_device(struct nd_pfn *nd_pfn, u32 *start_pad, u32 *end_trunc)
+{
+       struct nd_namespace_common *ndns = nd_pfn->ndns;
+       struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
+       struct nd_region *nd_region = to_nd_region(nd_pfn->dev.parent);
+       const resource_size_t start = nsio->res.start;
+       const resource_size_t end = start + resource_size(&nsio->res);
+       resource_size_t adjust, size;
+
+       *start_pad = 0;
+       *end_trunc = 0;
+
+       adjust = start - PHYS_SECTION_ALIGN_DOWN(start);
+       size = resource_size(&nsio->res) + adjust;
+       if (region_intersects(start - adjust, size, IORESOURCE_SYSTEM_RAM,
+                               IORES_DESC_NONE) == REGION_MIXED
+                       || nd_region_conflict(nd_region, start - adjust, size))
+               *start_pad = PHYS_SECTION_ALIGN_UP(start) - start;
+
+       /* Now check that end of the range does not collide. */
+       adjust = PHYS_SECTION_ALIGN_UP(end) - end;
+       size = resource_size(&nsio->res) + adjust;
+       if (region_intersects(start, size, IORESOURCE_SYSTEM_RAM,
+                               IORES_DESC_NONE) == REGION_MIXED
+                       || !IS_ALIGNED(end, nd_pfn->align)
+                       || nd_region_conflict(nd_region, start, size + adjust))
+               *end_trunc = end - phys_pmem_align_down(nd_pfn, end);
+}
+
 static int nd_pfn_init(struct nd_pfn *nd_pfn)
 {
        u32 dax_label_reserve = is_nd_dax(&nd_pfn->dev) ? SZ_128K : 0;
        struct nd_namespace_common *ndns = nd_pfn->ndns;
-       u32 start_pad = 0, end_trunc = 0;
+       struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
        resource_size_t start, size;
-       struct nd_namespace_io *nsio;
        struct nd_region *nd_region;
+       u32 start_pad, end_trunc;
        struct nd_pfn_sb *pfn_sb;
        unsigned long npfns;
        phys_addr_t offset;
@@ -688,30 +721,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
 
        memset(pfn_sb, 0, sizeof(*pfn_sb));
 
-       /*
-        * Check if pmem collides with 'System RAM' when section aligned and
-        * trim it accordingly
-        */
-       nsio = to_nd_namespace_io(&ndns->dev);
-       start = PHYS_SECTION_ALIGN_DOWN(nsio->res.start);
-       size = resource_size(&nsio->res);
-       if (region_intersects(start, size, IORESOURCE_SYSTEM_RAM,
-                               IORES_DESC_NONE) == REGION_MIXED) {
-               start = nsio->res.start;
-               start_pad = PHYS_SECTION_ALIGN_UP(start) - start;
-       }
-
-       start = nsio->res.start;
-       size = PHYS_SECTION_ALIGN_UP(start + size) - start;
-       if (region_intersects(start, size, IORESOURCE_SYSTEM_RAM,
-                               IORES_DESC_NONE) == REGION_MIXED
-                       || !IS_ALIGNED(start + resource_size(&nsio->res),
-                               nd_pfn->align)) {
-               size = resource_size(&nsio->res);
-               end_trunc = start + size - phys_pmem_align_down(nd_pfn,
-                               start + size);
-       }
-
+       trim_pfn_device(nd_pfn, &start_pad, &end_trunc);
        if (start_pad + end_trunc)
                dev_info(&nd_pfn->dev, "%s alignment collision, truncate %d bytes\n",
                                dev_name(&ndns->dev), start_pad + end_trunc);
@@ -722,7 +732,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
         * implementation will limit the pfns advertised through
         * ->direct_access() to those that are included in the memmap.
         */
-       start += start_pad;
+       start = nsio->res.start + start_pad;
        size = resource_size(&nsio->res);
        npfns = PFN_SECTION_ALIGN_UP((size - start_pad - end_trunc - SZ_8K)
                        / PAGE_SIZE);
index 174a418..e7377f1 100644 (file)
@@ -1184,6 +1184,47 @@ int nvdimm_has_cache(struct nd_region *nd_region)
 }
 EXPORT_SYMBOL_GPL(nvdimm_has_cache);
 
+struct conflict_context {
+       struct nd_region *nd_region;
+       resource_size_t start, size;
+};
+
+static int region_conflict(struct device *dev, void *data)
+{
+       struct nd_region *nd_region;
+       struct conflict_context *ctx = data;
+       resource_size_t res_end, region_end, region_start;
+
+       if (!is_memory(dev))
+               return 0;
+
+       nd_region = to_nd_region(dev);
+       if (nd_region == ctx->nd_region)
+               return 0;
+
+       res_end = ctx->start + ctx->size;
+       region_start = nd_region->ndr_start;
+       region_end = region_start + nd_region->ndr_size;
+       if (ctx->start >= region_start && ctx->start < region_end)
+               return -EBUSY;
+       if (res_end > region_start && res_end <= region_end)
+               return -EBUSY;
+       return 0;
+}
+
+int nd_region_conflict(struct nd_region *nd_region, resource_size_t start,
+               resource_size_t size)
+{
+       struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(&nd_region->dev);
+       struct conflict_context ctx = {
+               .nd_region = nd_region,
+               .start = start,
+               .size = size,
+       };
+
+       return device_for_each_child(&nvdimm_bus->dev, &ctx, region_conflict);
+}
+
 void __exit nd_region_devs_exit(void)
 {
        ida_destroy(&region_ida);
index 559d567..9620121 100644 (file)
@@ -831,6 +831,8 @@ static int nvme_submit_user_cmd(struct request_queue *q,
 static void nvme_keep_alive_end_io(struct request *rq, blk_status_t status)
 {
        struct nvme_ctrl *ctrl = rq->end_io_data;
+       unsigned long flags;
+       bool startka = false;
 
        blk_mq_free_request(rq);
 
@@ -841,7 +843,13 @@ static void nvme_keep_alive_end_io(struct request *rq, blk_status_t status)
                return;
        }
 
-       schedule_delayed_work(&ctrl->ka_work, ctrl->kato * HZ);
+       spin_lock_irqsave(&ctrl->lock, flags);
+       if (ctrl->state == NVME_CTRL_LIVE ||
+           ctrl->state == NVME_CTRL_CONNECTING)
+               startka = true;
+       spin_unlock_irqrestore(&ctrl->lock, flags);
+       if (startka)
+               schedule_delayed_work(&ctrl->ka_work, ctrl->kato * HZ);
 }
 
 static int nvme_keep_alive(struct nvme_ctrl *ctrl)
@@ -3314,6 +3322,9 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
        struct nvme_ns *ns, *next;
        LIST_HEAD(ns_list);
 
+       /* prevent racing with ns scanning */
+       flush_work(&ctrl->scan_work);
+
        /*
         * The dead states indicates the controller was not gracefully
         * disconnected. In that case, we won't be able to flush any data while
@@ -3476,7 +3487,6 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl)
        nvme_mpath_stop(ctrl);
        nvme_stop_keep_alive(ctrl);
        flush_work(&ctrl->async_event_work);
-       flush_work(&ctrl->scan_work);
        cancel_work_sync(&ctrl->fw_act_work);
        if (ctrl->ops->stop_ctrl)
                ctrl->ops->stop_ctrl(ctrl);
@@ -3585,7 +3595,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
 
        return 0;
 out_free_name:
-       kfree_const(dev->kobj.name);
+       kfree_const(ctrl->device->kobj.name);
 out_release_instance:
        ida_simple_remove(&nvme_instance_ida, ctrl->instance);
 out:
@@ -3607,7 +3617,7 @@ void nvme_kill_queues(struct nvme_ctrl *ctrl)
        down_read(&ctrl->namespaces_rwsem);
 
        /* Forcibly unquiesce queues to avoid blocking dispatch */
-       if (ctrl->admin_q)
+       if (ctrl->admin_q && !blk_queue_dying(ctrl->admin_q))
                blk_mq_unquiesce_queue(ctrl->admin_q);
 
        list_for_each_entry(ns, &ctrl->namespaces, list)
index 54032c4..feb86b5 100644 (file)
@@ -1752,12 +1752,12 @@ nvme_fc_init_request(struct blk_mq_tag_set *set, struct request *rq,
        struct nvme_fc_queue *queue = &ctrl->queues[queue_idx];
        int res;
 
-       nvme_req(rq)->ctrl = &ctrl->ctrl;
        res = __nvme_fc_init_request(ctrl, queue, &op->op, rq, queue->rqcnt++);
        if (res)
                return res;
        op->op.fcp_req.first_sgl = &op->sgl[0];
        op->op.fcp_req.private = &op->priv[0];
+       nvme_req(rq)->ctrl = &ctrl->ctrl;
        return res;
 }
 
index cee79cb..081cbdc 100644 (file)
@@ -531,6 +531,9 @@ static inline void nvme_mpath_check_last_path(struct nvme_ns *ns)
 static inline int nvme_mpath_init(struct nvme_ctrl *ctrl,
                struct nvme_id_ctrl *id)
 {
+       if (ctrl->subsys->cmic & (1 << 3))
+               dev_warn(ctrl->device,
+"Please enable CONFIG_NVME_MULTIPATH for full support of multi-port devices.\n");
        return 0;
 }
 static inline void nvme_mpath_uninit(struct nvme_ctrl *ctrl)
index d181caf..ab6ec72 100644 (file)
@@ -184,6 +184,7 @@ static int nvme_rdma_alloc_qe(struct ib_device *ibdev, struct nvme_rdma_qe *qe,
        qe->dma = ib_dma_map_single(ibdev, qe->data, capsule_size, dir);
        if (ib_dma_mapping_error(ibdev, qe->dma)) {
                kfree(qe->data);
+               qe->data = NULL;
                return -ENOMEM;
        }
 
@@ -823,6 +824,7 @@ out_free_tagset:
 out_free_async_qe:
        nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
                sizeof(struct nvme_command), DMA_TO_DEVICE);
+       ctrl->async_event_sqe.data = NULL;
 out_free_queue:
        nvme_rdma_free_queue(&ctrl->queues[0]);
        return error;
index 3f7971d..583086d 100644 (file)
@@ -529,6 +529,7 @@ static void nvmet_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc)
 {
        struct nvmet_rdma_rsp *rsp =
                container_of(wc->wr_cqe, struct nvmet_rdma_rsp, send_cqe);
+       struct nvmet_rdma_queue *queue = cq->cq_context;
 
        nvmet_rdma_release_rsp(rsp);
 
@@ -536,7 +537,7 @@ static void nvmet_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc)
                     wc->status != IB_WC_WR_FLUSH_ERR)) {
                pr_err("SEND for CQE 0x%p failed with status %s (%d).\n",
                        wc->wr_cqe, ib_wc_status_msg(wc->status), wc->status);
-               nvmet_rdma_error_comp(rsp->queue);
+               nvmet_rdma_error_comp(queue);
        }
 }
 
index 5a4b479..38a0880 100644 (file)
@@ -579,10 +579,8 @@ int dev_pm_opp_of_add_table_indexed(struct device *dev, int index)
                 */
                count = of_count_phandle_with_args(dev->of_node,
                                                   "operating-points-v2", NULL);
-               if (count != 1)
-                       return -ENODEV;
-
-               index = 0;
+               if (count == 1)
+                       index = 0;
        }
 
        opp_table = dev_pm_opp_get_opp_table_indexed(dev, index);
index 3f4fb4d..1c69c40 100644 (file)
@@ -417,7 +417,6 @@ static struct platform_driver ti_opp_supply_driver = {
        .probe = ti_opp_supply_probe,
        .driver = {
                   .name = "ti_opp_supply",
-                  .owner = THIS_MODULE,
                   .of_match_table = of_match_ptr(ti_opp_supply_of_match),
                   },
 };
index 2cbef2d..88af6bf 100644 (file)
@@ -81,8 +81,6 @@ struct imx6_pcie {
 #define PCIE_PL_PFLR_FORCE_LINK                        (1 << 15)
 #define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
 #define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
-#define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING        (1 << 29)
-#define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP         (1 << 4)
 
 #define PCIE_PHY_CTRL (PL_OFFSET + 0x114)
 #define PCIE_PHY_CTRL_DATA_LOC 0
@@ -711,12 +709,6 @@ static int imx6_pcie_host_init(struct pcie_port *pp)
        return 0;
 }
 
-static int imx6_pcie_link_up(struct dw_pcie *pci)
-{
-       return dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1) &
-                       PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
-}
-
 static const struct dw_pcie_host_ops imx6_pcie_host_ops = {
        .host_init = imx6_pcie_host_init,
 };
@@ -749,7 +741,7 @@ static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
 }
 
 static const struct dw_pcie_ops dw_pcie_ops = {
-       .link_up = imx6_pcie_link_up,
+       /* No special ops needed, but pcie-designware still expects this struct */
 };
 
 #ifdef CONFIG_PM_SLEEP
index 3724d3e..7aa9a82 100644 (file)
@@ -88,7 +88,7 @@ static void ls_pcie_disable_outbound_atus(struct ls_pcie *pcie)
        int i;
 
        for (i = 0; i < PCIE_IATU_NUM; i++)
-               dw_pcie_disable_atu(pcie->pci, DW_PCIE_REGION_OUTBOUND, i);
+               dw_pcie_disable_atu(pcie->pci, i, DW_PCIE_REGION_OUTBOUND);
 }
 
 static int ls1021_pcie_link_up(struct dw_pcie *pci)
index 1e7b022..de8635a 100644 (file)
@@ -440,7 +440,6 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
        tbl_offset = dw_pcie_readl_dbi(pci, reg);
        bir = (tbl_offset & PCI_MSIX_TABLE_BIR);
        tbl_offset &= PCI_MSIX_TABLE_OFFSET;
-       tbl_offset >>= 3;
 
        reg = PCI_BASE_ADDRESS_0 + (4 * bir);
        bar_addr_upper = 0;
index d068f11..c9d8e3c 100644 (file)
@@ -5556,9 +5556,13 @@ enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)
        u32 lnkcap2, lnkcap;
 
        /*
-        * PCIe r4.0 sec 7.5.3.18 recommends using the Supported Link
-        * Speeds Vector in Link Capabilities 2 when supported, falling
-        * back to Max Link Speed in Link Capabilities otherwise.
+        * Link Capabilities 2 was added in PCIe r3.0, sec 7.8.18.  The
+        * implementation note there recommends using the Supported Link
+        * Speeds Vector in Link Capabilities 2 when supported.
+        *
+        * Without Link Capabilities 2, i.e., prior to PCIe r3.0, software
+        * should use the Supported Link Speeds field in Link Capabilities,
+        * where only 2.5 GT/s and 5.0 GT/s speeds were defined.
         */
        pcie_capability_read_dword(dev, PCI_EXP_LNKCAP2, &lnkcap2);
        if (lnkcap2) { /* PCIe r3.0-compliant */
@@ -5574,16 +5578,10 @@ enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)
        }
 
        pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
-       if (lnkcap) {
-               if (lnkcap & PCI_EXP_LNKCAP_SLS_16_0GB)
-                       return PCIE_SPEED_16_0GT;
-               else if (lnkcap & PCI_EXP_LNKCAP_SLS_8_0GB)
-                       return PCIE_SPEED_8_0GT;
-               else if (lnkcap & PCI_EXP_LNKCAP_SLS_5_0GB)
-                       return PCIE_SPEED_5_0GT;
-               else if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB)
-                       return PCIE_SPEED_2_5GT;
-       }
+       if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_5_0GB)
+               return PCIE_SPEED_5_0GT;
+       else if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_2_5GB)
+               return PCIE_SPEED_2_5GT;
 
        return PCI_SPEED_UNKNOWN;
 }
index dcb29cb..f78860c 100644 (file)
@@ -895,7 +895,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
        struct pcie_link_state *link;
        int blacklist = !!pcie_aspm_sanity_check(pdev);
 
-       if (!aspm_support_enabled || aspm_disabled)
+       if (!aspm_support_enabled)
                return;
 
        if (pdev->link_state)
index 9ce5311..6d4b44b 100644 (file)
@@ -231,6 +231,7 @@ static const struct qusb2_phy_cfg sdm845_phy_cfg = {
        .mask_core_ready = CORE_READY_STATUS,
        .has_pll_override = true,
        .autoresume_en    = BIT(0),
+       .update_tune1_with_efuse = true,
 };
 
 static const char * const qusb2_phy_vreg_names[] = {
@@ -402,10 +403,10 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)
 
        /*
         * Read efuse register having TUNE2/1 parameter's high nibble.
-        * If efuse register shows value as 0x0, or if we fail to find
-        * a valid efuse register settings, then use default value
-        * as 0xB for high nibble that we have already set while
-        * configuring phy.
+        * If efuse register shows value as 0x0 (indicating value is not
+        * fused), or if we fail to find a valid efuse register setting,
+        * then use default value for high nibble that we have already
+        * set while configuring the phy.
         */
        val = nvmem_cell_read(qphy->cell, NULL);
        if (IS_ERR(val) || !val[0]) {
@@ -415,12 +416,13 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)
 
        /* Fused TUNE1/2 value is the higher nibble only */
        if (cfg->update_tune1_with_efuse)
-               qusb2_setbits(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1],
-                             val[0] << 0x4);
+               qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1],
+                                val[0] << HSTX_TRIM_SHIFT,
+                                HSTX_TRIM_MASK);
        else
-               qusb2_setbits(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE2],
-                             val[0] << 0x4);
-
+               qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE2],
+                                val[0] << HSTX_TRIM_SHIFT,
+                                HSTX_TRIM_MASK);
 }
 
 static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode)
index 467e814..9c85231 100644 (file)
@@ -26,7 +26,8 @@ config PHY_UNIPHIER_USB3
 
 config PHY_UNIPHIER_PCIE
        tristate "Uniphier PHY driver for PCIe controller"
-       depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF
+       depends on ARCH_UNIPHIER || COMPILE_TEST
+       depends on OF && HAS_IOMEM
        default PCIE_UNIPHIER
        select GENERIC_PHY
        help
index 2751dba..3e1abb4 100644 (file)
@@ -213,7 +213,7 @@ static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm)
        /* get a report with all values through requesting one value */
        sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev,
                        HID_USAGE_SENSOR_TIME, hid_time_addresses[0],
-                       time_state->info[0].report_id, SENSOR_HUB_SYNC);
+                       time_state->info[0].report_id, SENSOR_HUB_SYNC, false);
        /* wait for all values (event) */
        ret = wait_for_completion_killable_timeout(
                        &time_state->comp_last_time, HZ*6);
index fd77e46..70a006b 100644 (file)
@@ -387,8 +387,10 @@ static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
                 * orb specified one of the unsupported formats, we defer
                 * checking for IDAWs in unsupported formats to here.
                 */
-               if ((!cp->orb.cmd.c64 || cp->orb.cmd.i2k) && ccw_is_idal(ccw))
+               if ((!cp->orb.cmd.c64 || cp->orb.cmd.i2k) && ccw_is_idal(ccw)) {
+                       kfree(p);
                        return -EOPNOTSUPP;
+               }
 
                if ((!ccw_is_chain(ccw)) && (!ccw_is_tic(ccw)))
                        break;
@@ -528,7 +530,7 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
 
        ret = pfn_array_alloc_pin(pat->pat_pa, cp->mdev, ccw->cda, ccw->count);
        if (ret < 0)
-               goto out_init;
+               goto out_unpin;
 
        /* Translate this direct ccw to a idal ccw. */
        idaws = kcalloc(ret, sizeof(*idaws), GFP_DMA | GFP_KERNEL);
index f47d16b..a10cec0 100644 (file)
@@ -22,7 +22,7 @@
 #include "vfio_ccw_private.h"
 
 struct workqueue_struct *vfio_ccw_work_q;
-struct kmem_cache *vfio_ccw_io_region;
+static struct kmem_cache *vfio_ccw_io_region;
 
 /*
  * Helpers
@@ -134,14 +134,14 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
        if (ret)
                goto out_free;
 
-       ret = vfio_ccw_mdev_reg(sch);
-       if (ret)
-               goto out_disable;
-
        INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
        atomic_set(&private->avail, 1);
        private->state = VFIO_CCW_STATE_STANDBY;
 
+       ret = vfio_ccw_mdev_reg(sch);
+       if (ret)
+               goto out_disable;
+
        return 0;
 
 out_disable:
index 048665e..9f5a201 100644 (file)
@@ -775,6 +775,8 @@ static int ap_device_probe(struct device *dev)
                drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;
                if (!!devres != !!drvres)
                        return -ENODEV;
+               /* (re-)init queue's state machine */
+               ap_queue_reinit_state(to_ap_queue(dev));
        }
 
        /* Add queue/card to list of active queues/cards */
@@ -807,6 +809,8 @@ static int ap_device_remove(struct device *dev)
        struct ap_device *ap_dev = to_ap_dev(dev);
        struct ap_driver *ap_drv = ap_dev->drv;
 
+       if (is_queue_dev(dev))
+               ap_queue_remove(to_ap_queue(dev));
        if (ap_drv->remove)
                ap_drv->remove(ap_dev);
 
@@ -1444,10 +1448,6 @@ static void ap_scan_bus(struct work_struct *unused)
                        aq->ap_dev.device.parent = &ac->ap_dev.device;
                        dev_set_name(&aq->ap_dev.device,
                                     "%02x.%04x", id, dom);
-                       /* Start with a device reset */
-                       spin_lock_bh(&aq->lock);
-                       ap_wait(ap_sm_event(aq, AP_EVENT_POLL));
-                       spin_unlock_bh(&aq->lock);
                        /* Register device */
                        rc = device_register(&aq->ap_dev.device);
                        if (rc) {
index 3eed1b3..bfc66e4 100644 (file)
@@ -254,6 +254,7 @@ struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type);
 void ap_queue_remove(struct ap_queue *aq);
 void ap_queue_suspend(struct ap_device *ap_dev);
 void ap_queue_resume(struct ap_device *ap_dev);
+void ap_queue_reinit_state(struct ap_queue *aq);
 
 struct ap_card *ap_card_create(int id, int queue_depth, int raw_device_type,
                               int comp_device_type, unsigned int functions);
index 66f7334..0aa4b3c 100644 (file)
@@ -718,5 +718,20 @@ void ap_queue_remove(struct ap_queue *aq)
 {
        ap_flush_queue(aq);
        del_timer_sync(&aq->timeout);
+
+       /* reset with zero, also clears irq registration */
+       spin_lock_bh(&aq->lock);
+       ap_zapq(aq->qid);
+       aq->state = AP_STATE_BORKED;
+       spin_unlock_bh(&aq->lock);
 }
 EXPORT_SYMBOL(ap_queue_remove);
+
+void ap_queue_reinit_state(struct ap_queue *aq)
+{
+       spin_lock_bh(&aq->lock);
+       aq->state = AP_STATE_RESET_START;
+       ap_wait(ap_sm_event(aq, AP_EVENT_POLL));
+       spin_unlock_bh(&aq->lock);
+}
+EXPORT_SYMBOL(ap_queue_reinit_state);
index 146f54f..c50f3e8 100644 (file)
@@ -196,7 +196,6 @@ static void zcrypt_cex2a_queue_remove(struct ap_device *ap_dev)
        struct ap_queue *aq = to_ap_queue(&ap_dev->device);
        struct zcrypt_queue *zq = aq->private;
 
-       ap_queue_remove(aq);
        if (zq)
                zcrypt_queue_unregister(zq);
 }
index 546f676..35c7c66 100644 (file)
@@ -251,7 +251,6 @@ static void zcrypt_cex2c_queue_remove(struct ap_device *ap_dev)
        struct ap_queue *aq = to_ap_queue(&ap_dev->device);
        struct zcrypt_queue *zq = aq->private;
 
-       ap_queue_remove(aq);
        if (zq)
                zcrypt_queue_unregister(zq);
 }
index f9d4c6c..582ffa7 100644 (file)
@@ -275,7 +275,6 @@ static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev)
        struct ap_queue *aq = to_ap_queue(&ap_dev->device);
        struct zcrypt_queue *zq = aq->private;
 
-       ap_queue_remove(aq);
        if (zq)
                zcrypt_queue_unregister(zq);
 }
index 97b6f19..c9c57b4 100644 (file)
@@ -56,6 +56,7 @@ struct virtio_ccw_device {
        unsigned int revision; /* Transport revision */
        wait_queue_head_t wait_q;
        spinlock_t lock;
+       struct mutex io_lock; /* Serializes I/O requests */
        struct list_head virtqueues;
        unsigned long indicators;
        unsigned long indicators2;
@@ -296,6 +297,7 @@ static int ccw_io_helper(struct virtio_ccw_device *vcdev,
        unsigned long flags;
        int flag = intparm & VIRTIO_CCW_INTPARM_MASK;
 
+       mutex_lock(&vcdev->io_lock);
        do {
                spin_lock_irqsave(get_ccwdev_lock(vcdev->cdev), flags);
                ret = ccw_device_start(vcdev->cdev, ccw, intparm, 0, 0);
@@ -308,7 +310,9 @@ static int ccw_io_helper(struct virtio_ccw_device *vcdev,
                cpu_relax();
        } while (ret == -EBUSY);
        wait_event(vcdev->wait_q, doing_io(vcdev, flag) == 0);
-       return ret ? ret : vcdev->err;
+       ret = ret ? ret : vcdev->err;
+       mutex_unlock(&vcdev->io_lock);
+       return ret;
 }
 
 static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
@@ -828,6 +832,7 @@ static void virtio_ccw_get_config(struct virtio_device *vdev,
        int ret;
        struct ccw1 *ccw;
        void *config_area;
+       unsigned long flags;
 
        ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL);
        if (!ccw)
@@ -846,11 +851,13 @@ static void virtio_ccw_get_config(struct virtio_device *vdev,
        if (ret)
                goto out_free;
 
+       spin_lock_irqsave(&vcdev->lock, flags);
        memcpy(vcdev->config, config_area, offset + len);
-       if (buf)
-               memcpy(buf, &vcdev->config[offset], len);
        if (vcdev->config_ready < offset + len)
                vcdev->config_ready = offset + len;
+       spin_unlock_irqrestore(&vcdev->lock, flags);
+       if (buf)
+               memcpy(buf, config_area + offset, len);
 
 out_free:
        kfree(config_area);
@@ -864,6 +871,7 @@ static void virtio_ccw_set_config(struct virtio_device *vdev,
        struct virtio_ccw_device *vcdev = to_vc_device(vdev);
        struct ccw1 *ccw;
        void *config_area;
+       unsigned long flags;
 
        ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL);
        if (!ccw)
@@ -876,9 +884,11 @@ static void virtio_ccw_set_config(struct virtio_device *vdev,
        /* Make sure we don't overwrite fields. */
        if (vcdev->config_ready < offset)
                virtio_ccw_get_config(vdev, 0, NULL, offset);
+       spin_lock_irqsave(&vcdev->lock, flags);
        memcpy(&vcdev->config[offset], buf, len);
        /* Write the config area to the host. */
        memcpy(config_area, vcdev->config, sizeof(vcdev->config));
+       spin_unlock_irqrestore(&vcdev->lock, flags);
        ccw->cmd_code = CCW_CMD_WRITE_CONF;
        ccw->flags = 0;
        ccw->count = offset + len;
@@ -1247,6 +1257,7 @@ static int virtio_ccw_online(struct ccw_device *cdev)
        init_waitqueue_head(&vcdev->wait_q);
        INIT_LIST_HEAD(&vcdev->virtqueues);
        spin_lock_init(&vcdev->lock);
+       mutex_init(&vcdev->io_lock);
 
        spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
        dev_set_drvdata(&cdev->dev, vcdev);
index 5c8ed73..a36e4cf 100644 (file)
@@ -220,6 +220,7 @@ static int d7s_probe(struct platform_device *op)
        dev_set_drvdata(&op->dev, p);
        d7s_device = p;
        err = 0;
+       of_node_put(opts);
 
 out:
        return err;
index 56e962a..b848192 100644 (file)
@@ -910,8 +910,10 @@ static void envctrl_init_i2c_child(struct device_node *dp,
                        for (len = 0; len < PCF8584_MAX_CHANNELS; ++len) {
                                pchild->mon_type[len] = ENVCTRL_NOMON;
                        }
+                       of_node_put(root_node);
                        return;
                }
+               of_node_put(root_node);
        }
 
        /* Get the monitor channels. */
index 93c66eb..f78d2e5 100644 (file)
@@ -2416,8 +2416,8 @@ int iscsi_eh_session_reset(struct scsi_cmnd *sc)
 failed:
                ISCSI_DBG_EH(session,
                             "failing session reset: Could not log back into "
-                            "%s, %s [age %d]\n", session->targetname,
-                            conn->persistent_address, session->age);
+                            "%s [age %d]\n", session->targetname,
+                            session->age);
                spin_unlock_bh(&session->frwd_lock);
                mutex_unlock(&session->eh_mutex);
                return FAILED;
index 20fa678..68d62d5 100644 (file)
@@ -167,7 +167,11 @@ lpfc_config_port_prep(struct lpfc_hba *phba)
                       sizeof(phba->wwpn));
        }
 
-       phba->sli3_options = 0x0;
+       /*
+        * Clear all option bits except LPFC_SLI3_BG_ENABLED,
+        * which was already set in lpfc_get_cfgparam()
+        */
+       phba->sli3_options &= (uint32_t)LPFC_SLI3_BG_ENABLED;
 
        /* Setup and issue mailbox READ REV command */
        lpfc_read_rev(phba, pmb);
index 783a154..b9e5cd7 100644 (file)
@@ -4965,7 +4965,6 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode)
                phba->sli3_options &= ~(LPFC_SLI3_NPIV_ENABLED |
                                        LPFC_SLI3_HBQ_ENABLED |
                                        LPFC_SLI3_CRP_ENABLED |
-                                       LPFC_SLI3_BG_ENABLED |
                                        LPFC_SLI3_DSS_ENABLED);
                if (rc != MBX_SUCCESS) {
                        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
index f03dc03..8f88348 100644 (file)
@@ -446,7 +446,6 @@ struct storvsc_device {
 
        bool     destroy;
        bool     drain_notify;
-       bool     open_sub_channel;
        atomic_t num_outstanding_req;
        struct Scsi_Host *host;
 
@@ -636,33 +635,38 @@ get_in_err:
 static void handle_sc_creation(struct vmbus_channel *new_sc)
 {
        struct hv_device *device = new_sc->primary_channel->device_obj;
+       struct device *dev = &device->device;
        struct storvsc_device *stor_device;
        struct vmstorage_channel_properties props;
+       int ret;
 
        stor_device = get_out_stor_device(device);
        if (!stor_device)
                return;
 
-       if (stor_device->open_sub_channel == false)
-               return;
-
        memset(&props, 0, sizeof(struct vmstorage_channel_properties));
 
-       vmbus_open(new_sc,
-                  storvsc_ringbuffer_size,
-                  storvsc_ringbuffer_size,
-                  (void *)&props,
-                  sizeof(struct vmstorage_channel_properties),
-                  storvsc_on_channel_callback, new_sc);
+       ret = vmbus_open(new_sc,
+                        storvsc_ringbuffer_size,
+                        storvsc_ringbuffer_size,
+                        (void *)&props,
+                        sizeof(struct vmstorage_channel_properties),
+                        storvsc_on_channel_callback, new_sc);
 
-       if (new_sc->state == CHANNEL_OPENED_STATE) {
-               stor_device->stor_chns[new_sc->target_cpu] = new_sc;
-               cpumask_set_cpu(new_sc->target_cpu, &stor_device->alloced_cpus);
+       /* In case vmbus_open() fails, we don't use the sub-channel. */
+       if (ret != 0) {
+               dev_err(dev, "Failed to open sub-channel: err=%d\n", ret);
+               return;
        }
+
+       /* Add the sub-channel to the array of available channels. */
+       stor_device->stor_chns[new_sc->target_cpu] = new_sc;
+       cpumask_set_cpu(new_sc->target_cpu, &stor_device->alloced_cpus);
 }
 
 static void  handle_multichannel_storage(struct hv_device *device, int max_chns)
 {
+       struct device *dev = &device->device;
        struct storvsc_device *stor_device;
        int num_cpus = num_online_cpus();
        int num_sc;
@@ -679,21 +683,11 @@ static void  handle_multichannel_storage(struct hv_device *device, int max_chns)
        request = &stor_device->init_request;
        vstor_packet = &request->vstor_packet;
 
-       stor_device->open_sub_channel = true;
        /*
         * Establish a handler for dealing with subchannels.
         */
        vmbus_set_sc_create_callback(device->channel, handle_sc_creation);
 
-       /*
-        * Check to see if sub-channels have already been created. This
-        * can happen when this driver is re-loaded after unloading.
-        */
-
-       if (vmbus_are_subchannels_present(device->channel))
-               return;
-
-       stor_device->open_sub_channel = false;
        /*
         * Request the host to create sub-channels.
         */
@@ -710,23 +704,29 @@ static void  handle_multichannel_storage(struct hv_device *device, int max_chns)
                               VM_PKT_DATA_INBAND,
                               VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 
-       if (ret != 0)
+       if (ret != 0) {
+               dev_err(dev, "Failed to create sub-channel: err=%d\n", ret);
                return;
+       }
 
        t = wait_for_completion_timeout(&request->wait_event, 10*HZ);
-       if (t == 0)
+       if (t == 0) {
+               dev_err(dev, "Failed to create sub-channel: timed out\n");
                return;
+       }
 
        if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
-           vstor_packet->status != 0)
+           vstor_packet->status != 0) {
+               dev_err(dev, "Failed to create sub-channel: op=%d, sts=%d\n",
+                       vstor_packet->operation, vstor_packet->status);
                return;
+       }
 
        /*
-        * Now that we created the sub-channels, invoke the check; this
-        * may trigger the callback.
+        * We need to do nothing here, because vmbus_process_offer()
+        * invokes channel->sc_creation_callback, which will open and use
+        * the sub-channel(s).
         */
-       stor_device->open_sub_channel = true;
-       vmbus_are_subchannels_present(device->channel);
 }
 
 static void cache_wwn(struct storvsc_device *stor_device,
@@ -1794,7 +1794,6 @@ static int storvsc_probe(struct hv_device *device,
        }
 
        stor_device->destroy = false;
-       stor_device->open_sub_channel = false;
        init_waitqueue_head(&stor_device->waiting_to_drain);
        stor_device->device = device;
        stor_device->host = host;
index 6e49102..0d6b2a8 100644 (file)
@@ -1202,8 +1202,6 @@ static void pvscsi_shutdown_intr(struct pvscsi_adapter *adapter)
 
 static void pvscsi_release_resources(struct pvscsi_adapter *adapter)
 {
-       pvscsi_shutdown_intr(adapter);
-
        if (adapter->workqueue)
                destroy_workqueue(adapter->workqueue);
 
@@ -1534,6 +1532,7 @@ static int pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 out_reset_adapter:
        ll_adapter_reset(adapter);
 out_release_resources:
+       pvscsi_shutdown_intr(adapter);
        pvscsi_release_resources(adapter);
        scsi_host_put(host);
 out_disable_device:
@@ -1542,6 +1541,7 @@ out_disable_device:
        return error;
 
 out_release_resources_and_disable:
+       pvscsi_shutdown_intr(adapter);
        pvscsi_release_resources(adapter);
        goto out_disable_device;
 }
index e90b177..09a9400 100644 (file)
@@ -1005,35 +1005,38 @@ enum i8254_mode {
  * and INSN_DEVICE_CONFIG_GET_ROUTES.
  */
 #define NI_NAMES_BASE  0x8000u
+
+#define _TERM_N(base, n, x)    ((base) + ((x) & ((n) - 1)))
+
 /*
  * not necessarily all allowed 64 PFIs are valid--certainly not for all devices
  */
-#define NI_PFI(x)      (NI_NAMES_BASE        + ((x) & 0x3f))
+#define NI_PFI(x)              _TERM_N(NI_NAMES_BASE, 64, x)
 /* 8 trigger lines by standard, Some devices cannot talk to all eight. */
-#define TRIGGER_LINE(x)        (NI_PFI(-1)       + 1 + ((x) & 0x7))
+#define TRIGGER_LINE(x)                _TERM_N(NI_PFI(-1) + 1, 8, x)
 /* 4 RTSI shared MUXes to route signals to/from TRIGGER_LINES on NI hardware */
-#define NI_RTSI_BRD(x) (TRIGGER_LINE(-1) + 1 + ((x) & 0x3))
+#define NI_RTSI_BRD(x)         _TERM_N(TRIGGER_LINE(-1) + 1, 4, x)
 
 /* *** Counter/timer names : 8 counters max *** */
-#define NI_COUNTER_NAMES_BASE  (NI_RTSI_BRD(-1)  + 1)
-#define NI_MAX_COUNTERS               7
-#define NI_CtrSource(x)               (NI_COUNTER_NAMES_BASE + ((x) & NI_MAX_COUNTERS))
+#define NI_MAX_COUNTERS                8
+#define NI_COUNTER_NAMES_BASE  (NI_RTSI_BRD(-1)  + 1)
+#define NI_CtrSource(x)              _TERM_N(NI_COUNTER_NAMES_BASE, NI_MAX_COUNTERS, x)
 /* Gate, Aux, A,B,Z are all treated, at times as gates */
-#define NI_GATES_NAMES_BASE    (NI_CtrSource(-1) + 1)
-#define NI_CtrGate(x)         (NI_GATES_NAMES_BASE   + ((x) & NI_MAX_COUNTERS))
-#define NI_CtrAux(x)          (NI_CtrGate(-1)   + 1  + ((x) & NI_MAX_COUNTERS))
-#define NI_CtrA(x)            (NI_CtrAux(-1)    + 1  + ((x) & NI_MAX_COUNTERS))
-#define NI_CtrB(x)            (NI_CtrA(-1)      + 1  + ((x) & NI_MAX_COUNTERS))
-#define NI_CtrZ(x)            (NI_CtrB(-1)      + 1  + ((x) & NI_MAX_COUNTERS))
-#define NI_GATES_NAMES_MAX     NI_CtrZ(-1)
-#define NI_CtrArmStartTrigger(x) (NI_CtrZ(-1)    + 1  + ((x) & NI_MAX_COUNTERS))
+#define NI_GATES_NAMES_BASE    (NI_CtrSource(-1) + 1)
+#define NI_CtrGate(x)          _TERM_N(NI_GATES_NAMES_BASE, NI_MAX_COUNTERS, x)
+#define NI_CtrAux(x)           _TERM_N(NI_CtrGate(-1)  + 1, NI_MAX_COUNTERS, x)
+#define NI_CtrA(x)             _TERM_N(NI_CtrAux(-1)   + 1, NI_MAX_COUNTERS, x)
+#define NI_CtrB(x)             _TERM_N(NI_CtrA(-1)     + 1, NI_MAX_COUNTERS, x)
+#define NI_CtrZ(x)             _TERM_N(NI_CtrB(-1)     + 1, NI_MAX_COUNTERS, x)
+#define NI_GATES_NAMES_MAX     NI_CtrZ(-1)
+#define NI_CtrArmStartTrigger(x) _TERM_N(NI_CtrZ(-1)    + 1, NI_MAX_COUNTERS, x)
 #define NI_CtrInternalOutput(x) \
-                    (NI_CtrArmStartTrigger(-1)  + 1  + ((x) & NI_MAX_COUNTERS))
+                     _TERM_N(NI_CtrArmStartTrigger(-1) + 1, NI_MAX_COUNTERS, x)
 /** external pin(s) labeled conveniently as Ctr<i>Out. */
-#define NI_CtrOut(x)  (NI_CtrInternalOutput(-1)  + 1  + ((x) & NI_MAX_COUNTERS))
+#define NI_CtrOut(x)   _TERM_N(NI_CtrInternalOutput(-1) + 1, NI_MAX_COUNTERS, x)
 /** For Buffered sampling of ctr -- x series capability. */
-#define NI_CtrSampleClock(x)   (NI_CtrOut(-1)   + 1  + ((x) & NI_MAX_COUNTERS))
-#define NI_COUNTER_NAMES_MAX   NI_CtrSampleClock(-1)
+#define NI_CtrSampleClock(x)   _TERM_N(NI_CtrOut(-1)   + 1, NI_MAX_COUNTERS, x)
+#define NI_COUNTER_NAMES_MAX   NI_CtrSampleClock(-1)
 
 enum ni_common_signal_names {
        /* PXI_Star: this is a non-NI-specific signal */
index 2d1e032..5edf59a 100644 (file)
@@ -2843,7 +2843,8 @@ static int ni_ao_insn_config(struct comedi_device *dev,
                return ni_ao_arm(dev, s);
        case INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS:
                /* we don't care about actual channels */
-               data[1] = board->ao_speed;
+               /* data[3] : chanlist_len */
+               data[1] = board->ao_speed * data[3];
                data[2] = 0;
                return 0;
        default:
index ec277ec..a951b3f 100644 (file)
@@ -5,3 +5,8 @@ Before this stateless decoder driver can leave the staging area:
 * Userspace support for the Request API needs to be reviewed;
 * Another stateless decoder driver should be submitted;
 * At least one stateless encoder driver should be submitted.
+* When queueing a request containing references to I frames, the
+  refcount of the memory for those I frames needs to be incremented
+  and decremented when the request is completed. This will likely
+  require some help from vb2. The driver should fail the request
+  if the memory/buffer is gone.
index dd121f6..c912c70 100644 (file)
@@ -108,17 +108,6 @@ static int cedrus_request_validate(struct media_request *req)
        unsigned int count;
        unsigned int i;
 
-       count = vb2_request_buffer_cnt(req);
-       if (!count) {
-               v4l2_info(&ctx->dev->v4l2_dev,
-                         "No buffer was provided with the request\n");
-               return -ENOENT;
-       } else if (count > 1) {
-               v4l2_info(&ctx->dev->v4l2_dev,
-                         "More than one buffer was provided with the request\n");
-               return -EINVAL;
-       }
-
        list_for_each_entry(obj, &req->objects, list) {
                struct vb2_buffer *vb;
 
@@ -133,6 +122,17 @@ static int cedrus_request_validate(struct media_request *req)
        if (!ctx)
                return -ENOENT;
 
+       count = vb2_request_buffer_cnt(req);
+       if (!count) {
+               v4l2_info(&ctx->dev->v4l2_dev,
+                         "No buffer was provided with the request\n");
+               return -ENOENT;
+       } else if (count > 1) {
+               v4l2_info(&ctx->dev->v4l2_dev,
+                         "More than one buffer was provided with the request\n");
+               return -EINVAL;
+       }
+
        parent_hdl = &ctx->hdl;
 
        hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl);
index 6a18cf7..18936cd 100644 (file)
@@ -351,7 +351,7 @@ static ssize_t set_datatype_show(struct device *dev,
 
        for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
                if (c->cfg.data_type & ch_data_type[i].most_ch_data_type)
-                       return snprintf(buf, PAGE_SIZE, ch_data_type[i].name);
+                       return snprintf(buf, PAGE_SIZE, "%s", ch_data_type[i].name);
        }
        return snprintf(buf, PAGE_SIZE, "unconfigured\n");
 }
index df6ebf4..5831f81 100644 (file)
@@ -335,6 +335,8 @@ static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma,
        /* tx desc */
        src = sg->src_addr;
        for (i = 0; i < chan->desc->num_sgs; i++) {
+               tx_desc = &chan->tx_ring[chan->tx_idx];
+
                if (len > HSDMA_MAX_PLEN)
                        tlen = HSDMA_MAX_PLEN;
                else
@@ -344,7 +346,6 @@ static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma,
                        tx_desc->addr1 = src;
                        tx_desc->flags |= HSDMA_DESC_PLEN1(tlen);
                } else {
-                       tx_desc = &chan->tx_ring[chan->tx_idx];
                        tx_desc->addr0 = src;
                        tx_desc->flags = HSDMA_DESC_PLEN0(tlen);
 
index b8566ed..aa98fbb 100644 (file)
@@ -82,7 +82,7 @@ static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev,
        struct property *prop;
        const char *function_name, *group_name;
        int ret;
-       int ngroups;
+       int ngroups = 0;
        unsigned int reserved_maps = 0;
 
        for_each_node_with_property(np_config, "group")
index 9d156ef..4d473f0 100644 (file)
@@ -146,7 +146,7 @@ void r8712_report_sec_ie(struct _adapter *adapter, u8 authmode, u8 *sec_ie)
                p = buff;
                p += sprintf(p, "ASSOCINFO(ReqIEs=");
                len = sec_ie[1] + 2;
-               len =  (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX - 1;
+               len =  (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX;
                for (i = 0; i < len; i++)
                        p += sprintf(p, "%02x", sec_ie[i]);
                p += sprintf(p, ")");
index a737400..986a1d5 100644 (file)
@@ -1346,7 +1346,7 @@ sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
                     u8 *out_ie, uint in_len)
 {
        u8 authmode = 0, match;
-       u8 sec_ie[255], uncst_oui[4], bkup_ie[255];
+       u8 sec_ie[IW_CUSTOM_MAX], uncst_oui[4], bkup_ie[255];
        u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
        uint ielength, cnt, remove_cnt;
        int iEntry;
index 69c7abc..8445d51 100644 (file)
@@ -1565,7 +1565,7 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
        if (pstat->aid > 0) {
                DBG_871X("  old AID %d\n", pstat->aid);
        } else {
-               for (pstat->aid = 1; pstat->aid < NUM_STA; pstat->aid++)
+               for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
                        if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
                                break;
 
index 8507794..85aba8a 100644 (file)
@@ -109,12 +109,12 @@ static void update_recvframe_phyinfo(union recv_frame *precvframe,
        rx_bssid = get_hdr_bssid(wlanhdr);
        pkt_info.bssid_match = ((!IsFrameTypeCtrl(wlanhdr)) &&
                                !pattrib->icv_err && !pattrib->crc_err &&
-                               !ether_addr_equal(rx_bssid, my_bssid));
+                               ether_addr_equal(rx_bssid, my_bssid));
 
        rx_ra = get_ra(wlanhdr);
        my_hwaddr = myid(&padapter->eeprompriv);
        pkt_info.to_self = pkt_info.bssid_match &&
-               !ether_addr_equal(rx_ra, my_hwaddr);
+               ether_addr_equal(rx_ra, my_hwaddr);
 
 
        pkt_info.is_beacon = pkt_info.bssid_match &&
index af22347..db553f2 100644 (file)
@@ -1277,7 +1277,7 @@ static int cfg80211_rtw_get_station(struct wiphy *wiphy,
 
                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
                sinfo->tx_packets = psta->sta_stats.tx_pkts;
-
+               sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
        }
 
        /* for Ad-Hoc/AP mode */
index 28bfdbd..b8631ba 100644 (file)
@@ -2289,7 +2289,7 @@ static int rtw_wx_read32(struct net_device *dev,
 exit:
        kfree(ptmp);
 
-       return 0;
+       return ret;
 }
 
 static int rtw_wx_write32(struct net_device *dev,
index ea78937..45de21c 100644 (file)
@@ -1795,6 +1795,7 @@ vchiq_compat_ioctl_await_completion(struct file *file,
        struct vchiq_await_completion32 args32;
        struct vchiq_completion_data32 completion32;
        unsigned int *msgbufcount32;
+       unsigned int msgbufcount_native;
        compat_uptr_t msgbuf32;
        void *msgbuf;
        void **msgbufptr;
@@ -1906,7 +1907,11 @@ vchiq_compat_ioctl_await_completion(struct file *file,
                         sizeof(completion32)))
                return -EFAULT;
 
-       args32.msgbufcount--;
+       if (get_user(msgbufcount_native, &args->msgbufcount))
+               return -EFAULT;
+
+       if (!msgbufcount_native)
+               args32.msgbufcount--;
 
        msgbufcount32 =
                &((struct vchiq_await_completion32 __user *)arg)->msgbufcount;
index 92f67d4..d7105d0 100644 (file)
@@ -357,7 +357,7 @@ static int armada_get_temp_legacy(struct thermal_zone_device *thermal,
        int ret;
 
        /* Valid check */
-       if (armada_is_valid(priv)) {
+       if (!armada_is_valid(priv)) {
                dev_err(priv->dev,
                        "Temperature sensor reading not valid\n");
                return -EIO;
@@ -395,7 +395,7 @@ unlock_mutex:
        return ret;
 }
 
-static struct thermal_zone_of_device_ops of_ops = {
+static const struct thermal_zone_of_device_ops of_ops = {
        .get_temp = armada_get_temp,
 };
 
@@ -526,23 +526,21 @@ static int armada_thermal_probe_legacy(struct platform_device *pdev,
 
        /* First memory region points towards the status register */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -EIO;
-
-       /*
-        * Edit the resource start address and length to map over all the
-        * registers, instead of pointing at them one by one.
-        */
-       res->start -= data->syscon_status_off;
-       res->end = res->start + max(data->syscon_status_off,
-                                   max(data->syscon_control0_off,
-                                       data->syscon_control1_off)) +
-                  sizeof(unsigned int) - 1;
-
        base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(base))
                return PTR_ERR(base);
 
+       /*
+        * Fix up from the old individual DT register specification to
+        * cover all the registers.  We do this by adjusting the ioremap()
+        * result, which should be fine as ioremap() deals with pages.
+        * However, validate that we do not cross a page boundary while
+        * making this adjustment.
+        */
+       if (((unsigned long)base & ~PAGE_MASK) < data->syscon_status_off)
+               return -EINVAL;
+       base -= data->syscon_status_off;
+
        priv->syscon = devm_regmap_init_mmio(&pdev->dev, base,
                                             &armada_thermal_regmap_config);
        if (IS_ERR(priv->syscon))
index 23ad4f9..b9d90f0 100644 (file)
@@ -1,17 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Driver for Broadcom BCM2835 SoC temperature sensor
  *
  * Copyright (C) 2016 Martin Sperl
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <linux/clk.h>
index 1919f91..e8b1570 100644 (file)
@@ -299,7 +299,7 @@ static int brcmstb_set_trips(void *data, int low, int high)
        return 0;
 }
 
-static struct thermal_zone_of_device_ops of_ops = {
+static const struct thermal_zone_of_device_ops of_ops = {
        .get_temp       = brcmstb_get_temp,
        .set_trips      = brcmstb_set_trips,
 };
index 52ff854..cd96994 100644 (file)
@@ -863,6 +863,30 @@ static ssize_t key_store(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR(key, 0600, key_show, key_store);
 
+static void nvm_authenticate_start(struct tb_switch *sw)
+{
+       struct pci_dev *root_port;
+
+       /*
+        * During host router NVM upgrade we should not allow root port to
+        * go into D3cold because some root ports cannot trigger PME
+        * itself. To be on the safe side keep the root port in D0 during
+        * the whole upgrade process.
+        */
+       root_port = pci_find_pcie_root_port(sw->tb->nhi->pdev);
+       if (root_port)
+               pm_runtime_get_noresume(&root_port->dev);
+}
+
+static void nvm_authenticate_complete(struct tb_switch *sw)
+{
+       struct pci_dev *root_port;
+
+       root_port = pci_find_pcie_root_port(sw->tb->nhi->pdev);
+       if (root_port)
+               pm_runtime_put(&root_port->dev);
+}
+
 static ssize_t nvm_authenticate_show(struct device *dev,
        struct device_attribute *attr, char *buf)
 {
@@ -912,10 +936,18 @@ static ssize_t nvm_authenticate_store(struct device *dev,
 
                sw->nvm->authenticating = true;
 
-               if (!tb_route(sw))
+               if (!tb_route(sw)) {
+                       /*
+                        * Keep root port from suspending as long as the
+                        * NVM upgrade process is running.
+                        */
+                       nvm_authenticate_start(sw);
                        ret = nvm_authenticate_host(sw);
-               else
+                       if (ret)
+                               nvm_authenticate_complete(sw);
+               } else {
                        ret = nvm_authenticate_device(sw);
+               }
                pm_runtime_mark_last_busy(&sw->dev);
                pm_runtime_put_autosuspend(&sw->dev);
        }
@@ -1334,6 +1366,10 @@ static int tb_switch_add_dma_port(struct tb_switch *sw)
        if (ret <= 0)
                return ret;
 
+       /* Now we can allow root port to suspend again */
+       if (!tb_route(sw))
+               nvm_authenticate_complete(sw);
+
        if (status) {
                tb_sw_info(sw, "switch flash authentication failed\n");
                tb_switch_set_uuid(sw);
index dd5e1ce..c3f933d 100644 (file)
@@ -213,17 +213,17 @@ static int mtk8250_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, data);
 
-       pm_runtime_enable(&pdev->dev);
-       if (!pm_runtime_enabled(&pdev->dev)) {
-               err = mtk8250_runtime_resume(&pdev->dev);
-               if (err)
-                       return err;
-       }
+       err = mtk8250_runtime_resume(&pdev->dev);
+       if (err)
+               return err;
 
        data->line = serial8250_register_8250_port(&uart);
        if (data->line < 0)
                return data->line;
 
+       pm_runtime_set_active(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+
        return 0;
 }
 
@@ -234,13 +234,11 @@ static int mtk8250_remove(struct platform_device *pdev)
        pm_runtime_get_sync(&pdev->dev);
 
        serial8250_unregister_port(data->line);
+       mtk8250_runtime_suspend(&pdev->dev);
 
        pm_runtime_disable(&pdev->dev);
        pm_runtime_put_noidle(&pdev->dev);
 
-       if (!pm_runtime_status_suspended(&pdev->dev))
-               mtk8250_runtime_suspend(&pdev->dev);
-
        return 0;
 }
 
index baeeeae..6fb312e 100644 (file)
@@ -233,7 +233,7 @@ static void kgdboc_put_char(u8 chr)
 static int param_set_kgdboc_var(const char *kmessage,
                                const struct kernel_param *kp)
 {
-       int len = strlen(kmessage);
+       size_t len = strlen(kmessage);
 
        if (len >= MAX_CONFIG_LEN) {
                pr_err("config string too long\n");
@@ -254,7 +254,7 @@ static int param_set_kgdboc_var(const char *kmessage,
 
        strcpy(config, kmessage);
        /* Chop out \n char as a result of echo */
-       if (config[len - 1] == '\n')
+       if (len && config[len - 1] == '\n')
                config[len - 1] = '\0';
 
        if (configured == 1)
index 70a4ea4..9903765 100644 (file)
@@ -112,6 +112,7 @@ void sunserial_console_termios(struct console *con, struct device_node *uart_dp)
                mode = of_get_property(dp, mode_prop, NULL);
                if (!mode)
                        mode = "9600,8,n,1,-";
+               of_node_put(dp);
        }
 
        cflag = CREAD | HUPCL | CLOCAL;
index ee80dfb..687250e 100644 (file)
@@ -1373,7 +1373,13 @@ err_release_lock:
        return ERR_PTR(retval);
 }
 
-static void tty_free_termios(struct tty_struct *tty)
+/**
+ * tty_save_termios() - save tty termios data in driver table
+ * @tty: tty whose termios data to save
+ *
+ * Locking: Caller guarantees serialisation with tty_init_termios().
+ */
+void tty_save_termios(struct tty_struct *tty)
 {
        struct ktermios *tp;
        int idx = tty->index;
@@ -1392,6 +1398,7 @@ static void tty_free_termios(struct tty_struct *tty)
        }
        *tp = tty->termios;
 }
+EXPORT_SYMBOL_GPL(tty_save_termios);
 
 /**
  *     tty_flush_works         -       flush all works of a tty/pty pair
@@ -1491,7 +1498,7 @@ static void release_tty(struct tty_struct *tty, int idx)
        WARN_ON(!mutex_is_locked(&tty_mutex));
        if (tty->ops->shutdown)
                tty->ops->shutdown(tty);
-       tty_free_termios(tty);
+       tty_save_termios(tty);
        tty_driver_remove_tty(tty->driver, tty);
        tty->port->itty = NULL;
        if (tty->link)
index cb60750..044c3cb 100644 (file)
@@ -633,7 +633,8 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty,
        if (tty_port_close_start(port, tty, filp) == 0)
                return;
        tty_port_shutdown(port, tty);
-       set_bit(TTY_IO_ERROR, &tty->flags);
+       if (!port->console)
+               set_bit(TTY_IO_ERROR, &tty->flags);
        tty_port_close_end(port, tty);
        tty_port_tty_set(port, NULL);
 }
index 0f9381b..f76b2e0 100644 (file)
@@ -2251,7 +2251,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
                /* descriptor may appear anywhere in config */
                err = __usb_get_extra_descriptor(udev->rawdescriptors[0],
                                le16_to_cpu(udev->config[0].desc.wTotalLength),
-                               USB_DT_OTG, (void **) &desc);
+                               USB_DT_OTG, (void **) &desc, sizeof(*desc));
                if (err || !(desc->bmAttributes & USB_OTG_HNP))
                        return 0;
 
@@ -5163,7 +5163,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 /* Handle notifying userspace about hub over-current events */
 static void port_over_current_notify(struct usb_port *port_dev)
 {
-       static char *envp[] = { NULL, NULL, NULL };
+       char *envp[3];
        struct device *hub_dev;
        char *port_dev_path;
 
@@ -5187,6 +5187,7 @@ static void port_over_current_notify(struct usb_port *port_dev)
        if (!envp[1])
                goto exit;
 
+       envp[2] = NULL;
        kobject_uevent_env(&hub_dev->kobj, KOBJ_CHANGE, envp);
 
        kfree(envp[1]);
index f9ff03e..514c521 100644 (file)
@@ -209,6 +209,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Microsoft LifeCam-VX700 v2.0 */
        { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Cherry Stream G230 2.0 (G85-231) and 3.0 (G85-232) */
+       { USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Logitech HD Pro Webcams C920, C920-C, C925e and C930e */
        { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
        { USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT },
@@ -330,6 +333,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Midiman M-Audio Keystation 88es */
        { USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* SanDisk Ultra Fit and Ultra Flair */
+       { USB_DEVICE(0x0781, 0x5583), .driver_info = USB_QUIRK_NO_LPM },
+       { USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM },
+
        /* M-Systems Flash Disk Pioneers */
        { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
 
index 79d8bd7..4ebfbd7 100644 (file)
@@ -832,14 +832,14 @@ EXPORT_SYMBOL_GPL(usb_get_current_frame_number);
  */
 
 int __usb_get_extra_descriptor(char *buffer, unsigned size,
-                              unsigned char type, void **ptr)
+                              unsigned char type, void **ptr, size_t minsize)
 {
        struct usb_descriptor_header *header;
 
        while (size >= sizeof(struct usb_descriptor_header)) {
                header = (struct usb_descriptor_header *)buffer;
 
-               if (header->bLength < 2) {
+               if (header->bLength < 2 || header->bLength > size) {
                        printk(KERN_ERR
                                "%s: bogus descriptor, type %d length %d\n",
                                usbcore_name,
@@ -848,7 +848,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
                        return -1;
                }
 
-               if (header->bDescriptorType == type) {
+               if (header->bDescriptorType == type && header->bLength >= minsize) {
                        *ptr = header;
                        return 0;
                }
index 9faad89..9f92ee0 100644 (file)
@@ -1470,9 +1470,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
                unsigned transfer_in_flight;
                unsigned started;
 
-               if (dep->flags & DWC3_EP_STALL)
-                       return 0;
-
                if (dep->number > 1)
                        trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue);
                else
@@ -1494,8 +1491,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
                else
                        dep->flags |= DWC3_EP_STALL;
        } else {
-               if (!(dep->flags & DWC3_EP_STALL))
-                       return 0;
 
                ret = dwc3_send_clear_stall_ep_cmd(dep);
                if (ret)
index 1000d86..0f026d4 100644 (file)
@@ -401,12 +401,12 @@ done:
 static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)
 {
        struct usb_request      *req;
-       struct usb_request      *tmp;
        unsigned long           flags;
 
        /* fill unused rxq slots with some skb */
        spin_lock_irqsave(&dev->req_lock, flags);
-       list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) {
+       while (!list_empty(&dev->rx_reqs)) {
+               req = list_first_entry(&dev->rx_reqs, struct usb_request, list);
                list_del_init(&req->list);
                spin_unlock_irqrestore(&dev->req_lock, flags);
 
@@ -1125,7 +1125,6 @@ void gether_disconnect(struct gether *link)
 {
        struct eth_dev          *dev = link->ioport;
        struct usb_request      *req;
-       struct usb_request      *tmp;
 
        WARN_ON(!dev);
        if (!dev)
@@ -1142,7 +1141,8 @@ void gether_disconnect(struct gether *link)
         */
        usb_ep_disable(link->in_ep);
        spin_lock(&dev->req_lock);
-       list_for_each_entry_safe(req, tmp, &dev->tx_reqs, list) {
+       while (!list_empty(&dev->tx_reqs)) {
+               req = list_first_entry(&dev->tx_reqs, struct usb_request, list);
                list_del(&req->list);
 
                spin_unlock(&dev->req_lock);
@@ -1154,7 +1154,8 @@ void gether_disconnect(struct gether *link)
 
        usb_ep_disable(link->out_ep);
        spin_lock(&dev->req_lock);
-       list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) {
+       while (!list_empty(&dev->rx_reqs)) {
+               req = list_first_entry(&dev->rx_reqs, struct usb_request, list);
                list_del(&req->list);
 
                spin_unlock(&dev->req_lock);
index 3a16431..fcf13ef 100644 (file)
@@ -2033,6 +2033,7 @@ static inline int machine_without_vbus_sense(void)
 {
        return machine_is_omap_innovator()
                || machine_is_omap_osk()
+               || machine_is_omap_palmte()
                || machine_is_sx1()
                /* No known omap7xx boards with vbus sense */
                || cpu_is_omap7xx();
@@ -2041,7 +2042,7 @@ static inline int machine_without_vbus_sense(void)
 static int omap_udc_start(struct usb_gadget *g,
                struct usb_gadget_driver *driver)
 {
-       int             status = -ENODEV;
+       int             status;
        struct omap_ep  *ep;
        unsigned long   flags;
 
@@ -2079,6 +2080,7 @@ static int omap_udc_start(struct usb_gadget *g,
                        goto done;
                }
        } else {
+               status = 0;
                if (can_pullup(udc))
                        pullup_enable(udc);
                else
@@ -2593,9 +2595,22 @@ omap_ep_setup(char *name, u8 addr, u8 type,
 
 static void omap_udc_release(struct device *dev)
 {
-       complete(udc->done);
+       pullup_disable(udc);
+       if (!IS_ERR_OR_NULL(udc->transceiver)) {
+               usb_put_phy(udc->transceiver);
+               udc->transceiver = NULL;
+       }
+       omap_writew(0, UDC_SYSCON1);
+       remove_proc_file();
+       if (udc->dc_clk) {
+               if (udc->clk_requested)
+                       omap_udc_enable_clock(0);
+               clk_put(udc->hhc_clk);
+               clk_put(udc->dc_clk);
+       }
+       if (udc->done)
+               complete(udc->done);
        kfree(udc);
-       udc = NULL;
 }
 
 static int
@@ -2627,6 +2642,7 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
        udc->gadget.speed = USB_SPEED_UNKNOWN;
        udc->gadget.max_speed = USB_SPEED_FULL;
        udc->gadget.name = driver_name;
+       udc->gadget.quirk_ep_out_aligned_size = 1;
        udc->transceiver = xceiv;
 
        /* ep0 is special; put it right after the SETUP buffer */
@@ -2867,8 +2883,8 @@ bad_on_1710:
                udc->clr_halt = UDC_RESET_EP;
 
        /* USB general purpose IRQ:  ep0, state changes, dma, etc */
-       status = request_irq(pdev->resource[1].start, omap_udc_irq,
-                       0, driver_name, udc);
+       status = devm_request_irq(&pdev->dev, pdev->resource[1].start,
+                                 omap_udc_irq, 0, driver_name, udc);
        if (status != 0) {
                ERR("can't get irq %d, err %d\n",
                        (int) pdev->resource[1].start, status);
@@ -2876,20 +2892,20 @@ bad_on_1710:
        }
 
        /* USB "non-iso" IRQ (PIO for all but ep0) */
-       status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
-                       0, "omap_udc pio", udc);
+       status = devm_request_irq(&pdev->dev, pdev->resource[2].start,
+                                 omap_udc_pio_irq, 0, "omap_udc pio", udc);
        if (status != 0) {
                ERR("can't get irq %d, err %d\n",
                        (int) pdev->resource[2].start, status);
-               goto cleanup2;
+               goto cleanup1;
        }
 #ifdef USE_ISO
-       status = request_irq(pdev->resource[3].start, omap_udc_iso_irq,
-                       0, "omap_udc iso", udc);
+       status = devm_request_irq(&pdev->dev, pdev->resource[3].start,
+                                 omap_udc_iso_irq, 0, "omap_udc iso", udc);
        if (status != 0) {
                ERR("can't get irq %d, err %d\n",
                        (int) pdev->resource[3].start, status);
-               goto cleanup3;
+               goto cleanup1;
        }
 #endif
        if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
@@ -2900,23 +2916,8 @@ bad_on_1710:
        }
 
        create_proc_file();
-       status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
-                       omap_udc_release);
-       if (status)
-               goto cleanup4;
-
-       return 0;
-
-cleanup4:
-       remove_proc_file();
-
-#ifdef USE_ISO
-cleanup3:
-       free_irq(pdev->resource[2].start, udc);
-#endif
-
-cleanup2:
-       free_irq(pdev->resource[1].start, udc);
+       return usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
+                                         omap_udc_release);
 
 cleanup1:
        kfree(udc);
@@ -2943,42 +2944,15 @@ static int omap_udc_remove(struct platform_device *pdev)
 {
        DECLARE_COMPLETION_ONSTACK(done);
 
-       if (!udc)
-               return -ENODEV;
-
-       usb_del_gadget_udc(&udc->gadget);
-       if (udc->driver)
-               return -EBUSY;
-
        udc->done = &done;
 
-       pullup_disable(udc);
-       if (!IS_ERR_OR_NULL(udc->transceiver)) {
-               usb_put_phy(udc->transceiver);
-               udc->transceiver = NULL;
-       }
-       omap_writew(0, UDC_SYSCON1);
-
-       remove_proc_file();
-
-#ifdef USE_ISO
-       free_irq(pdev->resource[3].start, udc);
-#endif
-       free_irq(pdev->resource[2].start, udc);
-       free_irq(pdev->resource[1].start, udc);
+       usb_del_gadget_udc(&udc->gadget);
 
-       if (udc->dc_clk) {
-               if (udc->clk_requested)
-                       omap_udc_enable_clock(0);
-               clk_put(udc->hhc_clk);
-               clk_put(udc->dc_clk);
-       }
+       wait_for_completion(&done);
 
        release_mem_region(pdev->resource[0].start,
                        pdev->resource[0].end - pdev->resource[0].start + 1);
 
-       wait_for_completion(&done);
-
        return 0;
 }
 
index 684d6f0..09a8ebd 100644 (file)
@@ -640,7 +640,7 @@ static int hwahc_security_create(struct hwahc *hwahc)
        top = itr + itr_size;
        result = __usb_get_extra_descriptor(usb_dev->rawdescriptors[index],
                        le16_to_cpu(usb_dev->actconfig->desc.wTotalLength),
-                       USB_DT_SECURITY, (void **) &secd);
+                       USB_DT_SECURITY, (void **) &secd, sizeof(*secd));
        if (result == -1) {
                dev_warn(dev, "BUG? WUSB host has no security descriptors\n");
                return 0;
index a951526..a9ec705 100644 (file)
@@ -139,6 +139,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 pdev->device == 0x43bb))
                xhci->quirks |= XHCI_SUSPEND_DELAY;
 
+       if (pdev->vendor == PCI_VENDOR_ID_AMD &&
+           (pdev->device == 0x15e0 || pdev->device == 0x15e1))
+               xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND;
+
        if (pdev->vendor == PCI_VENDOR_ID_AMD)
                xhci->quirks |= XHCI_TRUST_TX_LENGTH;
 
index c928dbb..dae3be1 100644 (file)
@@ -968,6 +968,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
        unsigned int            delay = XHCI_MAX_HALT_USEC;
        struct usb_hcd          *hcd = xhci_to_hcd(xhci);
        u32                     command;
+       u32                     res;
 
        if (!hcd->state)
                return 0;
@@ -1021,11 +1022,28 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
        command = readl(&xhci->op_regs->command);
        command |= CMD_CSS;
        writel(command, &xhci->op_regs->command);
+       xhci->broken_suspend = 0;
        if (xhci_handshake(&xhci->op_regs->status,
                                STS_SAVE, 0, 10 * 1000)) {
-               xhci_warn(xhci, "WARN: xHC save state timeout\n");
-               spin_unlock_irq(&xhci->lock);
-               return -ETIMEDOUT;
+       /*
+        * AMD SNPS xHC 3.0 occasionally does not clear the
+        * SSS bit of USBSTS and when driver tries to poll
+        * to see if the xHC clears BIT(8) which never happens
+        * and driver assumes that controller is not responding
+        * and times out. To workaround this, its good to check
+        * if SRE and HCE bits are not set (as per xhci
+        * Section 5.4.2) and bypass the timeout.
+        */
+               res = readl(&xhci->op_regs->status);
+               if ((xhci->quirks & XHCI_SNPS_BROKEN_SUSPEND) &&
+                   (((res & STS_SRE) == 0) &&
+                               ((res & STS_HCE) == 0))) {
+                       xhci->broken_suspend = 1;
+               } else {
+                       xhci_warn(xhci, "WARN: xHC save state timeout\n");
+                       spin_unlock_irq(&xhci->lock);
+                       return -ETIMEDOUT;
+               }
        }
        spin_unlock_irq(&xhci->lock);
 
@@ -1078,7 +1096,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
        set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
 
        spin_lock_irq(&xhci->lock);
-       if (xhci->quirks & XHCI_RESET_ON_RESUME)
+       if ((xhci->quirks & XHCI_RESET_ON_RESUME) || xhci->broken_suspend)
                hibernated = true;
 
        if (!hibernated) {
@@ -4496,6 +4514,14 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci,
 {
        unsigned long long timeout_ns;
 
+       /* Prevent U1 if service interval is shorter than U1 exit latency */
+       if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) {
+               if (xhci_service_interval_to_ns(desc) <= udev->u1_params.mel) {
+                       dev_dbg(&udev->dev, "Disable U1, ESIT shorter than exit latency\n");
+                       return USB3_LPM_DISABLED;
+               }
+       }
+
        if (xhci->quirks & XHCI_INTEL_HOST)
                timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
        else
@@ -4552,6 +4578,14 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci,
 {
        unsigned long long timeout_ns;
 
+       /* Prevent U2 if service interval is shorter than U2 exit latency */
+       if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) {
+               if (xhci_service_interval_to_ns(desc) <= udev->u2_params.mel) {
+                       dev_dbg(&udev->dev, "Disable U2, ESIT shorter than exit latency\n");
+                       return USB3_LPM_DISABLED;
+               }
+       }
+
        if (xhci->quirks & XHCI_INTEL_HOST)
                timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc);
        else
index 260b259..c3515ba 100644 (file)
@@ -1850,6 +1850,7 @@ struct xhci_hcd {
 #define XHCI_ZERO_64B_REGS     BIT_ULL(32)
 #define XHCI_DEFAULT_PM_RUNTIME_ALLOW  BIT_ULL(33)
 #define XHCI_RESET_PLL_ON_DISCONNECT   BIT_ULL(34)
+#define XHCI_SNPS_BROKEN_SUSPEND    BIT_ULL(35)
 
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
@@ -1879,6 +1880,8 @@ struct xhci_hcd {
        void                    *dbc;
        /* platform-specific data -- must come last */
        unsigned long           priv[0] __aligned(sizeof(s64));
+       /* Broken Suspend flag for SNPS Suspend resume issue */
+       u8                      broken_suspend;
 };
 
 /* Platform specific overrides to generic XHCI hc_driver ops */
index 85b48c6..39ca31b 100644 (file)
@@ -51,6 +51,7 @@ static const struct usb_device_id appledisplay_table[] = {
        { APPLEDISPLAY_DEVICE(0x921c) },
        { APPLEDISPLAY_DEVICE(0x921d) },
        { APPLEDISPLAY_DEVICE(0x9222) },
+       { APPLEDISPLAY_DEVICE(0x9226) },
        { APPLEDISPLAY_DEVICE(0x9236) },
 
        /* Terminating entry */
index 1794058..7d28930 100644 (file)
@@ -101,7 +101,6 @@ static int usb_console_setup(struct console *co, char *options)
                cflag |= PARENB;
                break;
        }
-       co->cflag = cflag;
 
        /*
         * no need to check the index here: if the index is wrong, console
@@ -164,6 +163,7 @@ static int usb_console_setup(struct console *co, char *options)
                        serial->type->set_termios(tty, port, &dummy);
 
                        tty_port_tty_set(&port->port, NULL);
+                       tty_save_termios(tty);
                        tty_kref_put(tty);
                }
                tty_port_set_initialized(&port->port, 1);
index d17cd95..6b2140f 100644 (file)
@@ -27,4 +27,14 @@ UNUSUAL_DEV(0x0bda, 0x0159, 0x0000, 0x9999,
                "USB Card Reader",
                USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
 
+UNUSUAL_DEV(0x0bda, 0x0177, 0x0000, 0x9999,
+               "Realtek",
+               "USB Card Reader",
+               USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
+
+UNUSUAL_DEV(0x0bda, 0x0184, 0x0000, 0x9999,
+               "Realtek",
+               "USB Card Reader",
+               USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
+
 #endif  /* defined(CONFIG_USB_STORAGE_REALTEK) || ... */
index 34bc3ab..98ed5be 100644 (file)
@@ -15,6 +15,7 @@
 #include <net/sock.h>
 #include <linux/virtio_vsock.h>
 #include <linux/vhost.h>
+#include <linux/hashtable.h>
 
 #include <net/af_vsock.h>
 #include "vhost.h"
@@ -27,14 +28,14 @@ enum {
 
 /* Used to track all the vhost_vsock instances on the system. */
 static DEFINE_SPINLOCK(vhost_vsock_lock);
-static LIST_HEAD(vhost_vsock_list);
+static DEFINE_READ_MOSTLY_HASHTABLE(vhost_vsock_hash, 8);
 
 struct vhost_vsock {
        struct vhost_dev dev;
        struct vhost_virtqueue vqs[2];
 
-       /* Link to global vhost_vsock_list, protected by vhost_vsock_lock */
-       struct list_head list;
+       /* Link to global vhost_vsock_hash, writes use vhost_vsock_lock */
+       struct hlist_node hash;
 
        struct vhost_work send_pkt_work;
        spinlock_t send_pkt_list_lock;
@@ -50,11 +51,14 @@ static u32 vhost_transport_get_local_cid(void)
        return VHOST_VSOCK_DEFAULT_HOST_CID;
 }
 
-static struct vhost_vsock *__vhost_vsock_get(u32 guest_cid)
+/* Callers that dereference the return value must hold vhost_vsock_lock or the
+ * RCU read lock.
+ */
+static struct vhost_vsock *vhost_vsock_get(u32 guest_cid)
 {
        struct vhost_vsock *vsock;
 
-       list_for_each_entry(vsock, &vhost_vsock_list, list) {
+       hash_for_each_possible_rcu(vhost_vsock_hash, vsock, hash, guest_cid) {
                u32 other_cid = vsock->guest_cid;
 
                /* Skip instances that have no CID yet */
@@ -69,17 +73,6 @@ static struct vhost_vsock *__vhost_vsock_get(u32 guest_cid)
        return NULL;
 }
 
-static struct vhost_vsock *vhost_vsock_get(u32 guest_cid)
-{
-       struct vhost_vsock *vsock;
-
-       spin_lock_bh(&vhost_vsock_lock);
-       vsock = __vhost_vsock_get(guest_cid);
-       spin_unlock_bh(&vhost_vsock_lock);
-
-       return vsock;
-}
-
 static void
 vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
                            struct vhost_virtqueue *vq)
@@ -210,9 +203,12 @@ vhost_transport_send_pkt(struct virtio_vsock_pkt *pkt)
        struct vhost_vsock *vsock;
        int len = pkt->len;
 
+       rcu_read_lock();
+
        /* Find the vhost_vsock according to guest context id  */
        vsock = vhost_vsock_get(le64_to_cpu(pkt->hdr.dst_cid));
        if (!vsock) {
+               rcu_read_unlock();
                virtio_transport_free_pkt(pkt);
                return -ENODEV;
        }
@@ -225,6 +221,8 @@ vhost_transport_send_pkt(struct virtio_vsock_pkt *pkt)
        spin_unlock_bh(&vsock->send_pkt_list_lock);
 
        vhost_work_queue(&vsock->dev, &vsock->send_pkt_work);
+
+       rcu_read_unlock();
        return len;
 }
 
@@ -234,12 +232,15 @@ vhost_transport_cancel_pkt(struct vsock_sock *vsk)
        struct vhost_vsock *vsock;
        struct virtio_vsock_pkt *pkt, *n;
        int cnt = 0;
+       int ret = -ENODEV;
        LIST_HEAD(freeme);
 
+       rcu_read_lock();
+
        /* Find the vhost_vsock according to guest context id  */
        vsock = vhost_vsock_get(vsk->remote_addr.svm_cid);
        if (!vsock)
-               return -ENODEV;
+               goto out;
 
        spin_lock_bh(&vsock->send_pkt_list_lock);
        list_for_each_entry_safe(pkt, n, &vsock->send_pkt_list, list) {
@@ -265,7 +266,10 @@ vhost_transport_cancel_pkt(struct vsock_sock *vsk)
                        vhost_poll_queue(&tx_vq->poll);
        }
 
-       return 0;
+       ret = 0;
+out:
+       rcu_read_unlock();
+       return ret;
 }
 
 static struct virtio_vsock_pkt *
@@ -533,10 +537,6 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
        spin_lock_init(&vsock->send_pkt_list_lock);
        INIT_LIST_HEAD(&vsock->send_pkt_list);
        vhost_work_init(&vsock->send_pkt_work, vhost_transport_send_pkt_work);
-
-       spin_lock_bh(&vhost_vsock_lock);
-       list_add_tail(&vsock->list, &vhost_vsock_list);
-       spin_unlock_bh(&vhost_vsock_lock);
        return 0;
 
 out:
@@ -563,13 +563,21 @@ static void vhost_vsock_reset_orphans(struct sock *sk)
         * executing.
         */
 
-       if (!vhost_vsock_get(vsk->remote_addr.svm_cid)) {
-               sock_set_flag(sk, SOCK_DONE);
-               vsk->peer_shutdown = SHUTDOWN_MASK;
-               sk->sk_state = SS_UNCONNECTED;
-               sk->sk_err = ECONNRESET;
-               sk->sk_error_report(sk);
-       }
+       /* If the peer is still valid, no need to reset connection */
+       if (vhost_vsock_get(vsk->remote_addr.svm_cid))
+               return;
+
+       /* If the close timeout is pending, let it expire.  This avoids races
+        * with the timeout callback.
+        */
+       if (vsk->close_work_scheduled)
+               return;
+
+       sock_set_flag(sk, SOCK_DONE);
+       vsk->peer_shutdown = SHUTDOWN_MASK;
+       sk->sk_state = SS_UNCONNECTED;
+       sk->sk_err = ECONNRESET;
+       sk->sk_error_report(sk);
 }
 
 static int vhost_vsock_dev_release(struct inode *inode, struct file *file)
@@ -577,9 +585,13 @@ static int vhost_vsock_dev_release(struct inode *inode, struct file *file)
        struct vhost_vsock *vsock = file->private_data;
 
        spin_lock_bh(&vhost_vsock_lock);
-       list_del(&vsock->list);
+       if (vsock->guest_cid)
+               hash_del_rcu(&vsock->hash);
        spin_unlock_bh(&vhost_vsock_lock);
 
+       /* Wait for other CPUs to finish using vsock */
+       synchronize_rcu();
+
        /* Iterating over all connections for all CIDs to find orphans is
         * inefficient.  Room for improvement here. */
        vsock_for_each_connected_socket(vhost_vsock_reset_orphans);
@@ -620,12 +632,17 @@ static int vhost_vsock_set_cid(struct vhost_vsock *vsock, u64 guest_cid)
 
        /* Refuse if CID is already in use */
        spin_lock_bh(&vhost_vsock_lock);
-       other = __vhost_vsock_get(guest_cid);
+       other = vhost_vsock_get(guest_cid);
        if (other && other != vsock) {
                spin_unlock_bh(&vhost_vsock_lock);
                return -EADDRINUSE;
        }
+
+       if (vsock->guest_cid)
+               hash_del_rcu(&vsock->hash);
+
        vsock->guest_cid = guest_cid;
+       hash_add_rcu(vhost_vsock_hash, &vsock->hash, guest_cid);
        spin_unlock_bh(&vhost_vsock_lock);
 
        return 0;
index fdfc64f..221b733 100644 (file)
@@ -251,25 +251,10 @@ static void release_memory_resource(struct resource *resource)
        kfree(resource);
 }
 
-/*
- * Host memory not allocated to dom0. We can use this range for hotplug-based
- * ballooning.
- *
- * It's a type-less resource. Setting IORESOURCE_MEM will make resource
- * management algorithms (arch_remove_reservations()) look into guest e820,
- * which we don't want.
- */
-static struct resource hostmem_resource = {
-       .name   = "Host RAM",
-};
-
-void __attribute__((weak)) __init arch_xen_balloon_init(struct resource *res)
-{}
-
 static struct resource *additional_memory_resource(phys_addr_t size)
 {
-       struct resource *res, *res_hostmem;
-       int ret = -ENOMEM;
+       struct resource *res;
+       int ret;
 
        res = kzalloc(sizeof(*res), GFP_KERNEL);
        if (!res)
@@ -278,42 +263,13 @@ static struct resource *additional_memory_resource(phys_addr_t size)
        res->name = "System RAM";
        res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
 
-       res_hostmem = kzalloc(sizeof(*res), GFP_KERNEL);
-       if (res_hostmem) {
-               /* Try to grab a range from hostmem */
-               res_hostmem->name = "Host memory";
-               ret = allocate_resource(&hostmem_resource, res_hostmem,
-                                       size, 0, -1,
-                                       PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL);
-       }
-
-       if (!ret) {
-               /*
-                * Insert this resource into iomem. Because hostmem_resource
-                * tracks portion of guest e820 marked as UNUSABLE noone else
-                * should try to use it.
-                */
-               res->start = res_hostmem->start;
-               res->end = res_hostmem->end;
-               ret = insert_resource(&iomem_resource, res);
-               if (ret < 0) {
-                       pr_err("Can't insert iomem_resource [%llx - %llx]\n",
-                               res->start, res->end);
-                       release_memory_resource(res_hostmem);
-                       res_hostmem = NULL;
-                       res->start = res->end = 0;
-               }
-       }
-
-       if (ret) {
-               ret = allocate_resource(&iomem_resource, res,
-                                       size, 0, -1,
-                                       PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL);
-               if (ret < 0) {
-                       pr_err("Cannot allocate new System RAM resource\n");
-                       kfree(res);
-                       return NULL;
-               }
+       ret = allocate_resource(&iomem_resource, res,
+                               size, 0, -1,
+                               PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL);
+       if (ret < 0) {
+               pr_err("Cannot allocate new System RAM resource\n");
+               kfree(res);
+               return NULL;
        }
 
 #ifdef CONFIG_SPARSEMEM
@@ -325,7 +281,6 @@ static struct resource *additional_memory_resource(phys_addr_t size)
                        pr_err("New System RAM resource outside addressable RAM (%lu > %lu)\n",
                               pfn, limit);
                        release_memory_resource(res);
-                       release_memory_resource(res_hostmem);
                        return NULL;
                }
        }
@@ -750,8 +705,6 @@ static int __init balloon_init(void)
        set_online_page_callback(&xen_online_page);
        register_memory_notifier(&xen_memory_nb);
        register_sysctl_table(xen_root);
-
-       arch_xen_balloon_init(&hostmem_resource);
 #endif
 
 #ifdef CONFIG_XEN_PV
index 2f11ca7..77224d8 100644 (file)
@@ -385,8 +385,8 @@ static int create_active(struct sock_mapping *map, int *evtchn)
 out_error:
        if (*evtchn >= 0)
                xenbus_free_evtchn(pvcalls_front_dev, *evtchn);
-       kfree(map->active.data.in);
-       kfree(map->active.ring);
+       free_pages((unsigned long)map->active.data.in, PVCALLS_RING_ORDER);
+       free_page((unsigned long)map->active.ring);
        return ret;
 }
 
index 23f1387..e7df65d 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/xen/hypervisor.h>
 
 #include <xen/xen.h>
+#include <xen/xen-ops.h>
 #include <xen/page.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/memory.h>
index 43dea3b..8a2562e 100644 (file)
@@ -1075,8 +1075,6 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
        if (fc->ac.error < 0)
                return;
 
-       d_drop(new_dentry);
-
        inode = afs_iget(fc->vnode->vfs_inode.i_sb, fc->key,
                         newfid, newstatus, newcb, fc->cbi);
        if (IS_ERR(inode)) {
@@ -1090,7 +1088,7 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
        vnode = AFS_FS_I(inode);
        set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
        afs_vnode_commit_status(fc, vnode, 0);
-       d_add(new_dentry, inode);
+       d_instantiate(new_dentry, inode);
 }
 
 /*
index d049cb4..fde6b4d 100644 (file)
@@ -61,8 +61,11 @@ void afs_fileserver_probe_result(struct afs_call *call)
                afs_io_error(call, afs_io_error_fs_probe_fail);
                goto out;
        case -ECONNRESET: /* Responded, but call expired. */
+       case -ERFKILL:
+       case -EADDRNOTAVAIL:
        case -ENETUNREACH:
        case -EHOSTUNREACH:
+       case -EHOSTDOWN:
        case -ECONNREFUSED:
        case -ETIMEDOUT:
        case -ETIME:
@@ -132,12 +135,14 @@ out:
 static int afs_do_probe_fileserver(struct afs_net *net,
                                   struct afs_server *server,
                                   struct key *key,
-                                  unsigned int server_index)
+                                  unsigned int server_index,
+                                  struct afs_error *_e)
 {
        struct afs_addr_cursor ac = {
                .index = 0,
        };
-       int ret;
+       bool in_progress = false;
+       int err;
 
        _enter("%pU", &server->uuid);
 
@@ -151,15 +156,17 @@ static int afs_do_probe_fileserver(struct afs_net *net,
        server->probe.rtt = UINT_MAX;
 
        for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) {
-               ret = afs_fs_get_capabilities(net, server, &ac, key, server_index,
+               err = afs_fs_get_capabilities(net, server, &ac, key, server_index,
                                              true);
-               if (ret != -EINPROGRESS) {
-                       afs_fs_probe_done(server);
-                       return ret;
-               }
+               if (err == -EINPROGRESS)
+                       in_progress = true;
+               else
+                       afs_prioritise_error(_e, err, ac.abort_code);
        }
 
-       return 0;
+       if (!in_progress)
+               afs_fs_probe_done(server);
+       return in_progress;
 }
 
 /*
@@ -169,21 +176,23 @@ int afs_probe_fileservers(struct afs_net *net, struct key *key,
                          struct afs_server_list *list)
 {
        struct afs_server *server;
-       int i, ret;
+       struct afs_error e;
+       bool in_progress = false;
+       int i;
 
+       e.error = 0;
+       e.responded = false;
        for (i = 0; i < list->nr_servers; i++) {
                server = list->servers[i].server;
                if (test_bit(AFS_SERVER_FL_PROBED, &server->flags))
                        continue;
 
-               if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &server->flags)) {
-                       ret = afs_do_probe_fileserver(net, server, key, i);
-                       if (ret)
-                               return ret;
-               }
+               if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &server->flags) &&
+                   afs_do_probe_fileserver(net, server, key, i, &e))
+                       in_progress = true;
        }
 
-       return 0;
+       return in_progress ? 0 : e.error;
 }
 
 /*
index 4c6d8e1..6b17d36 100644 (file)
@@ -382,7 +382,7 @@ void afs_zap_data(struct afs_vnode *vnode)
 int afs_validate(struct afs_vnode *vnode, struct key *key)
 {
        time64_t now = ktime_get_real_seconds();
-       bool valid = false;
+       bool valid;
        int ret;
 
        _enter("{v={%llx:%llu} fl=%lx},%x",
@@ -402,15 +402,21 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
                        vnode->cb_v_break = vnode->volume->cb_v_break;
                        valid = false;
                } else if (vnode->status.type == AFS_FTYPE_DIR &&
-                          test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) &&
-                          vnode->cb_expires_at - 10 > now) {
-                       valid = true;
-               } else if (!test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) &&
-                          vnode->cb_expires_at - 10 > now) {
+                          (!test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) ||
+                           vnode->cb_expires_at - 10 <= now)) {
+                       valid = false;
+               } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) ||
+                          vnode->cb_expires_at - 10 <= now) {
+                       valid = false;
+               } else {
                        valid = true;
                }
        } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
                valid = true;
+       } else {
+               vnode->cb_s_break = vnode->cb_interest->server->cb_s_break;
+               vnode->cb_v_break = vnode->volume->cb_v_break;
+               valid = false;
        }
 
        read_sequnlock_excl(&vnode->cb_lock);
index 5da3b09..8871b9e 100644 (file)
@@ -695,6 +695,14 @@ struct afs_interface {
        unsigned        mtu;            /* MTU of interface */
 };
 
+/*
+ * Error prioritisation and accumulation.
+ */
+struct afs_error {
+       short   error;                  /* Accumulated error */
+       bool    responded;              /* T if server responded */
+};
+
 /*
  * Cursor for iterating over a server's address list.
  */
@@ -1015,6 +1023,7 @@ static inline void __afs_stat(atomic_t *s)
  * misc.c
  */
 extern int afs_abort_to_error(u32);
+extern void afs_prioritise_error(struct afs_error *, int, u32);
 
 /*
  * mntpt.c
index 700a5fa..bbb1fd5 100644 (file)
@@ -118,3 +118,55 @@ int afs_abort_to_error(u32 abort_code)
        default:                return -EREMOTEIO;
        }
 }
+
+/*
+ * Select the error to report from a set of errors.
+ */
+void afs_prioritise_error(struct afs_error *e, int error, u32 abort_code)
+{
+       switch (error) {
+       case 0:
+               return;
+       default:
+               if (e->error == -ETIMEDOUT ||
+                   e->error == -ETIME)
+                       return;
+       case -ETIMEDOUT:
+       case -ETIME:
+               if (e->error == -ENOMEM ||
+                   e->error == -ENONET)
+                       return;
+       case -ENOMEM:
+       case -ENONET:
+               if (e->error == -ERFKILL)
+                       return;
+       case -ERFKILL:
+               if (e->error == -EADDRNOTAVAIL)
+                       return;
+       case -EADDRNOTAVAIL:
+               if (e->error == -ENETUNREACH)
+                       return;
+       case -ENETUNREACH:
+               if (e->error == -EHOSTUNREACH)
+                       return;
+       case -EHOSTUNREACH:
+               if (e->error == -EHOSTDOWN)
+                       return;
+       case -EHOSTDOWN:
+               if (e->error == -ECONNREFUSED)
+                       return;
+       case -ECONNREFUSED:
+               if (e->error == -ECONNRESET)
+                       return;
+       case -ECONNRESET: /* Responded, but call expired. */
+               if (e->responded)
+                       return;
+               e->error = error;
+               return;
+
+       case -ECONNABORTED:
+               e->responded = true;
+               e->error = afs_abort_to_error(abort_code);
+               return;
+       }
+}
index 0050425..c3ae324 100644 (file)
@@ -136,7 +136,8 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
        struct afs_addr_list *alist;
        struct afs_server *server;
        struct afs_vnode *vnode = fc->vnode;
-       u32 rtt, abort_code;
+       struct afs_error e;
+       u32 rtt;
        int error = fc->ac.error, i;
 
        _enter("%lx[%d],%lx[%d],%d,%d",
@@ -306,8 +307,11 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
                if (fc->error != -EDESTADDRREQ)
                        goto iterate_address;
                /* Fall through */
+       case -ERFKILL:
+       case -EADDRNOTAVAIL:
        case -ENETUNREACH:
        case -EHOSTUNREACH:
+       case -EHOSTDOWN:
        case -ECONNREFUSED:
                _debug("no conn");
                fc->error = error;
@@ -446,50 +450,15 @@ no_more_servers:
        if (fc->flags & AFS_FS_CURSOR_VBUSY)
                goto restart_from_beginning;
 
-       abort_code = 0;
-       error = -EDESTADDRREQ;
+       e.error = -EDESTADDRREQ;
+       e.responded = false;
        for (i = 0; i < fc->server_list->nr_servers; i++) {
                struct afs_server *s = fc->server_list->servers[i].server;
-               int probe_error = READ_ONCE(s->probe.error);
 
-               switch (probe_error) {
-               case 0:
-                       continue;
-               default:
-                       if (error == -ETIMEDOUT ||
-                           error == -ETIME)
-                               continue;
-               case -ETIMEDOUT:
-               case -ETIME:
-                       if (error == -ENOMEM ||
-                           error == -ENONET)
-                               continue;
-               case -ENOMEM:
-               case -ENONET:
-                       if (error == -ENETUNREACH)
-                               continue;
-               case -ENETUNREACH:
-                       if (error == -EHOSTUNREACH)
-                               continue;
-               case -EHOSTUNREACH:
-                       if (error == -ECONNREFUSED)
-                               continue;
-               case -ECONNREFUSED:
-                       if (error == -ECONNRESET)
-                               continue;
-               case -ECONNRESET: /* Responded, but call expired. */
-                       if (error == -ECONNABORTED)
-                               continue;
-               case -ECONNABORTED:
-                       abort_code = s->probe.abort_code;
-                       error = probe_error;
-                       continue;
-               }
+               afs_prioritise_error(&e, READ_ONCE(s->probe.error),
+                                    s->probe.abort_code);
        }
 
-       if (error == -ECONNABORTED)
-               error = afs_abort_to_error(abort_code);
-
 failed_set_error:
        fc->error = error;
 failed:
@@ -553,8 +522,11 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
                _leave(" = f [abort]");
                return false;
 
+       case -ERFKILL:
+       case -EADDRNOTAVAIL:
        case -ENETUNREACH:
        case -EHOSTUNREACH:
+       case -EHOSTDOWN:
        case -ECONNREFUSED:
        case -ETIMEDOUT:
        case -ETIME:
@@ -633,6 +605,7 @@ int afs_end_vnode_operation(struct afs_fs_cursor *fc)
        struct afs_net *net = afs_v2net(fc->vnode);
 
        if (fc->error == -EDESTADDRREQ ||
+           fc->error == -EADDRNOTAVAIL ||
            fc->error == -ENETUNREACH ||
            fc->error == -EHOSTUNREACH)
                afs_dump_edestaddrreq(fc);
index c0f616b..f0b0329 100644 (file)
@@ -61,8 +61,11 @@ void afs_vlserver_probe_result(struct afs_call *call)
                afs_io_error(call, afs_io_error_vl_probe_fail);
                goto out;
        case -ECONNRESET: /* Responded, but call expired. */
+       case -ERFKILL:
+       case -EADDRNOTAVAIL:
        case -ENETUNREACH:
        case -EHOSTUNREACH:
+       case -EHOSTDOWN:
        case -ECONNREFUSED:
        case -ETIMEDOUT:
        case -ETIME:
@@ -129,15 +132,17 @@ out:
  * Probe all of a vlserver's addresses to find out the best route and to
  * query its capabilities.
  */
-static int afs_do_probe_vlserver(struct afs_net *net,
-                                struct afs_vlserver *server,
-                                struct key *key,
-                                unsigned int server_index)
+static bool afs_do_probe_vlserver(struct afs_net *net,
+                                 struct afs_vlserver *server,
+                                 struct key *key,
+                                 unsigned int server_index,
+                                 struct afs_error *_e)
 {
        struct afs_addr_cursor ac = {
                .index = 0,
        };
-       int ret;
+       bool in_progress = false;
+       int err;
 
        _enter("%s", server->name);
 
@@ -151,15 +156,17 @@ static int afs_do_probe_vlserver(struct afs_net *net,
        server->probe.rtt = UINT_MAX;
 
        for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) {
-               ret = afs_vl_get_capabilities(net, &ac, key, server,
+               err = afs_vl_get_capabilities(net, &ac, key, server,
                                              server_index, true);
-               if (ret != -EINPROGRESS) {
-                       afs_vl_probe_done(server);
-                       return ret;
-               }
+               if (err == -EINPROGRESS)
+                       in_progress = true;
+               else
+                       afs_prioritise_error(_e, err, ac.abort_code);
        }
 
-       return 0;
+       if (!in_progress)
+               afs_vl_probe_done(server);
+       return in_progress;
 }
 
 /*
@@ -169,21 +176,23 @@ int afs_send_vl_probes(struct afs_net *net, struct key *key,
                       struct afs_vlserver_list *vllist)
 {
        struct afs_vlserver *server;
-       int i, ret;
+       struct afs_error e;
+       bool in_progress = false;
+       int i;
 
+       e.error = 0;
+       e.responded = false;
        for (i = 0; i < vllist->nr_servers; i++) {
                server = vllist->servers[i].server;
                if (test_bit(AFS_VLSERVER_FL_PROBED, &server->flags))
                        continue;
 
-               if (!test_and_set_bit_lock(AFS_VLSERVER_FL_PROBING, &server->flags)) {
-                       ret = afs_do_probe_vlserver(net, server, key, i);
-                       if (ret)
-                               return ret;
-               }
+               if (!test_and_set_bit_lock(AFS_VLSERVER_FL_PROBING, &server->flags) &&
+                   afs_do_probe_vlserver(net, server, key, i, &e))
+                       in_progress = true;
        }
 
-       return 0;
+       return in_progress ? 0 : e.error;
 }
 
 /*
index b64a284..7adde83 100644 (file)
@@ -71,8 +71,9 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc)
 {
        struct afs_addr_list *alist;
        struct afs_vlserver *vlserver;
+       struct afs_error e;
        u32 rtt;
-       int error = vc->ac.error, abort_code, i;
+       int error = vc->ac.error, i;
 
        _enter("%lx[%d],%lx[%d],%d,%d",
               vc->untried, vc->index,
@@ -119,8 +120,11 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc)
                        goto failed;
                }
 
+       case -ERFKILL:
+       case -EADDRNOTAVAIL:
        case -ENETUNREACH:
        case -EHOSTUNREACH:
+       case -EHOSTDOWN:
        case -ECONNREFUSED:
        case -ETIMEDOUT:
        case -ETIME:
@@ -235,50 +239,15 @@ no_more_servers:
        if (vc->flags & AFS_VL_CURSOR_RETRY)
                goto restart_from_beginning;
 
-       abort_code = 0;
-       error = -EDESTADDRREQ;
+       e.error = -EDESTADDRREQ;
+       e.responded = false;
        for (i = 0; i < vc->server_list->nr_servers; i++) {
                struct afs_vlserver *s = vc->server_list->servers[i].server;
-               int probe_error = READ_ONCE(s->probe.error);
 
-               switch (probe_error) {
-               case 0:
-                       continue;
-               default:
-                       if (error == -ETIMEDOUT ||
-                           error == -ETIME)
-                               continue;
-               case -ETIMEDOUT:
-               case -ETIME:
-                       if (error == -ENOMEM ||
-                           error == -ENONET)
-                               continue;
-               case -ENOMEM:
-               case -ENONET:
-                       if (error == -ENETUNREACH)
-                               continue;
-               case -ENETUNREACH:
-                       if (error == -EHOSTUNREACH)
-                               continue;
-               case -EHOSTUNREACH:
-                       if (error == -ECONNREFUSED)
-                               continue;
-               case -ECONNREFUSED:
-                       if (error == -ECONNRESET)
-                               continue;
-               case -ECONNRESET: /* Responded, but call expired. */
-                       if (error == -ECONNABORTED)
-                               continue;
-               case -ECONNABORTED:
-                       abort_code = s->probe.abort_code;
-                       error = probe_error;
-                       continue;
-               }
+               afs_prioritise_error(&e, READ_ONCE(s->probe.error),
+                                    s->probe.abort_code);
        }
 
-       if (error == -ECONNABORTED)
-               error = afs_abort_to_error(abort_code);
-
 failed_set_error:
        vc->error = error;
 failed:
@@ -341,6 +310,7 @@ int afs_end_vlserver_operation(struct afs_vl_cursor *vc)
        struct afs_net *net = vc->cell->net;
 
        if (vc->error == -EDESTADDRREQ ||
+           vc->error == -EADDRNOTAVAIL ||
            vc->error == -ENETUNREACH ||
            vc->error == -EHOSTUNREACH)
                afs_vl_dump_edestaddrreq(vc);
index 301e631..97f9835 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1436,6 +1436,7 @@ static int aio_prep_rw(struct kiocb *req, struct iocb *iocb)
                ret = ioprio_check_cap(iocb->aio_reqprio);
                if (ret) {
                        pr_debug("aio ioprio check cap error: %d\n", ret);
+                       fput(req->ki_filp);
                        return ret;
                }
 
index efcf89a..1a4e2b1 100644 (file)
@@ -389,13 +389,11 @@ static int check_block_group_item(struct btrfs_fs_info *fs_info,
 
        /*
         * Here we don't really care about alignment since extent allocator can
-        * handle it.  We care more about the size, as if one block group is
-        * larger than maximum size, it's must be some obvious corruption.
+        * handle it.  We care more about the size.
         */
-       if (key->offset > BTRFS_MAX_DATA_CHUNK_SIZE || key->offset == 0) {
+       if (key->offset == 0) {
                block_group_err(fs_info, leaf, slot,
-                       "invalid block group size, have %llu expect (0, %llu]",
-                               key->offset, BTRFS_MAX_DATA_CHUNK_SIZE);
+                               "invalid block group size 0");
                return -EUCLEAN;
        }
 
index 95983c7..1645fcf 100644 (file)
@@ -244,11 +244,13 @@ wait_for_old_object:
 
        ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags));
 
-       cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_retry);
+       cache->cache.ops->put_object(&xobject->fscache,
+               (enum fscache_obj_ref_trace)cachefiles_obj_put_wait_retry);
        goto try_again;
 
 requeue:
-       cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_timeo);
+       cache->cache.ops->put_object(&xobject->fscache,
+               (enum fscache_obj_ref_trace)cachefiles_obj_put_wait_timeo);
        _leave(" = -ETIMEDOUT");
        return -ETIMEDOUT;
 }
@@ -336,7 +338,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
 try_again:
        /* first step is to make up a grave dentry in the graveyard */
        sprintf(nbuffer, "%08x%08x",
-               (uint32_t) get_seconds(),
+               (uint32_t) ktime_get_real_seconds(),
                (uint32_t) atomic_inc_return(&cache->gravecounter));
 
        /* do the multiway lock magic */
index 40f7595..8a57740 100644 (file)
@@ -535,7 +535,10 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
                                            netpage->index, cachefiles_gfp);
                if (ret < 0) {
                        if (ret == -EEXIST) {
+                               put_page(backpage);
+                               backpage = NULL;
                                put_page(netpage);
+                               netpage = NULL;
                                fscache_retrieval_complete(op, 1);
                                continue;
                        }
@@ -608,7 +611,10 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
                                            netpage->index, cachefiles_gfp);
                if (ret < 0) {
                        if (ret == -EEXIST) {
+                               put_page(backpage);
+                               backpage = NULL;
                                put_page(netpage);
+                               netpage = NULL;
                                fscache_retrieval_complete(op, 1);
                                continue;
                        }
@@ -962,11 +968,8 @@ void cachefiles_uncache_page(struct fscache_object *_object, struct page *page)
        __releases(&object->fscache.cookie->lock)
 {
        struct cachefiles_object *object;
-       struct cachefiles_cache *cache;
 
        object = container_of(_object, struct cachefiles_object, fscache);
-       cache = container_of(object->fscache.cache,
-                            struct cachefiles_cache, cache);
 
        _enter("%p,{%lu}", object, page->index);
 
index 0a29a00..511e6c6 100644 (file)
@@ -135,7 +135,8 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object,
        struct dentry *dentry = object->dentry;
        int ret;
 
-       ASSERT(dentry);
+       if (!dentry)
+               return -ESTALE;
 
        _enter("%p,#%d", object, auxdata->len);
 
index abcd78e..85dadb9 100644 (file)
@@ -133,7 +133,7 @@ config CIFS_XATTR
 
 config CIFS_POSIX
         bool "CIFS POSIX Extensions"
-        depends on CIFS_XATTR
+        depends on CIFS && CIFS_ALLOW_INSECURE_LEGACY && CIFS_XATTR
         help
           Enabling this option will cause the cifs client to attempt to
          negotiate a newer dialect with servers, such as Samba 3.0.5
index 3713d22..907e85d 100644 (file)
@@ -174,7 +174,7 @@ cifs_bp_rename_retry:
 
                cifs_dbg(FYI, "using cifs_sb prepath <%s>\n", cifs_sb->prepath);
                memcpy(full_path+dfsplen+1, cifs_sb->prepath, pplen-1);
-               full_path[dfsplen] = '\\';
+               full_path[dfsplen] = dirsep;
                for (i = 0; i < pplen-1; i++)
                        if (full_path[dfsplen+1+i] == '/')
                                full_path[dfsplen+1+i] = CIFS_DIR_SEP(cifs_sb);
index 74c33d5..c9bc56b 100644 (file)
@@ -2541,14 +2541,13 @@ static int
 cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list,
        struct cifs_aio_ctx *ctx)
 {
-       int wait_retry = 0;
        unsigned int wsize, credits;
        int rc;
        struct TCP_Server_Info *server =
                tlink_tcon(wdata->cfile->tlink)->ses->server;
 
        /*
-        * Try to resend this wdata, waiting for credits up to 3 seconds.
+        * Wait for credits to resend this wdata.
         * Note: we are attempting to resend the whole wdata not in segments
         */
        do {
@@ -2556,19 +2555,13 @@ cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list,
                        server, wdata->bytes, &wsize, &credits);
 
                if (rc)
-                       break;
+                       goto out;
 
                if (wsize < wdata->bytes) {
                        add_credits_and_wake_if(server, credits, 0);
                        msleep(1000);
-                       wait_retry++;
                }
-       } while (wsize < wdata->bytes && wait_retry < 3);
-
-       if (wsize < wdata->bytes) {
-               rc = -EBUSY;
-               goto out;
-       }
+       } while (wsize < wdata->bytes);
 
        rc = -EAGAIN;
        while (rc == -EAGAIN) {
@@ -3234,14 +3227,13 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata,
                        struct list_head *rdata_list,
                        struct cifs_aio_ctx *ctx)
 {
-       int wait_retry = 0;
        unsigned int rsize, credits;
        int rc;
        struct TCP_Server_Info *server =
                tlink_tcon(rdata->cfile->tlink)->ses->server;
 
        /*
-        * Try to resend this rdata, waiting for credits up to 3 seconds.
+        * Wait for credits to resend this rdata.
         * Note: we are attempting to resend the whole rdata not in segments
         */
        do {
@@ -3249,24 +3241,13 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata,
                                                &rsize, &credits);
 
                if (rc)
-                       break;
+                       goto out;
 
                if (rsize < rdata->bytes) {
                        add_credits_and_wake_if(server, credits, 0);
                        msleep(1000);
-                       wait_retry++;
                }
-       } while (rsize < rdata->bytes && wait_retry < 3);
-
-       /*
-        * If we can't find enough credits to send this rdata
-        * release the rdata and return failure, this will pass
-        * whatever I/O amount we have finished to VFS.
-        */
-       if (rsize < rdata->bytes) {
-               rc = -EBUSY;
-               goto out;
-       }
+       } while (rsize < rdata->bytes);
 
        rc = -EAGAIN;
        while (rc == -EAGAIN) {
index 9bcce89..48132ec 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -232,6 +232,34 @@ static void *get_unlocked_entry(struct xa_state *xas)
        }
 }
 
+/*
+ * The only thing keeping the address space around is the i_pages lock
+ * (it's cycled in clear_inode() after removing the entries from i_pages)
+ * After we call xas_unlock_irq(), we cannot touch xas->xa.
+ */
+static void wait_entry_unlocked(struct xa_state *xas, void *entry)
+{
+       struct wait_exceptional_entry_queue ewait;
+       wait_queue_head_t *wq;
+
+       init_wait(&ewait.wait);
+       ewait.wait.func = wake_exceptional_entry_func;
+
+       wq = dax_entry_waitqueue(xas, entry, &ewait.key);
+       prepare_to_wait_exclusive(wq, &ewait.wait, TASK_UNINTERRUPTIBLE);
+       xas_unlock_irq(xas);
+       schedule();
+       finish_wait(wq, &ewait.wait);
+
+       /*
+        * Entry lock waits are exclusive. Wake up the next waiter since
+        * we aren't sure we will acquire the entry lock and thus wake
+        * the next waiter up on unlock.
+        */
+       if (waitqueue_active(wq))
+               __wake_up(wq, TASK_NORMAL, 1, &ewait.key);
+}
+
 static void put_unlocked_entry(struct xa_state *xas, void *entry)
 {
        /* If we were the only waiter woken, wake the next one */
@@ -351,21 +379,21 @@ static struct page *dax_busy_page(void *entry)
  * @page: The page whose entry we want to lock
  *
  * Context: Process context.
- * Return: %true if the entry was locked or does not need to be locked.
+ * Return: A cookie to pass to dax_unlock_page() or 0 if the entry could
+ * not be locked.
  */
-bool dax_lock_mapping_entry(struct page *page)
+dax_entry_t dax_lock_page(struct page *page)
 {
        XA_STATE(xas, NULL, 0);
        void *entry;
-       bool locked;
 
        /* Ensure page->mapping isn't freed while we look at it */
        rcu_read_lock();
        for (;;) {
                struct address_space *mapping = READ_ONCE(page->mapping);
 
-               locked = false;
-               if (!dax_mapping(mapping))
+               entry = NULL;
+               if (!mapping || !dax_mapping(mapping))
                        break;
 
                /*
@@ -375,7 +403,7 @@ bool dax_lock_mapping_entry(struct page *page)
                 * otherwise we would not have a valid pfn_to_page()
                 * translation.
                 */
-               locked = true;
+               entry = (void *)~0UL;
                if (S_ISCHR(mapping->host->i_mode))
                        break;
 
@@ -389,9 +417,7 @@ bool dax_lock_mapping_entry(struct page *page)
                entry = xas_load(&xas);
                if (dax_is_locked(entry)) {
                        rcu_read_unlock();
-                       entry = get_unlocked_entry(&xas);
-                       xas_unlock_irq(&xas);
-                       put_unlocked_entry(&xas, entry);
+                       wait_entry_unlocked(&xas, entry);
                        rcu_read_lock();
                        continue;
                }
@@ -400,23 +426,18 @@ bool dax_lock_mapping_entry(struct page *page)
                break;
        }
        rcu_read_unlock();
-       return locked;
+       return (dax_entry_t)entry;
 }
 
-void dax_unlock_mapping_entry(struct page *page)
+void dax_unlock_page(struct page *page, dax_entry_t cookie)
 {
        struct address_space *mapping = page->mapping;
        XA_STATE(xas, &mapping->i_pages, page->index);
-       void *entry;
 
        if (S_ISCHR(mapping->host->i_mode))
                return;
 
-       rcu_read_lock();
-       entry = xas_load(&xas);
-       rcu_read_unlock();
-       entry = dax_make_entry(page_to_pfn_t(page), dax_is_pmd_entry(entry));
-       dax_unlock_entry(&xas, entry);
+       dax_unlock_entry(&xas, (void *)cookie);
 }
 
 /*
index 722d17c..41a0e97 100644 (file)
@@ -325,8 +325,8 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, unsigned int flags)
                 */
                dio->iocb->ki_pos += transferred;
 
-               if (dio->op == REQ_OP_WRITE)
-                       ret = generic_write_sync(dio->iocb,  transferred);
+               if (ret > 0 && dio->op == REQ_OP_WRITE)
+                       ret = generic_write_sync(dio->iocb, ret);
                dio->iocb->ki_complete(dio->iocb, ret, 0);
        }
 
index acc3a55..fc281b7 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -62,7 +62,6 @@
 #include <linux/oom.h>
 #include <linux/compat.h>
 #include <linux/vmalloc.h>
-#include <linux/freezer.h>
 
 #include <linux/uaccess.h>
 #include <asm/mmu_context.h>
@@ -1084,7 +1083,7 @@ static int de_thread(struct task_struct *tsk)
        while (sig->notify_count) {
                __set_current_state(TASK_KILLABLE);
                spin_unlock_irq(lock);
-               freezable_schedule();
+               schedule();
                if (unlikely(__fatal_signal_pending(tsk)))
                        goto killed;
                spin_lock_irq(lock);
@@ -1112,7 +1111,7 @@ static int de_thread(struct task_struct *tsk)
                        __set_current_state(TASK_KILLABLE);
                        write_unlock_irq(&tasklist_lock);
                        cgroup_threadgroup_change_end(tsk);
-                       freezable_schedule();
+                       schedule();
                        if (unlikely(__fatal_signal_pending(tsk)))
                                goto killed;
                }
index 645158d..c69927b 100644 (file)
@@ -77,7 +77,7 @@ static bool dentry_connected(struct dentry *dentry)
                struct dentry *parent = dget_parent(dentry);
 
                dput(dentry);
-               if (IS_ROOT(dentry)) {
+               if (dentry == parent) {
                        dput(parent);
                        return false;
                }
@@ -147,6 +147,7 @@ static struct dentry *reconnect_one(struct vfsmount *mnt,
        tmp = lookup_one_len_unlocked(nbuf, parent, strlen(nbuf));
        if (IS_ERR(tmp)) {
                dprintk("%s: lookup failed: %d\n", __func__, PTR_ERR(tmp));
+               err = PTR_ERR(tmp);
                goto out_err;
        }
        if (tmp != dentry) {
index cb91baa..eb11502 100644 (file)
@@ -892,6 +892,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
        if (sb->s_magic != EXT2_SUPER_MAGIC)
                goto cantfind_ext2;
 
+       opts.s_mount_opt = 0;
        /* Set defaults before we parse the mount options */
        def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
        if (def_mount_opts & EXT2_DEFM_DEBUG)
index 62d9a65..dd8f10d 100644 (file)
@@ -612,9 +612,9 @@ skip_replace:
        }
 
 cleanup:
-       brelse(bh);
        if (!(bh && header == HDR(bh)))
                kfree(header);
+       brelse(bh);
        up_write(&EXT2_I(inode)->xattr_sem);
 
        return error;
index 9edc920..6d9cb17 100644 (file)
@@ -730,6 +730,9 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob
 
        if (awaken)
                wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
+       if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags))
+               wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
+
 
        /* Prevent a race with our last child, which has to signal EV_CLEARED
         * before dropping our spinlock.
index 98b96ff..19017d2 100644 (file)
@@ -338,13 +338,14 @@ void hfs_bmap_free(struct hfs_bnode *node)
 
                nidx -= len * 8;
                i = node->next;
-               hfs_bnode_put(node);
                if (!i) {
                        /* panic */;
                        pr_crit("unable to free bnode %u. bmap not found!\n",
                                node->this);
+                       hfs_bnode_put(node);
                        return;
                }
+               hfs_bnode_put(node);
                node = hfs_bnode_find(tree, i);
                if (IS_ERR(node))
                        return;
index 236efe5..66774f4 100644 (file)
@@ -466,14 +466,15 @@ void hfs_bmap_free(struct hfs_bnode *node)
 
                nidx -= len * 8;
                i = node->next;
-               hfs_bnode_put(node);
                if (!i) {
                        /* panic */;
                        pr_crit("unable to free bnode %u. "
                                        "bmap not found!\n",
                                node->this);
+                       hfs_bnode_put(node);
                        return;
                }
+               hfs_bnode_put(node);
                node = hfs_bnode_find(tree, i);
                if (IS_ERR(node))
                        return;
index 3ffb776..d6bc98a 100644 (file)
@@ -1877,15 +1877,6 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                                dio->wait_for_completion = true;
                                ret = 0;
                        }
-
-                       /*
-                        * Splicing to pipes can fail on a full pipe. We have to
-                        * swallow this to make it look like a short IO
-                        * otherwise the higher splice layers will completely
-                        * mishandle the error and stop moving data.
-                        */
-                       if (ret == -EFAULT)
-                               ret = 0;
                        break;
                }
                pos += ret;
index aa12c30..33824a0 100644 (file)
@@ -98,8 +98,11 @@ struct nfs_direct_req {
        struct pnfs_ds_commit_info ds_cinfo;    /* Storage for cinfo */
        struct work_struct      work;
        int                     flags;
+       /* for write */
 #define NFS_ODIRECT_DO_COMMIT          (1)     /* an unstable reply was received */
 #define NFS_ODIRECT_RESCHED_WRITES     (2)     /* write verification failed */
+       /* for read */
+#define NFS_ODIRECT_SHOULD_DIRTY       (3)     /* dirty user-space page after read */
        struct nfs_writeverf    verf;           /* unstable write verifier */
 };
 
@@ -412,7 +415,8 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr)
                struct nfs_page *req = nfs_list_entry(hdr->pages.next);
                struct page *page = req->wb_page;
 
-               if (!PageCompound(page) && bytes < hdr->good_bytes)
+               if (!PageCompound(page) && bytes < hdr->good_bytes &&
+                   (dreq->flags == NFS_ODIRECT_SHOULD_DIRTY))
                        set_page_dirty(page);
                bytes += req->wb_bytes;
                nfs_list_remove_request(req);
@@ -587,6 +591,9 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter)
        if (!is_sync_kiocb(iocb))
                dreq->iocb = iocb;
 
+       if (iter_is_iovec(iter))
+               dreq->flags = NFS_ODIRECT_SHOULD_DIRTY;
+
        nfs_start_io_direct(inode);
 
        NFS_I(inode)->read_io += count;
index 74b36ed..310d750 100644 (file)
@@ -1733,7 +1733,8 @@ ff_layout_read_pagelist(struct nfs_pgio_header *hdr)
        if (fh)
                hdr->args.fh = fh;
 
-       if (!nfs4_ff_layout_select_ds_stateid(lseg, idx, &hdr->args.stateid))
+       if (vers == 4 &&
+               !nfs4_ff_layout_select_ds_stateid(lseg, idx, &hdr->args.stateid))
                goto out_failed;
 
        /*
@@ -1798,7 +1799,8 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
        if (fh)
                hdr->args.fh = fh;
 
-       if (!nfs4_ff_layout_select_ds_stateid(lseg, idx, &hdr->args.stateid))
+       if (vers == 4 &&
+               !nfs4_ff_layout_select_ds_stateid(lseg, idx, &hdr->args.stateid))
                goto out_failed;
 
        /*
index 9f88188..4bf8d58 100644 (file)
@@ -125,10 +125,10 @@ check_err:
 
 check_gen:
        if (handle->ih_generation != inode->i_generation) {
-               iput(inode);
                trace_ocfs2_get_dentry_generation((unsigned long long)blkno,
                                                  handle->ih_generation,
                                                  inode->i_generation);
+               iput(inode);
                result = ERR_PTR(-ESTALE);
                goto bail;
        }
index 3f1685d..1565dd8 100644 (file)
@@ -157,18 +157,14 @@ out:
 }
 
 /*
- * lock allocators, and reserving appropriate number of bits for
- * meta blocks and data clusters.
- *
- * in some cases, we don't need to reserve clusters, just let data_ac
- * be NULL.
+ * lock allocator, and reserve appropriate number of bits for
+ * meta blocks.
  */
-static int ocfs2_lock_allocators_move_extents(struct inode *inode,
+static int ocfs2_lock_meta_allocator_move_extents(struct inode *inode,
                                        struct ocfs2_extent_tree *et,
                                        u32 clusters_to_move,
                                        u32 extents_to_split,
                                        struct ocfs2_alloc_context **meta_ac,
-                                       struct ocfs2_alloc_context **data_ac,
                                        int extra_blocks,
                                        int *credits)
 {
@@ -193,13 +189,6 @@ static int ocfs2_lock_allocators_move_extents(struct inode *inode,
                goto out;
        }
 
-       if (data_ac) {
-               ret = ocfs2_reserve_clusters(osb, clusters_to_move, data_ac);
-               if (ret) {
-                       mlog_errno(ret);
-                       goto out;
-               }
-       }
 
        *credits += ocfs2_calc_extend_credits(osb->sb, et->et_root_el);
 
@@ -259,10 +248,10 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context,
                }
        }
 
-       ret = ocfs2_lock_allocators_move_extents(inode, &context->et, *len, 1,
-                                                &context->meta_ac,
-                                                &context->data_ac,
-                                                extra_blocks, &credits);
+       ret = ocfs2_lock_meta_allocator_move_extents(inode, &context->et,
+                                               *len, 1,
+                                               &context->meta_ac,
+                                               extra_blocks, &credits);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -285,6 +274,21 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context,
                }
        }
 
+       /*
+        * Make sure ocfs2_reserve_cluster is called after
+        * __ocfs2_flush_truncate_log, otherwise, dead lock may happen.
+        *
+        * If ocfs2_reserve_cluster is called
+        * before __ocfs2_flush_truncate_log, dead lock on global bitmap
+        * may happen.
+        *
+        */
+       ret = ocfs2_reserve_clusters(osb, *len, &context->data_ac);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_unlock_mutex;
+       }
+
        handle = ocfs2_start_trans(osb, credits);
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
@@ -617,9 +621,10 @@ static int ocfs2_move_extent(struct ocfs2_move_extents_context *context,
                }
        }
 
-       ret = ocfs2_lock_allocators_move_extents(inode, &context->et, len, 1,
-                                                &context->meta_ac,
-                                                NULL, extra_blocks, &credits);
+       ret = ocfs2_lock_meta_allocator_move_extents(inode, &context->et,
+                                               len, 1,
+                                               &context->meta_ac,
+                                               extra_blocks, &credits);
        if (ret) {
                mlog_errno(ret);
                goto out;
index ffcff65..e02a903 100644 (file)
@@ -816,17 +816,14 @@ static int ramoops_probe(struct platform_device *pdev)
 
        cxt->pstore.data = cxt;
        /*
-        * Console can handle any buffer size, so prefer LOG_LINE_MAX. If we
-        * have to handle dumps, we must have at least record_size buffer. And
-        * for ftrace, bufsize is irrelevant (if bufsize is 0, buf will be
-        * ZERO_SIZE_PTR).
+        * Since bufsize is only used for dmesg crash dumps, it
+        * must match the size of the dprz record (after PRZ header
+        * and ECC bytes have been accounted for).
         */
-       if (cxt->console_size)
-               cxt->pstore.bufsize = 1024; /* LOG_LINE_MAX */
-       cxt->pstore.bufsize = max(cxt->record_size, cxt->pstore.bufsize);
-       cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL);
+       cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size;
+       cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL);
        if (!cxt->pstore.buf) {
-               pr_err("cannot allocate pstore buffer\n");
+               pr_err("cannot allocate pstore crash dump buffer\n");
                err = -ENOMEM;
                goto fail_clear;
        }
index 4dae039..58f3053 100644 (file)
@@ -1956,7 +1956,7 @@ loff_t do_clone_file_range(struct file *file_in, loff_t pos_in,
        struct inode *inode_out = file_inode(file_out);
        loff_t ret;
 
-       WARN_ON_ONCE(remap_flags);
+       WARN_ON_ONCE(remap_flags & REMAP_FILE_DEDUP);
 
        if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
                return -EISDIR;
index 3553f19..de2ede0 100644 (file)
@@ -945,11 +945,16 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
        sd->flags &= ~SPLICE_F_NONBLOCK;
        more = sd->flags & SPLICE_F_MORE;
 
+       WARN_ON_ONCE(pipe->nrbufs != 0);
+
        while (len) {
                size_t read_len;
                loff_t pos = sd->pos, prev_pos = pos;
 
-               ret = do_splice_to(in, &pos, pipe, len, flags);
+               /* Don't try to read more the pipe has space for. */
+               read_len = min_t(size_t, len,
+                                (pipe->buffers - pipe->nrbufs) << PAGE_SHIFT);
+               ret = do_splice_to(in, &pos, pipe, read_len, flags);
                if (unlikely(ret <= 0))
                        goto out_release;
 
index 499a20a..273736f 100644 (file)
@@ -275,7 +275,7 @@ static int __sysv_write_inode(struct inode *inode, int wait)
                 }
         }
        brelse(bh);
-       return 0;
+       return err;
 }
 
 int sysv_write_inode(struct inode *inode, struct writeback_control *wbc)
index 8f2f56d..e3d684e 100644 (file)
@@ -827,16 +827,20 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
 
 
        ret = udf_dstrCS0toChar(sb, outstr, 31, pvoldesc->volIdent, 32);
-       if (ret < 0)
-               goto out_bh;
-
-       strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret);
+       if (ret < 0) {
+               strcpy(UDF_SB(sb)->s_volume_ident, "InvalidName");
+               pr_warn("incorrect volume identification, setting to "
+                       "'InvalidName'\n");
+       } else {
+               strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret);
+       }
        udf_debug("volIdent[] = '%s'\n", UDF_SB(sb)->s_volume_ident);
 
        ret = udf_dstrCS0toChar(sb, outstr, 127, pvoldesc->volSetIdent, 128);
-       if (ret < 0)
+       if (ret < 0) {
+               ret = 0;
                goto out_bh;
-
+       }
        outstr[ret] = 0;
        udf_debug("volSetIdent[] = '%s'\n", outstr);
 
index 4523479..5fcfa96 100644 (file)
@@ -351,6 +351,11 @@ try_again:
        return u_len;
 }
 
+/*
+ * Convert CS0 dstring to output charset. Warning: This function may truncate
+ * input string if it is too long as it is used for informational strings only
+ * and it is better to truncate the string than to refuse mounting a media.
+ */
 int udf_dstrCS0toChar(struct super_block *sb, uint8_t *utf_o, int o_len,
                      const uint8_t *ocu_i, int i_len)
 {
@@ -359,9 +364,12 @@ int udf_dstrCS0toChar(struct super_block *sb, uint8_t *utf_o, int o_len,
        if (i_len > 0) {
                s_len = ocu_i[i_len - 1];
                if (s_len >= i_len) {
-                       pr_err("incorrect dstring lengths (%d/%d)\n",
-                              s_len, i_len);
-                       return -EINVAL;
+                       pr_warn("incorrect dstring lengths (%d/%d),"
+                               " truncating\n", s_len, i_len);
+                       s_len = i_len - 1;
+                       /* 2-byte encoding? Need to round properly... */
+                       if (ocu_i[0] == 16)
+                               s_len -= (s_len - 1) & 2;
                }
        }
 
index 356d2b8..cd58939 100644 (file)
@@ -1361,6 +1361,19 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
                ret = -EINVAL;
                if (!vma_can_userfault(cur))
                        goto out_unlock;
+
+               /*
+                * UFFDIO_COPY will fill file holes even without
+                * PROT_WRITE. This check enforces that if this is a
+                * MAP_SHARED, the process has write permission to the backing
+                * file. If VM_MAYWRITE is set it also enforces that on a
+                * MAP_SHARED vma: there is no F_WRITE_SEAL and no further
+                * F_WRITE_SEAL can be taken until the vma is destroyed.
+                */
+               ret = -EPERM;
+               if (unlikely(!(cur->vm_flags & VM_MAYWRITE)))
+                       goto out_unlock;
+
                /*
                 * If this vma contains ending address, and huge pages
                 * check alignment.
@@ -1406,6 +1419,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
                BUG_ON(!vma_can_userfault(vma));
                BUG_ON(vma->vm_userfaultfd_ctx.ctx &&
                       vma->vm_userfaultfd_ctx.ctx != ctx);
+               WARN_ON(!(vma->vm_flags & VM_MAYWRITE));
 
                /*
                 * Nothing to do: this vma is already registered into this
@@ -1552,6 +1566,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
                cond_resched();
 
                BUG_ON(!vma_can_userfault(vma));
+               WARN_ON(!(vma->vm_flags & VM_MAYWRITE));
 
                /*
                 * Nothing to do: this vma is already registered into this
index 34c6d7b..bbdae2b 100644 (file)
@@ -330,7 +330,7 @@ xfs_btree_sblock_verify_crc(
 
        if (xfs_sb_version_hascrc(&mp->m_sb)) {
                if (!xfs_log_check_lsn(mp, be64_to_cpu(block->bb_u.s.bb_lsn)))
-                       return __this_address;
+                       return false;
                return xfs_buf_verify_cksum(bp, XFS_BTREE_SBLOCK_CRC_OFF);
        }
 
index 404e581..1ee8c55 100644 (file)
@@ -1126,9 +1126,9 @@ xfs_free_file_space(
         * page could be mmap'd and iomap_zero_range doesn't do that for us.
         * Writeback of the eof page will do this, albeit clumsily.
         */
-       if (offset + len >= XFS_ISIZE(ip) && ((offset + len) & PAGE_MASK)) {
+       if (offset + len >= XFS_ISIZE(ip) && offset_in_page(offset + len) > 0) {
                error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
-                               (offset + len) & ~PAGE_MASK, LLONG_MAX);
+                               round_down(offset + len, PAGE_SIZE), LLONG_MAX);
        }
 
        return error;
index 73a1d77..3091e4b 100644 (file)
@@ -40,7 +40,7 @@ xfs_fill_statvfs_from_dquot(
                statp->f_files = limit;
                statp->f_ffree =
                        (statp->f_files > dqp->q_res_icount) ?
-                        (statp->f_ffree - dqp->q_res_icount) : 0;
+                        (statp->f_files - dqp->q_res_icount) : 0;
        }
 }
 
index 450b28d..0dd316a 100644 (file)
@@ -7,6 +7,8 @@
 #include <linux/radix-tree.h>
 #include <asm/pgtable.h>
 
+typedef unsigned long dax_entry_t;
+
 struct iomap_ops;
 struct dax_device;
 struct dax_operations {
@@ -88,8 +90,8 @@ int dax_writeback_mapping_range(struct address_space *mapping,
                struct block_device *bdev, struct writeback_control *wbc);
 
 struct page *dax_layout_busy_page(struct address_space *mapping);
-bool dax_lock_mapping_entry(struct page *page);
-void dax_unlock_mapping_entry(struct page *page);
+dax_entry_t dax_lock_page(struct page *page);
+void dax_unlock_page(struct page *page, dax_entry_t cookie);
 #else
 static inline bool bdev_dax_supported(struct block_device *bdev,
                int blocksize)
@@ -122,14 +124,14 @@ static inline int dax_writeback_mapping_range(struct address_space *mapping,
        return -EOPNOTSUPP;
 }
 
-static inline bool dax_lock_mapping_entry(struct page *page)
+static inline dax_entry_t dax_lock_page(struct page *page)
 {
        if (IS_DAX(page->mapping->host))
-               return true;
-       return false;
+               return ~0UL;
+       return 0;
 }
 
-static inline void dax_unlock_mapping_entry(struct page *page)
+static inline void dax_unlock_page(struct page *page, dax_entry_t cookie)
 {
 }
 #endif
index 34cf0fd..610815e 100644 (file)
@@ -196,8 +196,7 @@ static inline void fscache_enqueue_retrieval(struct fscache_retrieval *op)
 static inline void fscache_retrieval_complete(struct fscache_retrieval *op,
                                              int n_pages)
 {
-       atomic_sub(n_pages, &op->n_pages);
-       if (atomic_read(&op->n_pages) <= 0)
+       if (atomic_sub_return_relaxed(n_pages, &op->n_pages) <= 0)
                fscache_op_complete(&op->op, false);
 }
 
index a397907..dd16e82 100644 (file)
@@ -777,8 +777,8 @@ struct ftrace_ret_stack {
 extern void return_to_handler(void);
 
 extern int
-ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
-                        unsigned long frame_pointer, unsigned long *retp);
+function_graph_enter(unsigned long ret, unsigned long func,
+                    unsigned long frame_pointer, unsigned long *retp);
 
 unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx,
                                    unsigned long ret, unsigned long *retp);
index 76f8db0..0705164 100644 (file)
@@ -510,18 +510,22 @@ alloc_pages(gfp_t gfp_mask, unsigned int order)
 }
 extern struct page *alloc_pages_vma(gfp_t gfp_mask, int order,
                        struct vm_area_struct *vma, unsigned long addr,
-                       int node);
+                       int node, bool hugepage);
+#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \
+       alloc_pages_vma(gfp_mask, order, vma, addr, numa_node_id(), true)
 #else
 #define alloc_pages(gfp_mask, order) \
                alloc_pages_node(numa_node_id(), gfp_mask, order)
-#define alloc_pages_vma(gfp_mask, order, vma, addr, node)\
+#define alloc_pages_vma(gfp_mask, order, vma, addr, node, false)\
+       alloc_pages(gfp_mask, order)
+#define alloc_hugepage_vma(gfp_mask, vma, addr, order) \
        alloc_pages(gfp_mask, order)
 #endif
 #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
 #define alloc_page_vma(gfp_mask, vma, addr)                    \
-       alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id())
+       alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id(), false)
 #define alloc_page_vma_node(gfp_mask, vma, addr, node)         \
-       alloc_pages_vma(gfp_mask, 0, vma, addr, node)
+       alloc_pages_vma(gfp_mask, 0, vma, addr, node, false)
 
 extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order);
 extern unsigned long get_zeroed_page(gfp_t gfp_mask);
index 331dc37..dc12f5c 100644 (file)
@@ -177,6 +177,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
 * @attr_usage_id:      Attribute usage id as per spec
 * @report_id:  Report id to look for
 * @flag:      Synchronous or asynchronous read
+* @is_signed:   If true then fields < 32 bits will be sign-extended
 *
 * Issues a synchronous or asynchronous read request for an input attribute.
 * Returns data upto 32 bits.
@@ -190,7 +191,8 @@ enum sensor_hub_read_flags {
 int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
                                        u32 usage_id,
                                        u32 attr_usage_id, u32 report_id,
-                                       enum sensor_hub_read_flags flag
+                                       enum sensor_hub_read_flags flag,
+                                       bool is_signed
 );
 
 /**
index b3e2436..14131b6 100644 (file)
@@ -905,6 +905,13 @@ struct vmbus_channel {
 
        bool probe_done;
 
+       /*
+        * We must offload the handling of the primary/sub channels
+        * from the single-threaded vmbus_connection.work_queue to
+        * two different workqueue, otherwise we can block
+        * vmbus_connection.work_queue and hang: see vmbus_process_offer().
+        */
+       struct work_struct add_channel_work;
 };
 
 static inline bool is_hvsock_channel(const struct vmbus_channel *c)
index bac395f..5228c62 100644 (file)
@@ -139,8 +139,6 @@ struct mempolicy *mpol_shared_policy_lookup(struct shared_policy *sp,
 struct mempolicy *get_task_policy(struct task_struct *p);
 struct mempolicy *__get_vma_policy(struct vm_area_struct *vma,
                unsigned long addr);
-struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
-                                               unsigned long addr);
 bool vma_policy_mof(struct vm_area_struct *vma);
 
 extern void numa_default_policy(void);
index dbff9ff..34e17e6 100644 (file)
@@ -2473,14 +2473,15 @@ struct mlx5_ifc_xrc_srqc_bits {
 
        u8         wq_signature[0x1];
        u8         cont_srq[0x1];
-       u8         dbr_umem_valid[0x1];
+       u8         reserved_at_22[0x1];
        u8         rlky[0x1];
        u8         basic_cyclic_rcv_wqe[0x1];
        u8         log_rq_stride[0x3];
        u8         xrcd[0x18];
 
        u8         page_offset[0x6];
-       u8         reserved_at_46[0x2];
+       u8         reserved_at_46[0x1];
+       u8         dbr_umem_valid[0x1];
        u8         cqn[0x18];
 
        u8         reserved_at_60[0x20];
@@ -6689,9 +6690,12 @@ struct mlx5_ifc_create_xrc_srq_in_bits {
 
        struct mlx5_ifc_xrc_srqc_bits xrc_srq_context_entry;
 
-       u8         reserved_at_280[0x40];
+       u8         reserved_at_280[0x60];
+
        u8         xrc_srq_umem_valid[0x1];
-       u8         reserved_at_2c1[0x5bf];
+       u8         reserved_at_2e1[0x1f];
+
+       u8         reserved_at_300[0x580];
 
        u8         pas[0][0x40];
 };
index f92a47e..a93841b 100644 (file)
@@ -17,6 +17,8 @@
 #define __DAVINCI_GPIO_PLATFORM_H
 
 struct davinci_gpio_platform_data {
+       bool    no_auto_base;
+       u32     base;
        u32     ngpio;
        u32     gpio_unbanked;
 };
index 8e0725a..7006008 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _LINUX_PSI_H
 #define _LINUX_PSI_H
 
+#include <linux/jump_label.h>
 #include <linux/psi_types.h>
 #include <linux/sched.h>
 
@@ -9,7 +10,7 @@ struct css_set;
 
 #ifdef CONFIG_PSI
 
-extern bool psi_disabled;
+extern struct static_key_false psi_disabled;
 
 void psi_init(void);
 
index a15bc4d..30fcec3 100644 (file)
@@ -90,7 +90,10 @@ struct pstore_record {
  *
  * @buf_lock:  spinlock to serialize access to @buf
  * @buf:       preallocated crash dump buffer
- * @bufsize:   size of @buf available for crash dump writes
+ * @bufsize:   size of @buf available for crash dump bytes (must match
+ *             smallest number of bytes available for writing to a
+ *             backend entry, since compressed bytes don't take kindly
+ *             to being truncated)
  *
  * @read_mutex:        serializes @open, @read, @close, and @erase callbacks
  * @flags:     bitfield of frontends the backend can accept writes for
index 6c2ffed..de20ede 100644 (file)
@@ -64,15 +64,12 @@ extern void exit_ptrace(struct task_struct *tracer, struct list_head *dead);
 #define PTRACE_MODE_NOAUDIT    0x04
 #define PTRACE_MODE_FSCREDS    0x08
 #define PTRACE_MODE_REALCREDS  0x10
-#define PTRACE_MODE_SCHED      0x20
-#define PTRACE_MODE_IBPB       0x40
 
 /* shorthands for READ/ATTACH and FSCREDS/REALCREDS combinations */
 #define PTRACE_MODE_READ_FSCREDS (PTRACE_MODE_READ | PTRACE_MODE_FSCREDS)
 #define PTRACE_MODE_READ_REALCREDS (PTRACE_MODE_READ | PTRACE_MODE_REALCREDS)
 #define PTRACE_MODE_ATTACH_FSCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS)
 #define PTRACE_MODE_ATTACH_REALCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS)
-#define PTRACE_MODE_SPEC_IBPB (PTRACE_MODE_ATTACH_REALCREDS | PTRACE_MODE_IBPB)
 
 /**
  * ptrace_may_access - check whether the caller is permitted to access
@@ -90,20 +87,6 @@ extern void exit_ptrace(struct task_struct *tracer, struct list_head *dead);
  */
 extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
 
-/**
- * ptrace_may_access - check whether the caller is permitted to access
- * a target task.
- * @task: target task
- * @mode: selects type of access and caller credentials
- *
- * Returns true on success, false on denial.
- *
- * Similar to ptrace_may_access(). Only to be called from context switch
- * code. Does not call into audit and the regular LSM hooks due to locking
- * constraints.
- */
-extern bool ptrace_may_access_sched(struct task_struct *task, unsigned int mode);
-
 static inline int ptrace_reparented(struct task_struct *child)
 {
        return !same_thread_group(child->real_parent, child->parent);
index a51c13c..291a9bd 100644 (file)
@@ -1116,6 +1116,7 @@ struct task_struct {
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        /* Index of current stored address in ret_stack: */
        int                             curr_ret_stack;
+       int                             curr_ret_depth;
 
        /* Stack of return addresses for return function tracing: */
        struct ftrace_ret_stack         *ret_stack;
@@ -1453,6 +1454,8 @@ static inline bool is_percpu_thread(void)
 #define PFA_SPREAD_SLAB                        2       /* Spread some slab caches over cpuset */
 #define PFA_SPEC_SSB_DISABLE           3       /* Speculative Store Bypass disabled */
 #define PFA_SPEC_SSB_FORCE_DISABLE     4       /* Speculative Store Bypass force disabled*/
+#define PFA_SPEC_IB_DISABLE            5       /* Indirect branch speculation restricted */
+#define PFA_SPEC_IB_FORCE_DISABLE      6       /* Indirect branch speculation permanently restricted */
 
 #define TASK_PFA_TEST(name, func)                                      \
        static inline bool task_##func(struct task_struct *p)           \
@@ -1484,6 +1487,13 @@ TASK_PFA_CLEAR(SPEC_SSB_DISABLE, spec_ssb_disable)
 TASK_PFA_TEST(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable)
 TASK_PFA_SET(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable)
 
+TASK_PFA_TEST(SPEC_IB_DISABLE, spec_ib_disable)
+TASK_PFA_SET(SPEC_IB_DISABLE, spec_ib_disable)
+TASK_PFA_CLEAR(SPEC_IB_DISABLE, spec_ib_disable)
+
+TASK_PFA_TEST(SPEC_IB_FORCE_DISABLE, spec_ib_force_disable)
+TASK_PFA_SET(SPEC_IB_FORCE_DISABLE, spec_ib_force_disable)
+
 static inline void
 current_restore_flags(unsigned long orig_flags, unsigned long flags)
 {
diff --git a/include/linux/sched/smt.h b/include/linux/sched/smt.h
new file mode 100644 (file)
index 0000000..59d3736
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_SCHED_SMT_H
+#define _LINUX_SCHED_SMT_H
+
+#include <linux/static_key.h>
+
+#ifdef CONFIG_SCHED_SMT
+extern struct static_key_false sched_smt_present;
+
+static __always_inline bool sched_smt_active(void)
+{
+       return static_branch_likely(&sched_smt_present);
+}
+#else
+static inline bool sched_smt_active(void) { return false; }
+#endif
+
+void arch_smt_update(void);
+
+#endif
index 43106ff..2ec1280 100644 (file)
@@ -72,7 +72,6 @@ xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)
        buf->head[0].iov_base = start;
        buf->head[0].iov_len = len;
        buf->tail[0].iov_len = 0;
-       buf->bvec = NULL;
        buf->pages = NULL;
        buf->page_len = 0;
        buf->flags = 0;
index 40b0b4c..df20f8b 100644 (file)
@@ -83,8 +83,8 @@ static inline int ptrace_report_syscall(struct pt_regs *regs)
  * tracehook_report_syscall_entry - task is about to attempt a system call
  * @regs:              user register state of current task
  *
- * This will be called if %TIF_SYSCALL_TRACE has been set, when the
- * current task has just entered the kernel for a system call.
+ * This will be called if %TIF_SYSCALL_TRACE or %TIF_SYSCALL_EMU have been set,
+ * when the current task has just entered the kernel for a system call.
  * Full user register state is available here.  Changing the values
  * in @regs can affect the system call number and arguments to be tried.
  * It is safe to block here, preventing the system call from beginning.
index 538ba1a..e9de8ad 100644 (file)
@@ -166,7 +166,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
                struct tracepoint_func *it_func_ptr;                    \
                void *it_func;                                          \
                void *__data;                                           \
-               int __maybe_unused idx = 0;                             \
+               int __maybe_unused __idx = 0;                           \
                                                                        \
                if (!(cond))                                            \
                        return;                                         \
@@ -182,7 +182,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
                 * doesn't work from the idle path.                     \
                 */                                                     \
                if (rcuidle) {                                          \
-                       idx = srcu_read_lock_notrace(&tracepoint_srcu); \
+                       __idx = srcu_read_lock_notrace(&tracepoint_srcu);\
                        rcu_irq_enter_irqson();                         \
                }                                                       \
                                                                        \
@@ -198,7 +198,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
                                                                        \
                if (rcuidle) {                                          \
                        rcu_irq_exit_irqson();                          \
-                       srcu_read_unlock_notrace(&tracepoint_srcu, idx);\
+                       srcu_read_unlock_notrace(&tracepoint_srcu, __idx);\
                }                                                       \
                                                                        \
                preempt_enable_notrace();                               \
index 414db2b..392138f 100644 (file)
@@ -556,6 +556,7 @@ extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
 extern void tty_release_struct(struct tty_struct *tty, int idx);
 extern int tty_release(struct inode *inode, struct file *filp);
 extern void tty_init_termios(struct tty_struct *tty);
+extern void tty_save_termios(struct tty_struct *tty);
 extern int tty_standard_install(struct tty_driver *driver,
                struct tty_struct *tty);
 
index 4cdd515..5e49e82 100644 (file)
@@ -407,11 +407,11 @@ struct usb_host_bos {
 };
 
 int __usb_get_extra_descriptor(char *buffer, unsigned size,
-       unsigned char type, void **ptr);
+       unsigned char type, void **ptr, size_t min);
 #define usb_get_extra_descriptor(ifpoint, type, ptr) \
                                __usb_get_extra_descriptor((ifpoint)->extra, \
                                (ifpoint)->extralen, \
-                               type, (void **)ptr)
+                               type, (void **)ptr, sizeof(**(ptr)))
 
 /* ----------------------------------------------------------------------- */
 
index 0ce75c3..bd36d74 100644 (file)
@@ -68,7 +68,7 @@ struct media_request {
        unsigned int access_count;
        struct list_head objects;
        unsigned int num_incomplete_objects;
-       struct wait_queue_head poll_wait;
+       wait_queue_head_t poll_wait;
        spinlock_t lock;
 };
 
index 2dd37ca..888a833 100644 (file)
@@ -254,11 +254,13 @@ static inline int snd_interval_empty(const struct snd_interval *i)
 static inline int snd_interval_single(const struct snd_interval *i)
 {
        return (i->min == i->max || 
-               (i->min + 1 == i->max && i->openmax));
+               (i->min + 1 == i->max && (i->openmin || i->openmax)));
 }
 
 static inline int snd_interval_value(const struct snd_interval *i)
 {
+       if (i->openmin && !i->openmax)
+               return i->max;
        return i->min;
 }
 
index f1dab1f..70c10a8 100644 (file)
@@ -1192,7 +1192,7 @@ struct snd_soc_pcm_runtime {
             ((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \
             (i)++)
 #define for_each_rtd_codec_dai_rollback(rtd, i, dai)           \
-       for (; ((i--) >= 0) && ((dai) = rtd->codec_dais[i]);)
+       for (; ((--i) >= 0) && ((dai) = rtd->codec_dais[i]);)
 
 
 /* mixer control */
index f07b270..9a4bdfa 100644 (file)
@@ -107,6 +107,8 @@ DEFINE_EVENT(sched_wakeup_template, sched_wakeup_new,
 #ifdef CREATE_TRACE_POINTS
 static inline long __trace_sched_switch_state(bool preempt, struct task_struct *p)
 {
+       unsigned int state;
+
 #ifdef CONFIG_SCHED_DEBUG
        BUG_ON(p != current);
 #endif /* CONFIG_SCHED_DEBUG */
@@ -118,7 +120,15 @@ static inline long __trace_sched_switch_state(bool preempt, struct task_struct *
        if (preempt)
                return TASK_REPORT_MAX;
 
-       return 1 << task_state_index(p);
+       /*
+        * task_state_index() uses fls() and returns a value from 0-8 range.
+        * Decrement it by 1 (except TASK_RUNNING state i.e 0) before using
+        * it for left shift operation to get the correct task->state
+        * mapping.
+        */
+       state = task_state_index(p);
+
+       return state ? (1 << (state - 1)) : state;
 }
 #endif /* CREATE_TRACE_POINTS */
 
index 538546e..c7f3321 100644 (file)
@@ -760,8 +760,10 @@ __SYSCALL(__NR_rseq, sys_rseq)
 #define __NR_ftruncate __NR3264_ftruncate
 #define __NR_lseek __NR3264_lseek
 #define __NR_sendfile __NR3264_sendfile
+#if defined(__ARCH_WANT_NEW_STAT) || defined(__ARCH_WANT_STAT64)
 #define __NR_newfstatat __NR3264_fstatat
 #define __NR_fstat __NR3264_fstat
+#endif
 #define __NR_mmap __NR3264_mmap
 #define __NR_fadvise64 __NR3264_fadvise64
 #ifdef __NR3264_stat
@@ -776,8 +778,10 @@ __SYSCALL(__NR_rseq, sys_rseq)
 #define __NR_ftruncate64 __NR3264_ftruncate
 #define __NR_llseek __NR3264_lseek
 #define __NR_sendfile64 __NR3264_sendfile
+#if defined(__ARCH_WANT_NEW_STAT) || defined(__ARCH_WANT_STAT64)
 #define __NR_fstatat64 __NR3264_fstatat
 #define __NR_fstat64 __NR3264_fstat
+#endif
 #define __NR_mmap2 __NR3264_mmap
 #define __NR_fadvise64_64 __NR3264_fadvise64
 #ifdef __NR3264_stat
index c0d7ea0..b17201e 100644 (file)
@@ -212,6 +212,7 @@ struct prctl_mm_map {
 #define PR_SET_SPECULATION_CTRL                53
 /* Speculation control variants */
 # define PR_SPEC_STORE_BYPASS          0
+# define PR_SPEC_INDIRECT_BRANCH       1
 /* Return and control values for PR_SET/GET_SPECULATION_CTRL */
 # define PR_SPEC_NOT_AFFECTED          0
 # define PR_SPEC_PRCTL                 (1UL << 0)
index 61f410f..4914b93 100644 (file)
@@ -44,8 +44,3 @@ static inline void xen_balloon_init(void)
 {
 }
 #endif
-
-#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
-struct resource;
-void arch_xen_balloon_init(struct resource *hostmem_resource);
-#endif
index a4112e9..cf5b5a0 100644 (file)
@@ -509,6 +509,15 @@ config PSI
 
          Say N if unsure.
 
+config PSI_DEFAULT_DISABLED
+       bool "Require boot parameter to enable pressure stall information tracking"
+       default n
+       depends on PSI
+       help
+         If set, pressure stall information tracking will be disabled
+         per default but can be enabled through passing psi_enable=1
+         on the kernel commandline during boot.
+
 endmenu # "CPU/Task time and stats accounting"
 
 config CPU_ISOLATION
index 6405577..f6f4a1e 100644 (file)
@@ -291,16 +291,6 @@ static int __init do_reset(void)
        return 1;
 }
 
-static int __init maybe_link(void)
-{
-       if (nlink >= 2) {
-               char *old = find_link(major, minor, ino, mode, collected);
-               if (old)
-                       return (ksys_link(old, collected) < 0) ? -1 : 1;
-       }
-       return 0;
-}
-
 static void __init clean_path(char *path, umode_t fmode)
 {
        struct kstat st;
@@ -313,6 +303,18 @@ static void __init clean_path(char *path, umode_t fmode)
        }
 }
 
+static int __init maybe_link(void)
+{
+       if (nlink >= 2) {
+               char *old = find_link(major, minor, ino, mode, collected);
+               if (old) {
+                       clean_path(collected, 0);
+                       return (ksys_link(old, collected) < 0) ? -1 : 1;
+               }
+       }
+       return 0;
+}
+
 static __initdata int wfd;
 
 static int __init do_name(void)
index 3c7f3b4..91d5c38 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/sched/signal.h>
 #include <linux/sched/hotplug.h>
 #include <linux/sched/task.h>
+#include <linux/sched/smt.h>
 #include <linux/unistd.h>
 #include <linux/cpu.h>
 #include <linux/oom.h>
@@ -367,6 +368,12 @@ static void lockdep_release_cpus_lock(void)
 
 #endif /* CONFIG_HOTPLUG_CPU */
 
+/*
+ * Architectures that need SMT-specific errata handling during SMT hotplug
+ * should override this.
+ */
+void __weak arch_smt_update(void) { }
+
 #ifdef CONFIG_HOTPLUG_SMT
 enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED;
 EXPORT_SYMBOL_GPL(cpu_smt_control);
@@ -1011,6 +1018,7 @@ out:
         * concurrent CPU hotplug via cpu_add_remove_lock.
         */
        lockup_detector_cleanup();
+       arch_smt_update();
        return ret;
 }
 
@@ -1139,6 +1147,7 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen, enum cpuhp_state target)
        ret = cpuhp_up_callbacks(cpu, st, target);
 out:
        cpus_write_unlock();
+       arch_smt_update();
        return ret;
 }
 
@@ -2055,12 +2064,6 @@ static void cpuhp_online_cpu_device(unsigned int cpu)
        kobject_uevent(&dev->kobj, KOBJ_ONLINE);
 }
 
-/*
- * Architectures that need SMT-specific errata handling during SMT hotplug
- * should override this.
- */
-void __weak arch_smt_update(void) { };
-
 static int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
 {
        int cpu, ret = 0;
index 96d4bee..abbd8da 100644 (file)
@@ -572,7 +572,9 @@ static void put_uprobe(struct uprobe *uprobe)
                 * gets called, we don't get a chance to remove uprobe from
                 * delayed_uprobe_list from remove_breakpoint(). Do it here.
                 */
+               mutex_lock(&delayed_uprobe_lock);
                delayed_uprobe_remove(uprobe, NULL);
+               mutex_unlock(&delayed_uprobe_lock);
                kfree(uprobe);
        }
 }
@@ -829,7 +831,7 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
        BUG_ON((uprobe->offset & ~PAGE_MASK) +
                        UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
 
-       smp_wmb(); /* pairs with rmb() in find_active_uprobe() */
+       smp_wmb(); /* pairs with the smp_rmb() in handle_swbp() */
        set_bit(UPROBE_COPY_INSN, &uprobe->flags);
 
  out:
@@ -2178,10 +2180,18 @@ static void handle_swbp(struct pt_regs *regs)
         * After we hit the bp, _unregister + _register can install the
         * new and not-yet-analyzed uprobe at the same address, restart.
         */
-       smp_rmb(); /* pairs with wmb() in install_breakpoint() */
        if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
                goto out;
 
+       /*
+        * Pairs with the smp_wmb() in prepare_uprobe().
+        *
+        * Guarantees that if we see the UPROBE_COPY_INSN bit set, then
+        * we must also see the stores to &uprobe->arch performed by the
+        * prepare_uprobe() call.
+        */
+       smp_rmb();
+
        /* Tracing handlers use ->utask to communicate with fetch methods */
        if (!get_utask())
                goto out;
index 3ebd09e..97959d7 100644 (file)
@@ -56,7 +56,7 @@ struct kcov {
        struct task_struct      *t;
 };
 
-static bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t)
+static notrace bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t)
 {
        unsigned int mode;
 
@@ -78,7 +78,7 @@ static bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t)
        return mode == needed_mode;
 }
 
-static unsigned long canonicalize_ip(unsigned long ip)
+static notrace unsigned long canonicalize_ip(unsigned long ip)
 {
 #ifdef CONFIG_RANDOMIZE_BASE
        ip -= kaslr_offset();
index 80b34df..c2cee9d 100644 (file)
@@ -261,9 +261,6 @@ static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
 
 static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
 {
-       if (mode & PTRACE_MODE_SCHED)
-               return false;
-
        if (mode & PTRACE_MODE_NOAUDIT)
                return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE);
        else
@@ -331,16 +328,9 @@ ok:
             !ptrace_has_cap(mm->user_ns, mode)))
            return -EPERM;
 
-       if (mode & PTRACE_MODE_SCHED)
-               return 0;
        return security_ptrace_access_check(task, mode);
 }
 
-bool ptrace_may_access_sched(struct task_struct *task, unsigned int mode)
-{
-       return __ptrace_may_access(task, mode | PTRACE_MODE_SCHED);
-}
-
 bool ptrace_may_access(struct task_struct *task, unsigned int mode)
 {
        int err;
index 091e089..6fedf3a 100644 (file)
@@ -5738,15 +5738,10 @@ int sched_cpu_activate(unsigned int cpu)
 
 #ifdef CONFIG_SCHED_SMT
        /*
-        * The sched_smt_present static key needs to be evaluated on every
-        * hotplug event because at boot time SMT might be disabled when
-        * the number of booted CPUs is limited.
-        *
-        * If then later a sibling gets hotplugged, then the key would stay
-        * off and SMT scheduling would never be functional.
+        * When going up, increment the number of cores with SMT present.
         */
-       if (cpumask_weight(cpu_smt_mask(cpu)) > 1)
-               static_branch_enable_cpuslocked(&sched_smt_present);
+       if (cpumask_weight(cpu_smt_mask(cpu)) == 2)
+               static_branch_inc_cpuslocked(&sched_smt_present);
 #endif
        set_cpu_active(cpu, true);
 
@@ -5790,6 +5785,14 @@ int sched_cpu_deactivate(unsigned int cpu)
         */
        synchronize_rcu_mult(call_rcu, call_rcu_sched);
 
+#ifdef CONFIG_SCHED_SMT
+       /*
+        * When going down, decrement the number of cores with SMT present.
+        */
+       if (cpumask_weight(cpu_smt_mask(cpu)) == 2)
+               static_branch_dec_cpuslocked(&sched_smt_present);
+#endif
+
        if (!sched_smp_initialized)
                return 0;
 
index 3d7355d..fe24de3 100644 (file)
 
 static int psi_bug __read_mostly;
 
-bool psi_disabled __read_mostly;
-core_param(psi_disabled, psi_disabled, bool, 0644);
+DEFINE_STATIC_KEY_FALSE(psi_disabled);
+
+#ifdef CONFIG_PSI_DEFAULT_DISABLED
+bool psi_enable;
+#else
+bool psi_enable = true;
+#endif
+static int __init setup_psi(char *str)
+{
+       return kstrtobool(str, &psi_enable) == 0;
+}
+__setup("psi=", setup_psi);
 
 /* Running averages - we need to be higher-res than loadavg */
 #define PSI_FREQ       (2*HZ+1)        /* 2 sec intervals */
@@ -169,8 +179,10 @@ static void group_init(struct psi_group *group)
 
 void __init psi_init(void)
 {
-       if (psi_disabled)
+       if (!psi_enable) {
+               static_branch_enable(&psi_disabled);
                return;
+       }
 
        psi_period = jiffies_to_nsecs(PSI_FREQ);
        group_init(&psi_system);
@@ -549,7 +561,7 @@ void psi_memstall_enter(unsigned long *flags)
        struct rq_flags rf;
        struct rq *rq;
 
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
 
        *flags = current->flags & PF_MEMSTALL;
@@ -579,7 +591,7 @@ void psi_memstall_leave(unsigned long *flags)
        struct rq_flags rf;
        struct rq *rq;
 
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
 
        if (*flags)
@@ -600,7 +612,7 @@ void psi_memstall_leave(unsigned long *flags)
 #ifdef CONFIG_CGROUPS
 int psi_cgroup_alloc(struct cgroup *cgroup)
 {
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return 0;
 
        cgroup->psi.pcpu = alloc_percpu(struct psi_group_cpu);
@@ -612,7 +624,7 @@ int psi_cgroup_alloc(struct cgroup *cgroup)
 
 void psi_cgroup_free(struct cgroup *cgroup)
 {
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
 
        cancel_delayed_work_sync(&cgroup->psi.clock_work);
@@ -637,7 +649,7 @@ void cgroup_move_task(struct task_struct *task, struct css_set *to)
        struct rq_flags rf;
        struct rq *rq;
 
-       if (psi_disabled) {
+       if (static_branch_likely(&psi_disabled)) {
                /*
                 * Lame to do this here, but the scheduler cannot be locked
                 * from the outside, so we move cgroups from inside sched/.
@@ -673,7 +685,7 @@ int psi_show(struct seq_file *m, struct psi_group *group, enum psi_res res)
 {
        int full;
 
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return -EOPNOTSUPP;
 
        update_stats(group);
index 618577f..4e524ab 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/sched/prio.h>
 #include <linux/sched/rt.h>
 #include <linux/sched/signal.h>
+#include <linux/sched/smt.h>
 #include <linux/sched/stat.h>
 #include <linux/sched/sysctl.h>
 #include <linux/sched/task.h>
@@ -936,9 +937,6 @@ static inline int cpu_of(struct rq *rq)
 
 
 #ifdef CONFIG_SCHED_SMT
-
-extern struct static_key_false sched_smt_present;
-
 extern void __update_idle_core(struct rq *rq);
 
 static inline void update_idle_core(struct rq *rq)
index 4904c46..aa0de24 100644 (file)
@@ -66,7 +66,7 @@ static inline void psi_enqueue(struct task_struct *p, bool wakeup)
 {
        int clear = 0, set = TSK_RUNNING;
 
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
 
        if (!wakeup || p->sched_psi_wake_requeue) {
@@ -86,7 +86,7 @@ static inline void psi_dequeue(struct task_struct *p, bool sleep)
 {
        int clear = TSK_RUNNING, set = 0;
 
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
 
        if (!sleep) {
@@ -102,7 +102,7 @@ static inline void psi_dequeue(struct task_struct *p, bool sleep)
 
 static inline void psi_ttwu_dequeue(struct task_struct *p)
 {
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
        /*
         * Is the task being migrated during a wakeup? Make sure to
@@ -128,7 +128,7 @@ static inline void psi_ttwu_dequeue(struct task_struct *p)
 
 static inline void psi_task_tick(struct rq *rq)
 {
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
 
        if (unlikely(rq->curr->flags & PF_MEMSTALL))
index e428929..b193a59 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/stackleak.h>
+#include <linux/kprobes.h>
 
 #ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
 #include <linux/jump_label.h>
@@ -47,7 +48,7 @@ int stack_erasing_sysctl(struct ctl_table *table, int write,
 #define skip_erasing() false
 #endif /* CONFIG_STACKLEAK_RUNTIME_DISABLE */
 
-asmlinkage void stackleak_erase(void)
+asmlinkage void notrace stackleak_erase(void)
 {
        /* It would be nice not to have 'kstack_ptr' and 'boundary' on stack */
        unsigned long kstack_ptr = current->lowest_stack;
@@ -101,8 +102,9 @@ asmlinkage void stackleak_erase(void)
        /* Reset the 'lowest_stack' value for the next syscall */
        current->lowest_stack = current_top_of_stack() - THREAD_SIZE/64;
 }
+NOKPROBE_SYMBOL(stackleak_erase);
 
-void __used stackleak_track_stack(void)
+void __used notrace stackleak_track_stack(void)
 {
        /*
         * N.B. stackleak_erase() fills the kernel stack with the poison value,
index f536f60..7773445 100644 (file)
@@ -817,7 +817,7 @@ function_profile_call(unsigned long ip, unsigned long parent_ip,
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 static int profile_graph_entry(struct ftrace_graph_ent *trace)
 {
-       int index = trace->depth;
+       int index = current->curr_ret_stack;
 
        function_profile_call(trace->func, 0, NULL, NULL);
 
@@ -852,7 +852,7 @@ static void profile_graph_return(struct ftrace_graph_ret *trace)
        if (!fgraph_graph_time) {
                int index;
 
-               index = trace->depth;
+               index = current->curr_ret_stack;
 
                /* Append this call time to the parent time to subtract */
                if (index)
@@ -6814,6 +6814,7 @@ static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
                        atomic_set(&t->tracing_graph_pause, 0);
                        atomic_set(&t->trace_overrun, 0);
                        t->curr_ret_stack = -1;
+                       t->curr_ret_depth = -1;
                        /* Make sure the tasks see the -1 first: */
                        smp_wmb();
                        t->ret_stack = ret_stack_list[start++];
@@ -7038,6 +7039,7 @@ graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack)
 void ftrace_graph_init_idle_task(struct task_struct *t, int cpu)
 {
        t->curr_ret_stack = -1;
+       t->curr_ret_depth = -1;
        /*
         * The idle task has no parent, it either has its own
         * stack or no stack at all.
@@ -7068,6 +7070,7 @@ void ftrace_graph_init_task(struct task_struct *t)
        /* Make sure we do not use the parent ret_stack */
        t->ret_stack = NULL;
        t->curr_ret_stack = -1;
+       t->curr_ret_depth = -1;
 
        if (ftrace_graph_active) {
                struct ftrace_ret_stack *ret_stack;
index 3b8c0e2..447bd96 100644 (file)
@@ -512,12 +512,44 @@ enum {
  * can only be modified by current, we can reuse trace_recursion.
  */
        TRACE_IRQ_BIT,
+
+       /* Set if the function is in the set_graph_function file */
+       TRACE_GRAPH_BIT,
+
+       /*
+        * In the very unlikely case that an interrupt came in
+        * at a start of graph tracing, and we want to trace
+        * the function in that interrupt, the depth can be greater
+        * than zero, because of the preempted start of a previous
+        * trace. In an even more unlikely case, depth could be 2
+        * if a softirq interrupted the start of graph tracing,
+        * followed by an interrupt preempting a start of graph
+        * tracing in the softirq, and depth can even be 3
+        * if an NMI came in at the start of an interrupt function
+        * that preempted a softirq start of a function that
+        * preempted normal context!!!! Luckily, it can't be
+        * greater than 3, so the next two bits are a mask
+        * of what the depth is when we set TRACE_GRAPH_BIT
+        */
+
+       TRACE_GRAPH_DEPTH_START_BIT,
+       TRACE_GRAPH_DEPTH_END_BIT,
 };
 
 #define trace_recursion_set(bit)       do { (current)->trace_recursion |= (1<<(bit)); } while (0)
 #define trace_recursion_clear(bit)     do { (current)->trace_recursion &= ~(1<<(bit)); } while (0)
 #define trace_recursion_test(bit)      ((current)->trace_recursion & (1<<(bit)))
 
+#define trace_recursion_depth() \
+       (((current)->trace_recursion >> TRACE_GRAPH_DEPTH_START_BIT) & 3)
+#define trace_recursion_set_depth(depth) \
+       do {                                                            \
+               current->trace_recursion &=                             \
+                       ~(3 << TRACE_GRAPH_DEPTH_START_BIT);            \
+               current->trace_recursion |=                             \
+                       ((depth) & 3) << TRACE_GRAPH_DEPTH_START_BIT;   \
+       } while (0)
+
 #define TRACE_CONTEXT_BITS     4
 
 #define TRACE_FTRACE_START     TRACE_FTRACE_BIT
@@ -843,8 +875,9 @@ extern void __trace_graph_return(struct trace_array *tr,
 extern struct ftrace_hash *ftrace_graph_hash;
 extern struct ftrace_hash *ftrace_graph_notrace_hash;
 
-static inline int ftrace_graph_addr(unsigned long addr)
+static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace)
 {
+       unsigned long addr = trace->func;
        int ret = 0;
 
        preempt_disable_notrace();
@@ -855,6 +888,14 @@ static inline int ftrace_graph_addr(unsigned long addr)
        }
 
        if (ftrace_lookup_ip(ftrace_graph_hash, addr)) {
+
+               /*
+                * This needs to be cleared on the return functions
+                * when the depth is zero.
+                */
+               trace_recursion_set(TRACE_GRAPH_BIT);
+               trace_recursion_set_depth(trace->depth);
+
                /*
                 * If no irqs are to be traced, but a set_graph_function
                 * is set, and called by an interrupt handler, we still
@@ -872,6 +913,13 @@ out:
        return ret;
 }
 
+static inline void ftrace_graph_addr_finish(struct ftrace_graph_ret *trace)
+{
+       if (trace_recursion_test(TRACE_GRAPH_BIT) &&
+           trace->depth == trace_recursion_depth())
+               trace_recursion_clear(TRACE_GRAPH_BIT);
+}
+
 static inline int ftrace_graph_notrace_addr(unsigned long addr)
 {
        int ret = 0;
@@ -885,7 +933,7 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr)
        return ret;
 }
 #else
-static inline int ftrace_graph_addr(unsigned long addr)
+static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace)
 {
        return 1;
 }
@@ -894,6 +942,8 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr)
 {
        return 0;
 }
+static inline void ftrace_graph_addr_finish(struct ftrace_graph_ret *trace)
+{ }
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
 extern unsigned int fgraph_max_depth;
@@ -901,7 +951,8 @@ extern unsigned int fgraph_max_depth;
 static inline bool ftrace_graph_ignore_func(struct ftrace_graph_ent *trace)
 {
        /* trace it when it is-nested-in or is a function enabled. */
-       return !(trace->depth || ftrace_graph_addr(trace->func)) ||
+       return !(trace_recursion_test(TRACE_GRAPH_BIT) ||
+                ftrace_graph_addr(trace)) ||
                (trace->depth < 0) ||
                (fgraph_max_depth && trace->depth >= fgraph_max_depth);
 }
index 169b3c4..086af4f 100644 (file)
@@ -118,8 +118,8 @@ print_graph_duration(struct trace_array *tr, unsigned long long duration,
                     struct trace_seq *s, u32 flags);
 
 /* Add a function return address to the trace stack on thread info.*/
-int
-ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
+static int
+ftrace_push_return_trace(unsigned long ret, unsigned long func,
                         unsigned long frame_pointer, unsigned long *retp)
 {
        unsigned long long calltime;
@@ -177,9 +177,31 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
 #ifdef HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
        current->ret_stack[index].retp = retp;
 #endif
-       *depth = current->curr_ret_stack;
+       return 0;
+}
+
+int function_graph_enter(unsigned long ret, unsigned long func,
+                        unsigned long frame_pointer, unsigned long *retp)
+{
+       struct ftrace_graph_ent trace;
+
+       trace.func = func;
+       trace.depth = ++current->curr_ret_depth;
+
+       if (ftrace_push_return_trace(ret, func,
+                                    frame_pointer, retp))
+               goto out;
+
+       /* Only trace if the calling function expects to */
+       if (!ftrace_graph_entry(&trace))
+               goto out_ret;
 
        return 0;
+ out_ret:
+       current->curr_ret_stack--;
+ out:
+       current->curr_ret_depth--;
+       return -EBUSY;
 }
 
 /* Retrieve a function return address to the trace stack on thread info.*/
@@ -241,7 +263,13 @@ ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret,
        trace->func = current->ret_stack[index].func;
        trace->calltime = current->ret_stack[index].calltime;
        trace->overrun = atomic_read(&current->trace_overrun);
-       trace->depth = index;
+       trace->depth = current->curr_ret_depth--;
+       /*
+        * We still want to trace interrupts coming in if
+        * max_depth is set to 1. Make sure the decrement is
+        * seen before ftrace_graph_return.
+        */
+       barrier();
 }
 
 /*
@@ -255,6 +283,12 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
 
        ftrace_pop_return_trace(&trace, &ret, frame_pointer);
        trace.rettime = trace_clock_local();
+       ftrace_graph_return(&trace);
+       /*
+        * The ftrace_graph_return() may still access the current
+        * ret_stack structure, we need to make sure the update of
+        * curr_ret_stack is after that.
+        */
        barrier();
        current->curr_ret_stack--;
        /*
@@ -267,13 +301,6 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
                return ret;
        }
 
-       /*
-        * The trace should run after decrementing the ret counter
-        * in case an interrupt were to come in. We don't want to
-        * lose the interrupt if max_depth is set.
-        */
-       ftrace_graph_return(&trace);
-
        if (unlikely(!ret)) {
                ftrace_graph_stop();
                WARN_ON(1);
@@ -482,6 +509,8 @@ void trace_graph_return(struct ftrace_graph_ret *trace)
        int cpu;
        int pc;
 
+       ftrace_graph_addr_finish(trace);
+
        local_irq_save(flags);
        cpu = raw_smp_processor_id();
        data = per_cpu_ptr(tr->trace_buffer.data, cpu);
@@ -505,6 +534,8 @@ void set_graph_array(struct trace_array *tr)
 
 static void trace_graph_thresh_return(struct ftrace_graph_ret *trace)
 {
+       ftrace_graph_addr_finish(trace);
+
        if (tracing_thresh &&
            (trace->rettime - trace->calltime < tracing_thresh))
                return;
index b7357f9..98ea6d2 100644 (file)
@@ -208,6 +208,8 @@ static void irqsoff_graph_return(struct ftrace_graph_ret *trace)
        unsigned long flags;
        int pc;
 
+       ftrace_graph_addr_finish(trace);
+
        if (!func_prolog_dec(tr, &data, &flags))
                return;
 
index a86b303..7d04b98 100644 (file)
@@ -270,6 +270,8 @@ static void wakeup_graph_return(struct ftrace_graph_ret *trace)
        unsigned long flags;
        int pc;
 
+       ftrace_graph_addr_finish(trace);
+
        if (!func_prolog_preempt_disable(tr, &data, &pc))
                return;
 
index 70935ed..14afeeb 100644 (file)
@@ -135,7 +135,6 @@ static void fill_pool(void)
                if (!new)
                        return;
 
-               kmemleak_ignore(new);
                raw_spin_lock_irqsave(&pool_lock, flags);
                hlist_add_head(&new->node, &obj_pool);
                debug_objects_allocated++;
@@ -1128,7 +1127,6 @@ static int __init debug_objects_replace_static_objects(void)
                obj = kmem_cache_zalloc(obj_cache, GFP_KERNEL);
                if (!obj)
                        goto free;
-               kmemleak_ignore(obj);
                hlist_add_head(&obj->node, &objects);
        }
 
@@ -1184,7 +1182,8 @@ void __init debug_objects_mem_init(void)
 
        obj_cache = kmem_cache_create("debug_objects_cache",
                                      sizeof (struct debug_obj), 0,
-                                     SLAB_DEBUG_OBJECTS, NULL);
+                                     SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE,
+                                     NULL);
 
        if (!obj_cache || debug_objects_replace_static_objects()) {
                debug_objects_enabled = 0;
index 7ebccb5..54c2485 100644 (file)
@@ -560,6 +560,38 @@ static size_t copy_pipe_to_iter(const void *addr, size_t bytes,
        return bytes;
 }
 
+static size_t csum_and_copy_to_pipe_iter(const void *addr, size_t bytes,
+                               __wsum *csum, struct iov_iter *i)
+{
+       struct pipe_inode_info *pipe = i->pipe;
+       size_t n, r;
+       size_t off = 0;
+       __wsum sum = *csum, next;
+       int idx;
+
+       if (!sanity(i))
+               return 0;
+
+       bytes = n = push_pipe(i, bytes, &idx, &r);
+       if (unlikely(!n))
+               return 0;
+       for ( ; n; idx = next_idx(idx, pipe), r = 0) {
+               size_t chunk = min_t(size_t, n, PAGE_SIZE - r);
+               char *p = kmap_atomic(pipe->bufs[idx].page);
+               next = csum_partial_copy_nocheck(addr, p + r, chunk, 0);
+               sum = csum_block_add(sum, next, off);
+               kunmap_atomic(p);
+               i->idx = idx;
+               i->iov_offset = r + chunk;
+               n -= chunk;
+               off += chunk;
+               addr += chunk;
+       }
+       i->count -= bytes;
+       *csum = sum;
+       return bytes;
+}
+
 size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
 {
        const char *from = addr;
@@ -1438,8 +1470,12 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum,
        const char *from = addr;
        __wsum sum, next;
        size_t off = 0;
+
+       if (unlikely(iov_iter_is_pipe(i)))
+               return csum_and_copy_to_pipe_iter(addr, bytes, csum, i);
+
        sum = *csum;
-       if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) {
+       if (unlikely(iov_iter_is_discard(i))) {
                WARN_ON(1);     /* for now */
                return 0;
        }
index 626f580..5144899 100644 (file)
@@ -99,7 +99,7 @@ static void __init test_hexdump_prepare_test(size_t len, int rowsize,
                const char *q = *result++;
                size_t amount = strlen(q);
 
-               strncpy(p, q, amount);
+               memcpy(p, q, amount);
                p += amount;
 
                *p++ = ' ';
index e3ddd83..d82d022 100644 (file)
@@ -1214,7 +1214,6 @@ void unregister_test_dev_kmod(struct kmod_test_device *test_dev)
 
        dev_info(test_dev->dev, "removing interface\n");
        misc_deregister(&test_dev->misc_dev);
-       kfree(&test_dev->misc_dev.name);
 
        mutex_unlock(&test_dev->config_mutex);
        mutex_unlock(&test_dev->trigger_mutex);
index aa43620..8cb68a5 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -702,12 +702,11 @@ static long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                if (!vma || start >= vma->vm_end) {
                        vma = find_extend_vma(mm, start);
                        if (!vma && in_gate_area(mm, start)) {
-                               int ret;
                                ret = get_gate_page(mm, start & PAGE_MASK,
                                                gup_flags, &vma,
                                                pages ? &pages[i] : NULL);
                                if (ret)
-                                       return i ? : ret;
+                                       goto out;
                                ctx.page_mask = 0;
                                goto next_page;
                        }
index 55478ab..5da55b3 100644 (file)
@@ -629,40 +629,30 @@ release:
  *         available
  * never: never stall for any thp allocation
  */
-static inline gfp_t alloc_hugepage_direct_gfpmask(struct vm_area_struct *vma, unsigned long addr)
+static inline gfp_t alloc_hugepage_direct_gfpmask(struct vm_area_struct *vma)
 {
        const bool vma_madvised = !!(vma->vm_flags & VM_HUGEPAGE);
-       gfp_t this_node = 0;
-
-#ifdef CONFIG_NUMA
-       struct mempolicy *pol;
-       /*
-        * __GFP_THISNODE is used only when __GFP_DIRECT_RECLAIM is not
-        * specified, to express a general desire to stay on the current
-        * node for optimistic allocation attempts. If the defrag mode
-        * and/or madvise hint requires the direct reclaim then we prefer
-        * to fallback to other node rather than node reclaim because that
-        * can lead to excessive reclaim even though there is free memory
-        * on other nodes. We expect that NUMA preferences are specified
-        * by memory policies.
-        */
-       pol = get_vma_policy(vma, addr);
-       if (pol->mode != MPOL_BIND)
-               this_node = __GFP_THISNODE;
-       mpol_cond_put(pol);
-#endif
 
+       /* Always do synchronous compaction */
        if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags))
                return GFP_TRANSHUGE | (vma_madvised ? 0 : __GFP_NORETRY);
+
+       /* Kick kcompactd and fail quickly */
        if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags))
-               return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM | this_node;
+               return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM;
+
+       /* Synchronous compaction if madvised, otherwise kick kcompactd */
        if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags))
-               return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
-                                                            __GFP_KSWAPD_RECLAIM | this_node);
+               return GFP_TRANSHUGE_LIGHT |
+                       (vma_madvised ? __GFP_DIRECT_RECLAIM :
+                                       __GFP_KSWAPD_RECLAIM);
+
+       /* Only do synchronous compaction if madvised */
        if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags))
-               return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM :
-                                                            this_node);
-       return GFP_TRANSHUGE_LIGHT | this_node;
+               return GFP_TRANSHUGE_LIGHT |
+                      (vma_madvised ? __GFP_DIRECT_RECLAIM : 0);
+
+       return GFP_TRANSHUGE_LIGHT;
 }
 
 /* Caller must hold page table lock. */
@@ -734,8 +724,8 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf)
                        pte_free(vma->vm_mm, pgtable);
                return ret;
        }
-       gfp = alloc_hugepage_direct_gfpmask(vma, haddr);
-       page = alloc_pages_vma(gfp, HPAGE_PMD_ORDER, vma, haddr, numa_node_id());
+       gfp = alloc_hugepage_direct_gfpmask(vma);
+       page = alloc_hugepage_vma(gfp, vma, haddr, HPAGE_PMD_ORDER);
        if (unlikely(!page)) {
                count_vm_event(THP_FAULT_FALLBACK);
                return VM_FAULT_FALLBACK;
@@ -1305,9 +1295,8 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd)
 alloc:
        if (transparent_hugepage_enabled(vma) &&
            !transparent_hugepage_debug_cow()) {
-               huge_gfp = alloc_hugepage_direct_gfpmask(vma, haddr);
-               new_page = alloc_pages_vma(huge_gfp, HPAGE_PMD_ORDER, vma,
-                               haddr, numa_node_id());
+               huge_gfp = alloc_hugepage_direct_gfpmask(vma);
+               new_page = alloc_hugepage_vma(huge_gfp, vma, haddr, HPAGE_PMD_ORDER);
        } else
                new_page = NULL;
 
@@ -2350,7 +2339,7 @@ void vma_adjust_trans_huge(struct vm_area_struct *vma,
        }
 }
 
-static void freeze_page(struct page *page)
+static void unmap_page(struct page *page)
 {
        enum ttu_flags ttu_flags = TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS |
                TTU_RMAP_LOCKED | TTU_SPLIT_HUGE_PMD;
@@ -2365,7 +2354,7 @@ static void freeze_page(struct page *page)
        VM_BUG_ON_PAGE(!unmap_success, page);
 }
 
-static void unfreeze_page(struct page *page)
+static void remap_page(struct page *page)
 {
        int i;
        if (PageTransHuge(page)) {
@@ -2402,6 +2391,12 @@ static void __split_huge_page_tail(struct page *head, int tail,
                         (1L << PG_unevictable) |
                         (1L << PG_dirty)));
 
+       /* ->mapping in first tail page is compound_mapcount */
+       VM_BUG_ON_PAGE(tail > 2 && page_tail->mapping != TAIL_MAPPING,
+                       page_tail);
+       page_tail->mapping = head->mapping;
+       page_tail->index = head->index + tail;
+
        /* Page flags must be visible before we make the page non-compound. */
        smp_wmb();
 
@@ -2422,12 +2417,6 @@ static void __split_huge_page_tail(struct page *head, int tail,
        if (page_is_idle(head))
                set_page_idle(page_tail);
 
-       /* ->mapping in first tail page is compound_mapcount */
-       VM_BUG_ON_PAGE(tail > 2 && page_tail->mapping != TAIL_MAPPING,
-                       page_tail);
-       page_tail->mapping = head->mapping;
-
-       page_tail->index = head->index + tail;
        page_cpupid_xchg_last(page_tail, page_cpupid_last(head));
 
        /*
@@ -2439,12 +2428,11 @@ static void __split_huge_page_tail(struct page *head, int tail,
 }
 
 static void __split_huge_page(struct page *page, struct list_head *list,
-               unsigned long flags)
+               pgoff_t end, unsigned long flags)
 {
        struct page *head = compound_head(page);
        struct zone *zone = page_zone(head);
        struct lruvec *lruvec;
-       pgoff_t end = -1;
        int i;
 
        lruvec = mem_cgroup_page_lruvec(head, zone->zone_pgdat);
@@ -2452,9 +2440,6 @@ static void __split_huge_page(struct page *page, struct list_head *list,
        /* complete memcg works before add pages to LRU */
        mem_cgroup_split_huge_fixup(head);
 
-       if (!PageAnon(page))
-               end = DIV_ROUND_UP(i_size_read(head->mapping->host), PAGE_SIZE);
-
        for (i = HPAGE_PMD_NR - 1; i >= 1; i--) {
                __split_huge_page_tail(head, i, lruvec, list);
                /* Some pages can be beyond i_size: drop them from page cache */
@@ -2483,7 +2468,7 @@ static void __split_huge_page(struct page *page, struct list_head *list,
 
        spin_unlock_irqrestore(zone_lru_lock(page_zone(head)), flags);
 
-       unfreeze_page(head);
+       remap_page(head);
 
        for (i = 0; i < HPAGE_PMD_NR; i++) {
                struct page *subpage = head + i;
@@ -2626,6 +2611,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
        int count, mapcount, extra_pins, ret;
        bool mlocked;
        unsigned long flags;
+       pgoff_t end;
 
        VM_BUG_ON_PAGE(is_huge_zero_page(page), page);
        VM_BUG_ON_PAGE(!PageLocked(page), page);
@@ -2648,6 +2634,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
                        ret = -EBUSY;
                        goto out;
                }
+               end = -1;
                mapping = NULL;
                anon_vma_lock_write(anon_vma);
        } else {
@@ -2661,10 +2648,19 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
 
                anon_vma = NULL;
                i_mmap_lock_read(mapping);
+
+               /*
+                *__split_huge_page() may need to trim off pages beyond EOF:
+                * but on 32-bit, i_size_read() takes an irq-unsafe seqlock,
+                * which cannot be nested inside the page tree lock. So note
+                * end now: i_size itself may be changed at any moment, but
+                * head page lock is good enough to serialize the trimming.
+                */
+               end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE);
        }
 
        /*
-        * Racy check if we can split the page, before freeze_page() will
+        * Racy check if we can split the page, before unmap_page() will
         * split PMDs
         */
        if (!can_split_huge_page(head, &extra_pins)) {
@@ -2673,7 +2669,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
        }
 
        mlocked = PageMlocked(page);
-       freeze_page(head);
+       unmap_page(head);
        VM_BUG_ON_PAGE(compound_mapcount(head), head);
 
        /* Make sure the page is not on per-CPU pagevec as it takes pin */
@@ -2707,7 +2703,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
                if (mapping)
                        __dec_node_page_state(page, NR_SHMEM_THPS);
                spin_unlock(&pgdata->split_queue_lock);
-               __split_huge_page(page, list, flags);
+               __split_huge_page(page, list, end, flags);
                if (PageSwapCache(head)) {
                        swp_entry_t entry = { .val = page_private(head) };
 
@@ -2727,7 +2723,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
 fail:          if (mapping)
                        xa_unlock(&mapping->i_pages);
                spin_unlock_irqrestore(zone_lru_lock(page_zone(head)), flags);
-               unfreeze_page(head);
+               remap_page(head);
                ret = -EBUSY;
        }
 
index 7f2a28a..705a3e9 100644 (file)
@@ -4080,7 +4080,7 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm,
 
                /* fallback to copy_from_user outside mmap_sem */
                if (unlikely(ret)) {
-                       ret = -EFAULT;
+                       ret = -ENOENT;
                        *pagep = page;
                        /* don't free the page */
                        goto out;
index c13625c..8e2ff19 100644 (file)
@@ -1287,7 +1287,7 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
  * collapse_shmem - collapse small tmpfs/shmem pages into huge one.
  *
  * Basic scheme is simple, details are more complex:
- *  - allocate and freeze a new huge page;
+ *  - allocate and lock a new huge page;
  *  - scan page cache replacing old pages with the new one
  *    + swap in pages if necessary;
  *    + fill in gaps;
@@ -1295,11 +1295,11 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
  *  - if replacing succeeds:
  *    + copy data over;
  *    + free old pages;
- *    + unfreeze huge page;
+ *    + unlock huge page;
  *  - if replacing failed;
  *    + put all pages back and unfreeze them;
  *    + restore gaps in the page cache;
- *    + free huge page;
+ *    + unlock and free huge page;
  */
 static void collapse_shmem(struct mm_struct *mm,
                struct address_space *mapping, pgoff_t start,
@@ -1329,19 +1329,6 @@ static void collapse_shmem(struct mm_struct *mm,
                goto out;
        }
 
-       new_page->index = start;
-       new_page->mapping = mapping;
-       __SetPageSwapBacked(new_page);
-       __SetPageLocked(new_page);
-       BUG_ON(!page_ref_freeze(new_page, 1));
-
-       /*
-        * At this point the new_page is 'frozen' (page_count() is zero),
-        * locked and not up-to-date. It's safe to insert it into the page
-        * cache, because nobody would be able to map it or use it in other
-        * way until we unfreeze it.
-        */
-
        /* This will be less messy when we use multi-index entries */
        do {
                xas_lock_irq(&xas);
@@ -1349,19 +1336,44 @@ static void collapse_shmem(struct mm_struct *mm,
                if (!xas_error(&xas))
                        break;
                xas_unlock_irq(&xas);
-               if (!xas_nomem(&xas, GFP_KERNEL))
+               if (!xas_nomem(&xas, GFP_KERNEL)) {
+                       mem_cgroup_cancel_charge(new_page, memcg, true);
+                       result = SCAN_FAIL;
                        goto out;
+               }
        } while (1);
 
+       __SetPageLocked(new_page);
+       __SetPageSwapBacked(new_page);
+       new_page->index = start;
+       new_page->mapping = mapping;
+
+       /*
+        * At this point the new_page is locked and not up-to-date.
+        * It's safe to insert it into the page cache, because nobody would
+        * be able to map it or use it in another way until we unlock it.
+        */
+
        xas_set(&xas, start);
        for (index = start; index < end; index++) {
                struct page *page = xas_next(&xas);
 
                VM_BUG_ON(index != xas.xa_index);
                if (!page) {
+                       /*
+                        * Stop if extent has been truncated or hole-punched,
+                        * and is now completely empty.
+                        */
+                       if (index == start) {
+                               if (!xas_next_entry(&xas, end - 1)) {
+                                       result = SCAN_TRUNCATED;
+                                       goto xa_locked;
+                               }
+                               xas_set(&xas, index);
+                       }
                        if (!shmem_charge(mapping->host, 1)) {
                                result = SCAN_FAIL;
-                               break;
+                               goto xa_locked;
                        }
                        xas_store(&xas, new_page + (index % HPAGE_PMD_NR));
                        nr_none++;
@@ -1376,13 +1388,12 @@ static void collapse_shmem(struct mm_struct *mm,
                                result = SCAN_FAIL;
                                goto xa_unlocked;
                        }
-                       xas_lock_irq(&xas);
-                       xas_set(&xas, index);
                } else if (trylock_page(page)) {
                        get_page(page);
+                       xas_unlock_irq(&xas);
                } else {
                        result = SCAN_PAGE_LOCK;
-                       break;
+                       goto xa_locked;
                }
 
                /*
@@ -1391,17 +1402,24 @@ static void collapse_shmem(struct mm_struct *mm,
                 */
                VM_BUG_ON_PAGE(!PageLocked(page), page);
                VM_BUG_ON_PAGE(!PageUptodate(page), page);
-               VM_BUG_ON_PAGE(PageTransCompound(page), page);
+
+               /*
+                * If file was truncated then extended, or hole-punched, before
+                * we locked the first page, then a THP might be there already.
+                */
+               if (PageTransCompound(page)) {
+                       result = SCAN_PAGE_COMPOUND;
+                       goto out_unlock;
+               }
 
                if (page_mapping(page) != mapping) {
                        result = SCAN_TRUNCATED;
                        goto out_unlock;
                }
-               xas_unlock_irq(&xas);
 
                if (isolate_lru_page(page)) {
                        result = SCAN_DEL_PAGE_LRU;
-                       goto out_isolate_failed;
+                       goto out_unlock;
                }
 
                if (page_mapped(page))
@@ -1421,7 +1439,9 @@ static void collapse_shmem(struct mm_struct *mm,
                 */
                if (!page_ref_freeze(page, 3)) {
                        result = SCAN_PAGE_COUNT;
-                       goto out_lru;
+                       xas_unlock_irq(&xas);
+                       putback_lru_page(page);
+                       goto out_unlock;
                }
 
                /*
@@ -1433,71 +1453,74 @@ static void collapse_shmem(struct mm_struct *mm,
                /* Finally, replace with the new page. */
                xas_store(&xas, new_page + (index % HPAGE_PMD_NR));
                continue;
-out_lru:
-               xas_unlock_irq(&xas);
-               putback_lru_page(page);
-out_isolate_failed:
-               unlock_page(page);
-               put_page(page);
-               goto xa_unlocked;
 out_unlock:
                unlock_page(page);
                put_page(page);
-               break;
+               goto xa_unlocked;
        }
-       xas_unlock_irq(&xas);
 
+       __inc_node_page_state(new_page, NR_SHMEM_THPS);
+       if (nr_none) {
+               struct zone *zone = page_zone(new_page);
+
+               __mod_node_page_state(zone->zone_pgdat, NR_FILE_PAGES, nr_none);
+               __mod_node_page_state(zone->zone_pgdat, NR_SHMEM, nr_none);
+       }
+
+xa_locked:
+       xas_unlock_irq(&xas);
 xa_unlocked:
+
        if (result == SCAN_SUCCEED) {
                struct page *page, *tmp;
-               struct zone *zone = page_zone(new_page);
 
                /*
                 * Replacing old pages with new one has succeeded, now we
                 * need to copy the content and free the old pages.
                 */
+               index = start;
                list_for_each_entry_safe(page, tmp, &pagelist, lru) {
+                       while (index < page->index) {
+                               clear_highpage(new_page + (index % HPAGE_PMD_NR));
+                               index++;
+                       }
                        copy_highpage(new_page + (page->index % HPAGE_PMD_NR),
                                        page);
                        list_del(&page->lru);
-                       unlock_page(page);
-                       page_ref_unfreeze(page, 1);
                        page->mapping = NULL;
+                       page_ref_unfreeze(page, 1);
                        ClearPageActive(page);
                        ClearPageUnevictable(page);
+                       unlock_page(page);
                        put_page(page);
+                       index++;
                }
-
-               local_irq_disable();
-               __inc_node_page_state(new_page, NR_SHMEM_THPS);
-               if (nr_none) {
-                       __mod_node_page_state(zone->zone_pgdat, NR_FILE_PAGES, nr_none);
-                       __mod_node_page_state(zone->zone_pgdat, NR_SHMEM, nr_none);
+               while (index < end) {
+                       clear_highpage(new_page + (index % HPAGE_PMD_NR));
+                       index++;
                }
-               local_irq_enable();
 
-               /*
-                * Remove pte page tables, so we can re-fault
-                * the page as huge.
-                */
-               retract_page_tables(mapping, start);
-
-               /* Everything is ready, let's unfreeze the new_page */
-               set_page_dirty(new_page);
                SetPageUptodate(new_page);
-               page_ref_unfreeze(new_page, HPAGE_PMD_NR);
+               page_ref_add(new_page, HPAGE_PMD_NR - 1);
+               set_page_dirty(new_page);
                mem_cgroup_commit_charge(new_page, memcg, false, true);
                lru_cache_add_anon(new_page);
-               unlock_page(new_page);
 
+               /*
+                * Remove pte page tables, so we can re-fault the page as huge.
+                */
+               retract_page_tables(mapping, start);
                *hpage = NULL;
 
                khugepaged_pages_collapsed++;
        } else {
                struct page *page;
+
                /* Something went wrong: roll back page cache changes */
-               shmem_uncharge(mapping->host, nr_none);
                xas_lock_irq(&xas);
+               mapping->nrpages -= nr_none;
+               shmem_uncharge(mapping->host, nr_none);
+
                xas_set(&xas, start);
                xas_for_each(&xas, page, end - 1) {
                        page = list_first_entry_or_null(&pagelist,
@@ -1519,19 +1542,18 @@ xa_unlocked:
                        xas_store(&xas, page);
                        xas_pause(&xas);
                        xas_unlock_irq(&xas);
-                       putback_lru_page(page);
                        unlock_page(page);
+                       putback_lru_page(page);
                        xas_lock_irq(&xas);
                }
                VM_BUG_ON(nr_none);
                xas_unlock_irq(&xas);
 
-               /* Unfreeze new_page, caller would take care about freeing it */
-               page_ref_unfreeze(new_page, 1);
                mem_cgroup_cancel_charge(new_page, memcg, true);
-               unlock_page(new_page);
                new_page->mapping = NULL;
        }
+
+       unlock_page(new_page);
 out:
        VM_BUG_ON(!list_empty(&pagelist));
        /* TODO: tracepoints */
index 0cd3de3..7c72f2a 100644 (file)
@@ -1161,6 +1161,7 @@ static int memory_failure_dev_pagemap(unsigned long pfn, int flags,
        LIST_HEAD(tokill);
        int rc = -EBUSY;
        loff_t start;
+       dax_entry_t cookie;
 
        /*
         * Prevent the inode from being freed while we are interrogating
@@ -1169,7 +1170,8 @@ static int memory_failure_dev_pagemap(unsigned long pfn, int flags,
         * also prevents changes to the mapping of this pfn until
         * poison signaling is complete.
         */
-       if (!dax_lock_mapping_entry(page))
+       cookie = dax_lock_page(page);
+       if (!cookie)
                goto out;
 
        if (hwpoison_filter(page)) {
@@ -1220,7 +1222,7 @@ static int memory_failure_dev_pagemap(unsigned long pfn, int flags,
        kill_procs(&tokill, flags & MF_MUST_KILL, !unmap_success, pfn, flags);
        rc = 0;
 unlock:
-       dax_unlock_mapping_entry(page);
+       dax_unlock_page(page, cookie);
 out:
        /* drop pgmap ref acquired in caller */
        put_dev_pagemap(pgmap);
index 5837a06..d4496d9 100644 (file)
@@ -1116,8 +1116,8 @@ static struct page *new_page(struct page *page, unsigned long start)
        } else if (PageTransHuge(page)) {
                struct page *thp;
 
-               thp = alloc_pages_vma(GFP_TRANSHUGE, HPAGE_PMD_ORDER, vma,
-                               address, numa_node_id());
+               thp = alloc_hugepage_vma(GFP_TRANSHUGE, vma, address,
+                                        HPAGE_PMD_ORDER);
                if (!thp)
                        return NULL;
                prep_transhuge_page(thp);
@@ -1662,7 +1662,7 @@ struct mempolicy *__get_vma_policy(struct vm_area_struct *vma,
  * freeing by another task.  It is the caller's responsibility to free the
  * extra reference for shared policies.
  */
-struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
+static struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
                                                unsigned long addr)
 {
        struct mempolicy *pol = __get_vma_policy(vma, addr);
@@ -2011,6 +2011,7 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
  *     @vma:  Pointer to VMA or NULL if not available.
  *     @addr: Virtual Address of the allocation. Must be inside the VMA.
  *     @node: Which node to prefer for allocation (modulo policy).
+ *     @hugepage: for hugepages try only the preferred node if possible
  *
  *     This function allocates a page from the kernel page pool and applies
  *     a NUMA policy associated with the VMA or the current process.
@@ -2021,7 +2022,7 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order,
  */
 struct page *
 alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
-               unsigned long addr, int node)
+               unsigned long addr, int node, bool hugepage)
 {
        struct mempolicy *pol;
        struct page *page;
@@ -2039,6 +2040,31 @@ alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
                goto out;
        }
 
+       if (unlikely(IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && hugepage)) {
+               int hpage_node = node;
+
+               /*
+                * For hugepage allocation and non-interleave policy which
+                * allows the current node (or other explicitly preferred
+                * node) we only try to allocate from the current/preferred
+                * node and don't fall back to other nodes, as the cost of
+                * remote accesses would likely offset THP benefits.
+                *
+                * If the policy is interleave, or does not allow the current
+                * node in its nodemask, we allocate the standard way.
+                */
+               if (pol->mode == MPOL_PREFERRED && !(pol->flags & MPOL_F_LOCAL))
+                       hpage_node = pol->v.preferred_node;
+
+               nmask = policy_nodemask(gfp, pol);
+               if (!nmask || node_isset(hpage_node, *nmask)) {
+                       mpol_cond_put(pol);
+                       page = __alloc_pages_node(hpage_node,
+                                               gfp | __GFP_THISNODE, order);
+                       goto out;
+               }
+       }
+
        nmask = policy_nodemask(gfp, pol);
        preferred_nid = policy_node(gfp, pol, node);
        page = __alloc_pages_nodemask(gfp, order, preferred_nid, nmask);
index 6847177..2ec9cc4 100644 (file)
@@ -5813,8 +5813,10 @@ void __meminit init_currently_empty_zone(struct zone *zone,
                                        unsigned long size)
 {
        struct pglist_data *pgdat = zone->zone_pgdat;
+       int zone_idx = zone_idx(zone) + 1;
 
-       pgdat->nr_zones = zone_idx(zone) + 1;
+       if (zone_idx > pgdat->nr_zones)
+               pgdat->nr_zones = zone_idx;
 
        zone->zone_start_pfn = zone_start_pfn;
 
index 1e79fac..85b7f94 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1627,16 +1627,9 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
                                                      address + PAGE_SIZE);
                } else {
                        /*
-                        * We should not need to notify here as we reach this
-                        * case only from freeze_page() itself only call from
-                        * split_huge_page_to_list() so everything below must
-                        * be true:
-                        *   - page is not anonymous
-                        *   - page is locked
-                        *
-                        * So as it is a locked file back page thus it can not
-                        * be remove from the page cache and replace by a new
-                        * page before mmu_notifier_invalidate_range_end so no
+                        * This is a locked file-backed page, thus it cannot
+                        * be removed from the page cache and replaced by a new
+                        * page before mmu_notifier_invalidate_range_end, so no
                         * concurrent thread might update its page table to
                         * point at new page while a device still is using this
                         * page.
index d44991e..921f804 100644 (file)
@@ -297,12 +297,14 @@ bool shmem_charge(struct inode *inode, long pages)
        if (!shmem_inode_acct_block(inode, pages))
                return false;
 
+       /* nrpages adjustment first, then shmem_recalc_inode() when balanced */
+       inode->i_mapping->nrpages += pages;
+
        spin_lock_irqsave(&info->lock, flags);
        info->alloced += pages;
        inode->i_blocks += pages * BLOCKS_PER_PAGE;
        shmem_recalc_inode(inode);
        spin_unlock_irqrestore(&info->lock, flags);
-       inode->i_mapping->nrpages += pages;
 
        return true;
 }
@@ -312,6 +314,8 @@ void shmem_uncharge(struct inode *inode, long pages)
        struct shmem_inode_info *info = SHMEM_I(inode);
        unsigned long flags;
 
+       /* nrpages adjustment done by __delete_from_page_cache() or caller */
+
        spin_lock_irqsave(&info->lock, flags);
        info->alloced -= pages;
        inode->i_blocks -= pages * BLOCKS_PER_PAGE;
@@ -1435,7 +1439,7 @@ static struct page *shmem_alloc_hugepage(gfp_t gfp,
 
        shmem_pseudo_vma_init(&pvma, info, hindex);
        page = alloc_pages_vma(gfp | __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN,
-                       HPAGE_PMD_ORDER, &pvma, 0, numa_node_id());
+                       HPAGE_PMD_ORDER, &pvma, 0, numa_node_id(), true);
        shmem_pseudo_vma_destroy(&pvma);
        if (page)
                prep_transhuge_page(page);
@@ -1509,11 +1513,13 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
 {
        struct page *oldpage, *newpage;
        struct address_space *swap_mapping;
+       swp_entry_t entry;
        pgoff_t swap_index;
        int error;
 
        oldpage = *pagep;
-       swap_index = page_private(oldpage);
+       entry.val = page_private(oldpage);
+       swap_index = swp_offset(entry);
        swap_mapping = page_mapping(oldpage);
 
        /*
@@ -1532,7 +1538,7 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
        __SetPageLocked(newpage);
        __SetPageSwapBacked(newpage);
        SetPageUptodate(newpage);
-       set_page_private(newpage, swap_index);
+       set_page_private(newpage, entry.val);
        SetPageSwapCache(newpage);
 
        /*
@@ -2214,6 +2220,7 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
        struct page *page;
        pte_t _dst_pte, *dst_pte;
        int ret;
+       pgoff_t offset, max_off;
 
        ret = -ENOMEM;
        if (!shmem_inode_acct_block(inode, 1))
@@ -2236,7 +2243,7 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
                                *pagep = page;
                                shmem_inode_unacct_blocks(inode, 1);
                                /* don't free the page */
-                               return -EFAULT;
+                               return -ENOENT;
                        }
                } else {                /* mfill_zeropage_atomic */
                        clear_highpage(page);
@@ -2251,6 +2258,12 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
        __SetPageSwapBacked(page);
        __SetPageUptodate(page);
 
+       ret = -EFAULT;
+       offset = linear_page_index(dst_vma, dst_addr);
+       max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
+       if (unlikely(offset >= max_off))
+               goto out_release;
+
        ret = mem_cgroup_try_charge_delay(page, dst_mm, gfp, &memcg, false);
        if (ret)
                goto out_release;
@@ -2265,9 +2278,25 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
        _dst_pte = mk_pte(page, dst_vma->vm_page_prot);
        if (dst_vma->vm_flags & VM_WRITE)
                _dst_pte = pte_mkwrite(pte_mkdirty(_dst_pte));
+       else {
+               /*
+                * We don't set the pte dirty if the vma has no
+                * VM_WRITE permission, so mark the page dirty or it
+                * could be freed from under us. We could do it
+                * unconditionally before unlock_page(), but doing it
+                * only if VM_WRITE is not set is faster.
+                */
+               set_page_dirty(page);
+       }
 
-       ret = -EEXIST;
        dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl);
+
+       ret = -EFAULT;
+       max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
+       if (unlikely(offset >= max_off))
+               goto out_release_uncharge_unlock;
+
+       ret = -EEXIST;
        if (!pte_none(*dst_pte))
                goto out_release_uncharge_unlock;
 
@@ -2285,13 +2314,15 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
 
        /* No need to invalidate - it was non-present before */
        update_mmu_cache(dst_vma, dst_addr, dst_pte);
-       unlock_page(page);
        pte_unmap_unlock(dst_pte, ptl);
+       unlock_page(page);
        ret = 0;
 out:
        return ret;
 out_release_uncharge_unlock:
        pte_unmap_unlock(dst_pte, ptl);
+       ClearPageDirty(page);
+       delete_from_page_cache(page);
 out_release_uncharge:
        mem_cgroup_cancel_charge(page, memcg, false);
 out_release:
index 45d68e9..798e7cc 100644 (file)
@@ -517,9 +517,13 @@ void truncate_inode_pages_final(struct address_space *mapping)
                 */
                xa_lock_irq(&mapping->i_pages);
                xa_unlock_irq(&mapping->i_pages);
-
-               truncate_inode_pages(mapping, 0);
        }
+
+       /*
+        * Cleancache needs notification even if there are no pages or shadow
+        * entries.
+        */
+       truncate_inode_pages(mapping, 0);
 }
 EXPORT_SYMBOL(truncate_inode_pages_final);
 
index 5029f24..458acda 100644 (file)
@@ -33,6 +33,8 @@ static int mcopy_atomic_pte(struct mm_struct *dst_mm,
        void *page_kaddr;
        int ret;
        struct page *page;
+       pgoff_t offset, max_off;
+       struct inode *inode;
 
        if (!*pagep) {
                ret = -ENOMEM;
@@ -48,7 +50,7 @@ static int mcopy_atomic_pte(struct mm_struct *dst_mm,
 
                /* fallback to copy_from_user outside mmap_sem */
                if (unlikely(ret)) {
-                       ret = -EFAULT;
+                       ret = -ENOENT;
                        *pagep = page;
                        /* don't free the page */
                        goto out;
@@ -73,8 +75,17 @@ static int mcopy_atomic_pte(struct mm_struct *dst_mm,
        if (dst_vma->vm_flags & VM_WRITE)
                _dst_pte = pte_mkwrite(pte_mkdirty(_dst_pte));
 
-       ret = -EEXIST;
        dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl);
+       if (dst_vma->vm_file) {
+               /* the shmem MAP_PRIVATE case requires checking the i_size */
+               inode = dst_vma->vm_file->f_inode;
+               offset = linear_page_index(dst_vma, dst_addr);
+               max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
+               ret = -EFAULT;
+               if (unlikely(offset >= max_off))
+                       goto out_release_uncharge_unlock;
+       }
+       ret = -EEXIST;
        if (!pte_none(*dst_pte))
                goto out_release_uncharge_unlock;
 
@@ -108,11 +119,22 @@ static int mfill_zeropage_pte(struct mm_struct *dst_mm,
        pte_t _dst_pte, *dst_pte;
        spinlock_t *ptl;
        int ret;
+       pgoff_t offset, max_off;
+       struct inode *inode;
 
        _dst_pte = pte_mkspecial(pfn_pte(my_zero_pfn(dst_addr),
                                         dst_vma->vm_page_prot));
-       ret = -EEXIST;
        dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl);
+       if (dst_vma->vm_file) {
+               /* the shmem MAP_PRIVATE case requires checking the i_size */
+               inode = dst_vma->vm_file->f_inode;
+               offset = linear_page_index(dst_vma, dst_addr);
+               max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
+               ret = -EFAULT;
+               if (unlikely(offset >= max_off))
+                       goto out_unlock;
+       }
+       ret = -EEXIST;
        if (!pte_none(*dst_pte))
                goto out_unlock;
        set_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte);
@@ -205,8 +227,9 @@ retry:
                if (!dst_vma || !is_vm_hugetlb_page(dst_vma))
                        goto out_unlock;
                /*
-                * Only allow __mcopy_atomic_hugetlb on userfaultfd
-                * registered ranges.
+                * Check the vma is registered in uffd, this is
+                * required to enforce the VM_MAYWRITE check done at
+                * uffd registration time.
                 */
                if (!dst_vma->vm_userfaultfd_ctx.ctx)
                        goto out_unlock;
@@ -274,7 +297,7 @@ retry:
 
                cond_resched();
 
-               if (unlikely(err == -EFAULT)) {
+               if (unlikely(err == -ENOENT)) {
                        up_read(&dst_mm->mmap_sem);
                        BUG_ON(!page);
 
@@ -380,7 +403,17 @@ static __always_inline ssize_t mfill_atomic_pte(struct mm_struct *dst_mm,
 {
        ssize_t err;
 
-       if (vma_is_anonymous(dst_vma)) {
+       /*
+        * The normal page fault path for a shmem will invoke the
+        * fault, fill the hole in the file and COW it right away. The
+        * result generates plain anonymous memory. So when we are
+        * asked to fill an hole in a MAP_PRIVATE shmem mapping, we'll
+        * generate anonymous memory directly without actually filling
+        * the hole. For the MAP_PRIVATE case the robustness check
+        * only happens in the pagetable (to verify it's still none)
+        * and not in the radix tree.
+        */
+       if (!(dst_vma->vm_flags & VM_SHARED)) {
                if (!zeropage)
                        err = mcopy_atomic_pte(dst_mm, dst_pmd, dst_vma,
                                               dst_addr, src_addr, page);
@@ -449,13 +482,9 @@ retry:
        if (!dst_vma)
                goto out_unlock;
        /*
-        * Be strict and only allow __mcopy_atomic on userfaultfd
-        * registered ranges to prevent userland errors going
-        * unnoticed. As far as the VM consistency is concerned, it
-        * would be perfectly safe to remove this check, but there's
-        * no useful usage for __mcopy_atomic ouside of userfaultfd
-        * registered ranges. This is after all why these are ioctls
-        * belonging to the userfaultfd and not syscalls.
+        * Check the vma is registered in uffd, this is required to
+        * enforce the VM_MAYWRITE check done at uffd registration
+        * time.
         */
        if (!dst_vma->vm_userfaultfd_ctx.ctx)
                goto out_unlock;
@@ -489,7 +518,8 @@ retry:
         * dst_vma.
         */
        err = -ENOMEM;
-       if (vma_is_anonymous(dst_vma) && unlikely(anon_vma_prepare(dst_vma)))
+       if (!(dst_vma->vm_flags & VM_SHARED) &&
+           unlikely(anon_vma_prepare(dst_vma)))
                goto out_unlock;
 
        while (src_addr < src_start + len) {
@@ -530,7 +560,7 @@ retry:
                                       src_addr, &page, zeropage);
                cond_resched();
 
-               if (unlikely(err == -EFAULT)) {
+               if (unlikely(err == -ENOENT)) {
                        void *page_kaddr;
 
                        up_read(&dst_mm->mmap_sem);
index 5d3f252..ba76547 100644 (file)
@@ -1791,6 +1791,7 @@ priv_release_snd_buf(struct rpc_rqst *rqstp)
        for (i=0; i < rqstp->rq_enc_pages_num; i++)
                __free_page(rqstp->rq_enc_pages[i]);
        kfree(rqstp->rq_enc_pages);
+       rqstp->rq_release_snd_buf = NULL;
 }
 
 static int
@@ -1799,6 +1800,9 @@ alloc_enc_pages(struct rpc_rqst *rqstp)
        struct xdr_buf *snd_buf = &rqstp->rq_snd_buf;
        int first, last, i;
 
+       if (rqstp->rq_release_snd_buf)
+               rqstp->rq_release_snd_buf(rqstp);
+
        if (snd_buf->page_len == 0) {
                rqstp->rq_enc_pages_num = 0;
                return 0;
index ae3b814..c6782aa 100644 (file)
@@ -1915,6 +1915,13 @@ call_connect_status(struct rpc_task *task)
        struct rpc_clnt *clnt = task->tk_client;
        int status = task->tk_status;
 
+       /* Check if the task was already transmitted */
+       if (!test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate)) {
+               xprt_end_transmit(task);
+               task->tk_action = call_transmit_status;
+               return;
+       }
+
        dprint_status(task);
 
        trace_rpc_connect_status(task);
@@ -2302,6 +2309,7 @@ out_retry:
        task->tk_status = 0;
        /* Note: rpc_verify_header() may have freed the RPC slot */
        if (task->tk_rqstp == req) {
+               xdr_free_bvec(&req->rq_rcv_buf);
                req->rq_reply_bytes_recvd = req->rq_rcv_buf.len = 0;
                if (task->tk_client->cl_discrtry)
                        xprt_conditional_disconnect(req->rq_xprt,
index 86bea45..ce92700 100644 (file)
@@ -826,8 +826,15 @@ void xprt_connect(struct rpc_task *task)
                        return;
                if (xprt_test_and_set_connecting(xprt))
                        return;
-               xprt->stat.connect_start = jiffies;
-               xprt->ops->connect(xprt, task);
+               /* Race breaker */
+               if (!xprt_connected(xprt)) {
+                       xprt->stat.connect_start = jiffies;
+                       xprt->ops->connect(xprt, task);
+               } else {
+                       xprt_clear_connecting(xprt);
+                       task->tk_status = 0;
+                       rpc_wake_up_queued_task(&xprt->pending, task);
+               }
        }
        xprt_release_write(xprt, task);
 }
@@ -1623,6 +1630,8 @@ xprt_request_init(struct rpc_task *task)
        req->rq_snd_buf.buflen = 0;
        req->rq_rcv_buf.len = 0;
        req->rq_rcv_buf.buflen = 0;
+       req->rq_snd_buf.bvec = NULL;
+       req->rq_rcv_buf.bvec = NULL;
        req->rq_release_snd_buf = NULL;
        xprt_reset_majortimeo(req);
        dprintk("RPC: %5u reserved req %p xid %08x\n", task->tk_pid,
index ae77c71..8a5e823 100644 (file)
@@ -330,18 +330,16 @@ xs_alloc_sparse_pages(struct xdr_buf *buf, size_t want, gfp_t gfp)
 {
        size_t i,n;
 
-       if (!(buf->flags & XDRBUF_SPARSE_PAGES))
+       if (!want || !(buf->flags & XDRBUF_SPARSE_PAGES))
                return want;
-       if (want > buf->page_len)
-               want = buf->page_len;
        n = (buf->page_base + want + PAGE_SIZE - 1) >> PAGE_SHIFT;
        for (i = 0; i < n; i++) {
                if (buf->pages[i])
                        continue;
                buf->bvec[i].bv_page = buf->pages[i] = alloc_page(gfp);
                if (!buf->pages[i]) {
-                       buf->page_len = (i * PAGE_SIZE) - buf->page_base;
-                       return buf->page_len;
+                       i *= PAGE_SIZE;
+                       return i > buf->page_base ? i - buf->page_base : 0;
                }
        }
        return want;
@@ -378,8 +376,8 @@ static ssize_t
 xs_read_discard(struct socket *sock, struct msghdr *msg, int flags,
                size_t count)
 {
-       struct kvec kvec = { 0 };
-       return xs_read_kvec(sock, msg, flags | MSG_TRUNC, &kvec, count, 0);
+       iov_iter_discard(&msg->msg_iter, READ, count);
+       return sock_recvmsg(sock, msg, flags);
 }
 
 static ssize_t
@@ -398,16 +396,17 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
                if (offset == count || msg->msg_flags & (MSG_EOR|MSG_TRUNC))
                        goto out;
                if (ret != want)
-                       goto eagain;
+                       goto out;
                seek = 0;
        } else {
                seek -= buf->head[0].iov_len;
                offset += buf->head[0].iov_len;
        }
-       if (seek < buf->page_len) {
-               want = xs_alloc_sparse_pages(buf,
-                               min_t(size_t, count - offset, buf->page_len),
-                               GFP_NOWAIT);
+
+       want = xs_alloc_sparse_pages(buf,
+                       min_t(size_t, count - offset, buf->page_len),
+                       GFP_NOWAIT);
+       if (seek < want) {
                ret = xs_read_bvec(sock, msg, flags, buf->bvec,
                                xdr_buf_pagecount(buf),
                                want + buf->page_base,
@@ -418,12 +417,13 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
                if (offset == count || msg->msg_flags & (MSG_EOR|MSG_TRUNC))
                        goto out;
                if (ret != want)
-                       goto eagain;
+                       goto out;
                seek = 0;
        } else {
-               seek -= buf->page_len;
-               offset += buf->page_len;
+               seek -= want;
+               offset += want;
        }
+
        if (seek < buf->tail[0].iov_len) {
                want = min_t(size_t, count - offset, buf->tail[0].iov_len);
                ret = xs_read_kvec(sock, msg, flags, &buf->tail[0], want, seek);
@@ -433,17 +433,13 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
                if (offset == count || msg->msg_flags & (MSG_EOR|MSG_TRUNC))
                        goto out;
                if (ret != want)
-                       goto eagain;
+                       goto out;
        } else
                offset += buf->tail[0].iov_len;
        ret = -EMSGSIZE;
-       msg->msg_flags |= MSG_TRUNC;
 out:
        *read = offset - seek_init;
        return ret;
-eagain:
-       ret = -EAGAIN;
-       goto out;
 sock_err:
        offset += seek;
        goto out;
@@ -486,19 +482,20 @@ xs_read_stream_request(struct sock_xprt *transport, struct msghdr *msg,
        if (transport->recv.offset == transport->recv.len) {
                if (xs_read_stream_request_done(transport))
                        msg->msg_flags |= MSG_EOR;
-               return transport->recv.copied;
+               return read;
        }
 
        switch (ret) {
+       default:
+               break;
+       case -EFAULT:
        case -EMSGSIZE:
-               return transport->recv.copied;
+               msg->msg_flags |= MSG_TRUNC;
+               return read;
        case 0:
                return -ESHUTDOWN;
-       default:
-               if (ret < 0)
-                       return ret;
        }
-       return -EAGAIN;
+       return ret < 0 ? ret : read;
 }
 
 static size_t
@@ -537,7 +534,7 @@ xs_read_stream_call(struct sock_xprt *transport, struct msghdr *msg, int flags)
 
        ret = xs_read_stream_request(transport, msg, flags, req);
        if (msg->msg_flags & (MSG_EOR|MSG_TRUNC))
-               xprt_complete_bc_request(req, ret);
+               xprt_complete_bc_request(req, transport->recv.copied);
 
        return ret;
 }
@@ -570,7 +567,7 @@ xs_read_stream_reply(struct sock_xprt *transport, struct msghdr *msg, int flags)
 
        spin_lock(&xprt->queue_lock);
        if (msg->msg_flags & (MSG_EOR|MSG_TRUNC))
-               xprt_complete_rqst(req->rq_task, ret);
+               xprt_complete_rqst(req->rq_task, transport->recv.copied);
        xprt_unpin_rqst(req);
 out:
        spin_unlock(&xprt->queue_lock);
@@ -591,10 +588,8 @@ xs_read_stream(struct sock_xprt *transport, int flags)
                if (ret <= 0)
                        goto out_err;
                transport->recv.offset = ret;
-               if (ret != want) {
-                       ret = -EAGAIN;
-                       goto out_err;
-               }
+               if (transport->recv.offset != want)
+                       return transport->recv.offset;
                transport->recv.len = be32_to_cpu(transport->recv.fraghdr) &
                        RPC_FRAGMENT_SIZE_MASK;
                transport->recv.offset -= sizeof(transport->recv.fraghdr);
@@ -602,6 +597,9 @@ xs_read_stream(struct sock_xprt *transport, int flags)
        }
 
        switch (be32_to_cpu(transport->recv.calldir)) {
+       default:
+               msg.msg_flags |= MSG_TRUNC;
+               break;
        case RPC_CALL:
                ret = xs_read_stream_call(transport, &msg, flags);
                break;
@@ -616,6 +614,9 @@ xs_read_stream(struct sock_xprt *transport, int flags)
                goto out_err;
        read += ret;
        if (transport->recv.offset < transport->recv.len) {
+               if (!(msg.msg_flags & MSG_TRUNC))
+                       return read;
+               msg.msg_flags = 0;
                ret = xs_read_discard(transport->sock, &msg, flags,
                                transport->recv.len - transport->recv.offset);
                if (ret <= 0)
@@ -623,7 +624,7 @@ xs_read_stream(struct sock_xprt *transport, int flags)
                transport->recv.offset += ret;
                read += ret;
                if (transport->recv.offset != transport->recv.len)
-                       return -EAGAIN;
+                       return read;
        }
        if (xs_read_stream_request_done(transport)) {
                trace_xs_stream_read_request(transport);
@@ -633,13 +634,7 @@ xs_read_stream(struct sock_xprt *transport, int flags)
        transport->recv.len = 0;
        return read;
 out_err:
-       switch (ret) {
-       case 0:
-       case -ESHUTDOWN:
-               xprt_force_disconnect(&transport->xprt);
-               return -ESHUTDOWN;
-       }
-       return ret;
+       return ret != 0 ? ret : -ESHUTDOWN;
 }
 
 static void xs_stream_data_receive(struct sock_xprt *transport)
@@ -648,12 +643,12 @@ static void xs_stream_data_receive(struct sock_xprt *transport)
        ssize_t ret = 0;
 
        mutex_lock(&transport->recv_mutex);
+       clear_bit(XPRT_SOCK_DATA_READY, &transport->sock_state);
        if (transport->sock == NULL)
                goto out;
-       clear_bit(XPRT_SOCK_DATA_READY, &transport->sock_state);
        for (;;) {
                ret = xs_read_stream(transport, MSG_DONTWAIT);
-               if (ret <= 0)
+               if (ret < 0)
                        break;
                read += ret;
                cond_resched();
@@ -1345,10 +1340,10 @@ static void xs_udp_data_receive(struct sock_xprt *transport)
        int err;
 
        mutex_lock(&transport->recv_mutex);
+       clear_bit(XPRT_SOCK_DATA_READY, &transport->sock_state);
        sk = transport->inet;
        if (sk == NULL)
                goto out;
-       clear_bit(XPRT_SOCK_DATA_READY, &transport->sock_state);
        for (;;) {
                skb = skb_recv_udp(sk, 0, 1, &err);
                if (skb == NULL)
index a8e7ba9..6a6be9f 100644 (file)
@@ -236,10 +236,8 @@ ifdef CONFIG_GCOV_KERNEL
 objtool_args += --no-unreachable
 endif
 ifdef CONFIG_RETPOLINE
-ifneq ($(RETPOLINE_CFLAGS),)
   objtool_args += --retpoline
 endif
-endif
 
 
 ifdef CONFIG_MODVERSIONS
index 2f48da9..dbd3746 100644 (file)
@@ -363,10 +363,12 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
                                                PASS_POS_INSERT_BEFORE);
 
        /*
-        * The stackleak_cleanup pass should be executed after the
-        * "reload" pass, when the stack frame size is final.
+        * The stackleak_cleanup pass should be executed before the "*free_cfg"
+        * pass. It's the moment when the stack frame size is already final,
+        * function prologues and epilogues are generated, and the
+        * machine-dependent code transformations are not done.
         */
-       PASS_INFO(stackleak_cleanup, "reload", 1, PASS_POS_INSERT_AFTER);
+       PASS_INFO(stackleak_cleanup, "*free_cfg", 1, PASS_POS_INSERT_BEFORE);
 
        if (!plugin_default_version_check(version, &gcc_version)) {
                error(G_("incompatible gcc/plugin versions"));
index 7493c0e..db00e3e 100644 (file)
@@ -395,7 +395,7 @@ usage(void)
  * When we have processed a group that starts off with a known-false
  * #if/#elif sequence (which has therefore been deleted) followed by a
  * #elif that we don't understand and therefore must keep, we edit the
- * latter into a #if to keep the nesting correct. We use strncpy() to
+ * latter into a #if to keep the nesting correct. We use memcpy() to
  * overwrite the 4 byte token "elif" with "if  " without a '\0' byte.
  *
  * When we find a true #elif in a group, the following block will
@@ -450,7 +450,7 @@ static void Idrop (void) { Fdrop();  ignoreon(); }
 static void Itrue (void) { Ftrue();  ignoreon(); }
 static void Ifalse(void) { Ffalse(); ignoreon(); }
 /* modify this line */
-static void Mpass (void) { strncpy(keyword, "if  ", 4); Pelif(); }
+static void Mpass (void) { memcpy(keyword, "if  ", 4); Pelif(); }
 static void Mtrue (void) { keywordedit("else");  state(IS_TRUE_MIDDLE); }
 static void Melif (void) { keywordedit("endif"); state(IS_FALSE_TRAILER); }
 static void Melse (void) { keywordedit("endif"); state(IS_FALSE_ELSE); }
index 74b951f..9cec812 100644 (file)
@@ -80,6 +80,9 @@ static const struct nlmsg_perm nlmsg_route_perms[] =
        { RTM_NEWSTATS,         NETLINK_ROUTE_SOCKET__NLMSG_READ },
        { RTM_GETSTATS,         NETLINK_ROUTE_SOCKET__NLMSG_READ  },
        { RTM_NEWCACHEREPORT,   NETLINK_ROUTE_SOCKET__NLMSG_READ },
+       { RTM_NEWCHAIN,         NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+       { RTM_DELCHAIN,         NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+       { RTM_GETCHAIN,         NETLINK_ROUTE_SOCKET__NLMSG_READ  },
 };
 
 static const struct nlmsg_perm nlmsg_tcpdiag_perms[] =
@@ -158,7 +161,11 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
 
        switch (sclass) {
        case SECCLASS_NETLINK_ROUTE_SOCKET:
-               /* RTM_MAX always point to RTM_SETxxxx, ie RTM_NEWxxx + 3 */
+               /* RTM_MAX always points to RTM_SETxxxx, ie RTM_NEWxxx + 3.
+                * If the BUILD_BUG_ON() below fails you must update the
+                * structures at the top of this file with the new mappings
+                * before updating the BUILD_BUG_ON() macro!
+                */
                BUILD_BUG_ON(RTM_MAX != (RTM_NEWCHAIN + 3));
                err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms,
                                 sizeof(nlmsg_route_perms));
@@ -170,6 +177,10 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
                break;
 
        case SECCLASS_NETLINK_XFRM_SOCKET:
+               /* If the BUILD_BUG_ON() below fails you must update the
+                * structures at the top of this file with the new mappings
+                * before updating the BUILD_BUG_ON() macro!
+                */
                BUILD_BUG_ON(XFRM_MSG_MAX != XFRM_MSG_MAPPING);
                err = nlmsg_perm(nlmsg_type, perm, nlmsg_xfrm_perms,
                                 sizeof(nlmsg_xfrm_perms));
index 9aa15bf..649d321 100644 (file)
@@ -348,6 +348,40 @@ static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
        return 0;
 }
 
+/* add a new kcontrol object; call with card->controls_rwsem locked */
+static int __snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
+{
+       struct snd_ctl_elem_id id;
+       unsigned int idx;
+       unsigned int count;
+
+       id = kcontrol->id;
+       if (id.index > UINT_MAX - kcontrol->count)
+               return -EINVAL;
+
+       if (snd_ctl_find_id(card, &id)) {
+               dev_err(card->dev,
+                       "control %i:%i:%i:%s:%i is already present\n",
+                       id.iface, id.device, id.subdevice, id.name, id.index);
+               return -EBUSY;
+       }
+
+       if (snd_ctl_find_hole(card, kcontrol->count) < 0)
+               return -ENOMEM;
+
+       list_add_tail(&kcontrol->list, &card->controls);
+       card->controls_count += kcontrol->count;
+       kcontrol->id.numid = card->last_numid + 1;
+       card->last_numid += kcontrol->count;
+
+       id = kcontrol->id;
+       count = kcontrol->count;
+       for (idx = 0; idx < count; idx++, id.index++, id.numid++)
+               snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
+
+       return 0;
+}
+
 /**
  * snd_ctl_add - add the control instance to the card
  * @card: the card instance
@@ -364,45 +398,18 @@ static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
  */
 int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
 {
-       struct snd_ctl_elem_id id;
-       unsigned int idx;
-       unsigned int count;
        int err = -EINVAL;
 
        if (! kcontrol)
                return err;
        if (snd_BUG_ON(!card || !kcontrol->info))
                goto error;
-       id = kcontrol->id;
-       if (id.index > UINT_MAX - kcontrol->count)
-               goto error;
 
        down_write(&card->controls_rwsem);
-       if (snd_ctl_find_id(card, &id)) {
-               up_write(&card->controls_rwsem);
-               dev_err(card->dev, "control %i:%i:%i:%s:%i is already present\n",
-                                       id.iface,
-                                       id.device,
-                                       id.subdevice,
-                                       id.name,
-                                       id.index);
-               err = -EBUSY;
-               goto error;
-       }
-       if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
-               up_write(&card->controls_rwsem);
-               err = -ENOMEM;
-               goto error;
-       }
-       list_add_tail(&kcontrol->list, &card->controls);
-       card->controls_count += kcontrol->count;
-       kcontrol->id.numid = card->last_numid + 1;
-       card->last_numid += kcontrol->count;
-       id = kcontrol->id;
-       count = kcontrol->count;
+       err = __snd_ctl_add(card, kcontrol);
        up_write(&card->controls_rwsem);
-       for (idx = 0; idx < count; idx++, id.index++, id.numid++)
-               snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
+       if (err < 0)
+               goto error;
        return 0;
 
  error:
@@ -1361,9 +1368,12 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
                kctl->tlv.c = snd_ctl_elem_user_tlv;
 
        /* This function manage to free the instance on failure. */
-       err = snd_ctl_add(card, kctl);
-       if (err < 0)
-               return err;
+       down_write(&card->controls_rwsem);
+       err = __snd_ctl_add(card, kctl);
+       if (err < 0) {
+               snd_ctl_free_one(kctl);
+               goto unlock;
+       }
        offset = snd_ctl_get_ioff(kctl, &info->id);
        snd_ctl_build_ioff(&info->id, kctl, offset);
        /*
@@ -1374,10 +1384,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
         * which locks the element.
         */
 
-       down_write(&card->controls_rwsem);
        card->user_ctl_count++;
-       up_write(&card->controls_rwsem);
 
+ unlock:
+       up_write(&card->controls_rwsem);
        return 0;
 }
 
index 66c90f4..818dff1 100644 (file)
@@ -36,6 +36,7 @@
 #include <sound/timer.h>
 #include <sound/minors.h>
 #include <linux/uio.h>
+#include <linux/delay.h>
 
 #include "pcm_local.h"
 
@@ -91,12 +92,12 @@ static DECLARE_RWSEM(snd_pcm_link_rwsem);
  * and this may lead to a deadlock when the code path takes read sem
  * twice (e.g. one in snd_pcm_action_nonatomic() and another in
  * snd_pcm_stream_lock()).  As a (suboptimal) workaround, let writer to
- * spin until it gets the lock.
+ * sleep until all the readers are completed without blocking by writer.
  */
-static inline void down_write_nonblock(struct rw_semaphore *lock)
+static inline void down_write_nonfifo(struct rw_semaphore *lock)
 {
        while (!down_write_trylock(lock))
-               cond_resched();
+               msleep(1);
 }
 
 #define PCM_LOCK_DEFAULT       0
@@ -1967,7 +1968,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
                res = -ENOMEM;
                goto _nolock;
        }
-       down_write_nonblock(&snd_pcm_link_rwsem);
+       down_write_nonfifo(&snd_pcm_link_rwsem);
        write_lock_irq(&snd_pcm_link_rwlock);
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
            substream->runtime->status->state != substream1->runtime->status->state ||
@@ -2014,7 +2015,7 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream)
        struct snd_pcm_substream *s;
        int res = 0;
 
-       down_write_nonblock(&snd_pcm_link_rwsem);
+       down_write_nonfifo(&snd_pcm_link_rwsem);
        write_lock_irq(&snd_pcm_link_rwlock);
        if (!snd_pcm_stream_linked(substream)) {
                res = -EALREADY;
@@ -2369,7 +2370,8 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
 
 static void pcm_release_private(struct snd_pcm_substream *substream)
 {
-       snd_pcm_unlink(substream);
+       if (snd_pcm_stream_linked(substream))
+               snd_pcm_unlink(substream);
 }
 
 void snd_pcm_release_substream(struct snd_pcm_substream *substream)
index 32453f8..3a50088 100644 (file)
@@ -1531,7 +1531,6 @@ static int snd_wss_playback_open(struct snd_pcm_substream *substream)
        if (err < 0) {
                if (chip->release_dma)
                        chip->release_dma(chip, chip->dma_private_data, chip->dma1);
-               snd_free_pages(runtime->dma_area, runtime->dma_bytes);
                return err;
        }
        chip->playback_substream = substream;
@@ -1572,7 +1571,6 @@ static int snd_wss_capture_open(struct snd_pcm_substream *substream)
        if (err < 0) {
                if (chip->release_dma)
                        chip->release_dma(chip, chip->dma_private_data, chip->dma2);
-               snd_free_pages(runtime->dma_area, runtime->dma_bytes);
                return err;
        }
        chip->capture_substream = substream;
index f4459d1..27b468f 100644 (file)
@@ -824,7 +824,7 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
 {
        struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
        int reg = kcontrol->private_value & 0xff;
-       int shift = (kcontrol->private_value >> 8) & 0xff;
+       int shift = (kcontrol->private_value >> 8) & 0x0f;
        int mask = (kcontrol->private_value >> 16) & 0xff;
        // int invert = (kcontrol->private_value >> 24) & 0xff;
        unsigned short value, old, new;
index d8eb2b5..76f03ab 100644 (file)
@@ -2169,6 +2169,8 @@ static struct snd_pci_quirk power_save_blacklist[] = {
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        SND_PCI_QUIRK(0x1849, 0xc892, "Asrock B85M-ITX", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
+       SND_PCI_QUIRK(0x1849, 0x0397, "Asrock N68C-S UCC", 0),
+       /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        SND_PCI_QUIRK(0x1849, 0x7662, "Asrock H81M-HDS", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0),
@@ -2496,6 +2498,10 @@ static const struct pci_device_id azx_ids[] = {
        /* AMD Hudson */
        { PCI_DEVICE(0x1022, 0x780d),
          .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB },
+       /* AMD Stoney */
+       { PCI_DEVICE(0x1022, 0x157a),
+         .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB |
+                        AZX_DCAPS_PM_RUNTIME },
        /* AMD Raven */
        { PCI_DEVICE(0x1022, 0x15e3),
          .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB |
index 970bc44..8d75597 100644 (file)
@@ -388,6 +388,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
        case 0x10ec0285:
        case 0x10ec0298:
        case 0x10ec0289:
+       case 0x10ec0300:
                alc_update_coef_idx(codec, 0x10, 1<<9, 0);
                break;
        case 0x10ec0275:
@@ -2830,6 +2831,7 @@ enum {
        ALC269_TYPE_ALC215,
        ALC269_TYPE_ALC225,
        ALC269_TYPE_ALC294,
+       ALC269_TYPE_ALC300,
        ALC269_TYPE_ALC700,
 };
 
@@ -2864,6 +2866,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        case ALC269_TYPE_ALC215:
        case ALC269_TYPE_ALC225:
        case ALC269_TYPE_ALC294:
+       case ALC269_TYPE_ALC300:
        case ALC269_TYPE_ALC700:
                ssids = alc269_ssids;
                break;
@@ -4985,9 +4988,18 @@ static void alc_fixup_tpt470_dock(struct hda_codec *codec,
                { 0x19, 0x21a11010 }, /* dock mic */
                { }
        };
+       /* Assure the speaker pin to be coupled with DAC NID 0x03; otherwise
+        * the speaker output becomes too low by some reason on Thinkpads with
+        * ALC298 codec
+        */
+       static hda_nid_t preferred_pairs[] = {
+               0x14, 0x03, 0x17, 0x02, 0x21, 0x02,
+               0
+       };
        struct alc_spec *spec = codec->spec;
 
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               spec->gen.preferred_dacs = preferred_pairs;
                spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
                snd_hda_apply_pincfgs(codec, pincfgs);
        } else if (action == HDA_FIXUP_ACT_INIT) {
@@ -5358,6 +5370,16 @@ static void alc274_fixup_bind_dacs(struct hda_codec *codec,
        spec->gen.preferred_dacs = preferred_pairs;
 }
 
+/* The DAC of NID 0x3 will introduce click/pop noise on headphones, so invalidate it */
+static void alc285_fixup_invalidate_dacs(struct hda_codec *codec,
+                             const struct hda_fixup *fix, int action)
+{
+       if (action != HDA_FIXUP_ACT_PRE_PROBE)
+               return;
+
+       snd_hda_override_wcaps(codec, 0x03, 0);
+}
+
 /* for hda_fixup_thinkpad_acpi() */
 #include "thinkpad_helper.c"
 
@@ -5495,6 +5517,9 @@ enum {
        ALC255_FIXUP_DELL_HEADSET_MIC,
        ALC295_FIXUP_HP_X360,
        ALC221_FIXUP_HP_HEADSET_MIC,
+       ALC285_FIXUP_LENOVO_HEADPHONE_NOISE,
+       ALC295_FIXUP_HP_AUTO_MUTE,
+       ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -5659,6 +5684,8 @@ static const struct hda_fixup alc269_fixups[] = {
        [ALC269_FIXUP_HP_MUTE_LED_MIC3] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc269_fixup_hp_mute_led_mic3,
+               .chained = true,
+               .chain_id = ALC295_FIXUP_HP_AUTO_MUTE
        },
        [ALC269_FIXUP_HP_GPIO_LED] = {
                .type = HDA_FIXUP_FUNC,
@@ -6362,6 +6389,23 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_HEADSET_MIC
        },
+       [ALC285_FIXUP_LENOVO_HEADPHONE_NOISE] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc285_fixup_invalidate_dacs,
+       },
+       [ALC295_FIXUP_HP_AUTO_MUTE] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_auto_mute_via_amp,
+       },
+       [ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x18, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MIC
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -6376,7 +6420,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0762, "Acer Aspire E1-472", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
        SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
        SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
+       SND_PCI_QUIRK(0x1025, 0x102b, "Acer Aspire C24-860", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1025, 0x106d, "Acer Cloudbook 14", ALC283_FIXUP_CHROME_BOOK),
+       SND_PCI_QUIRK(0x1025, 0x128f, "Acer Veriton Z6860G", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
        SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
        SND_PCI_QUIRK(0x1028, 0x05bd, "Dell Latitude E6440", ALC292_FIXUP_DELL_E7X),
@@ -6532,6 +6580,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
        SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
@@ -7034,6 +7083,15 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x12, 0x90a60130},
                {0x19, 0x03a11020},
                {0x21, 0x0321101f}),
+       SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_HEADPHONE_NOISE,
+               {0x12, 0x90a60130},
+               {0x14, 0x90170110},
+               {0x19, 0x04a11040},
+               {0x21, 0x04211020}),
+       SND_HDA_PIN_QUIRK(0x10ec0286, 0x1025, "Acer", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE,
+               {0x12, 0x90a60130},
+               {0x17, 0x90170110},
+               {0x21, 0x02211020}),
        SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
                {0x12, 0x90a60120},
                {0x14, 0x90170110},
@@ -7295,6 +7353,10 @@ static int patch_alc269(struct hda_codec *codec)
                spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */
                alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */
                break;
+       case 0x10ec0300:
+               spec->codec_variant = ALC269_TYPE_ALC300;
+               spec->gen.mixer_nid = 0; /* no loopback on ALC300 */
+               break;
        case 0x10ec0700:
        case 0x10ec0701:
        case 0x10ec0703:
@@ -8405,6 +8467,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
        HDA_CODEC_ENTRY(0x10ec0295, "ALC295", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0299, "ALC299", patch_alc269),
+       HDA_CODEC_ENTRY(0x10ec0300, "ALC300", patch_alc269),
        HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861),
        HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
        HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861),
index 4e98548..e63d6e3 100644 (file)
@@ -2187,11 +2187,6 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
         */
        snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE,
                                                        AC_PWRST_D3);
-       err = snd_hdac_display_power(bus, false);
-       if (err < 0) {
-               dev_err(dev, "Cannot turn on display power on i915\n");
-               return err;
-       }
 
        hlink = snd_hdac_ext_bus_get_link(bus, dev_name(dev));
        if (!hlink) {
@@ -2201,7 +2196,11 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
 
        snd_hdac_ext_bus_link_put(bus, hlink);
 
-       return 0;
+       err = snd_hdac_display_power(bus, false);
+       if (err < 0)
+               dev_err(dev, "Cannot turn off display power on i915\n");
+
+       return err;
 }
 
 static int hdac_hdmi_runtime_resume(struct device *dev)
index 2c6ba55..bb3f0c4 100644 (file)
@@ -139,7 +139,7 @@ enum pcm186x_type {
 #define PCM186X_MAX_REGISTER           PCM186X_CURR_TRIM_CTRL
 
 /* PCM186X_PAGE */
-#define PCM186X_RESET                  0xff
+#define PCM186X_RESET                  0xfe
 
 /* PCM186X_ADCX_INPUT_SEL_X */
 #define PCM186X_ADC_INPUT_SEL_POL      BIT(7)
index 494d9d6..771b46e 100644 (file)
@@ -198,20 +198,16 @@ static const struct snd_kcontrol_new pcm3060_dapm_controls[] = {
 };
 
 static const struct snd_soc_dapm_widget pcm3060_dapm_widgets[] = {
-       SND_SOC_DAPM_OUTPUT("OUTL+"),
-       SND_SOC_DAPM_OUTPUT("OUTR+"),
-       SND_SOC_DAPM_OUTPUT("OUTL-"),
-       SND_SOC_DAPM_OUTPUT("OUTR-"),
+       SND_SOC_DAPM_OUTPUT("OUTL"),
+       SND_SOC_DAPM_OUTPUT("OUTR"),
 
        SND_SOC_DAPM_INPUT("INL"),
        SND_SOC_DAPM_INPUT("INR"),
 };
 
 static const struct snd_soc_dapm_route pcm3060_dapm_map[] = {
-       { "OUTL+", NULL, "Playback" },
-       { "OUTR+", NULL, "Playback" },
-       { "OUTL-", NULL, "Playback" },
-       { "OUTR-", NULL, "Playback" },
+       { "OUTL", NULL, "Playback" },
+       { "OUTR", NULL, "Playback" },
 
        { "Capture", NULL, "INL" },
        { "Capture", NULL, "INR" },
index a53dc17..66501b8 100644 (file)
@@ -765,38 +765,41 @@ static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *mem,
 
 static void wm_adsp2_show_fw_status(struct wm_adsp *dsp)
 {
-       u16 scratch[4];
+       unsigned int scratch[4];
+       unsigned int addr = dsp->base + ADSP2_SCRATCH0;
+       unsigned int i;
        int ret;
 
-       ret = regmap_raw_read(dsp->regmap, dsp->base + ADSP2_SCRATCH0,
-                               scratch, sizeof(scratch));
-       if (ret) {
-               adsp_err(dsp, "Failed to read SCRATCH regs: %d\n", ret);
-               return;
+       for (i = 0; i < ARRAY_SIZE(scratch); ++i) {
+               ret = regmap_read(dsp->regmap, addr + i, &scratch[i]);
+               if (ret) {
+                       adsp_err(dsp, "Failed to read SCRATCH%u: %d\n", i, ret);
+                       return;
+               }
        }
 
        adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
-                be16_to_cpu(scratch[0]),
-                be16_to_cpu(scratch[1]),
-                be16_to_cpu(scratch[2]),
-                be16_to_cpu(scratch[3]));
+                scratch[0], scratch[1], scratch[2], scratch[3]);
 }
 
 static void wm_adsp2v2_show_fw_status(struct wm_adsp *dsp)
 {
-       u32 scratch[2];
+       unsigned int scratch[2];
        int ret;
 
-       ret = regmap_raw_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH0_1,
-                             scratch, sizeof(scratch));
-
+       ret = regmap_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH0_1,
+                         &scratch[0]);
        if (ret) {
-               adsp_err(dsp, "Failed to read SCRATCH regs: %d\n", ret);
+               adsp_err(dsp, "Failed to read SCRATCH0_1: %d\n", ret);
                return;
        }
 
-       scratch[0] = be32_to_cpu(scratch[0]);
-       scratch[1] = be32_to_cpu(scratch[1]);
+       ret = regmap_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH2_3,
+                         &scratch[1]);
+       if (ret) {
+               adsp_err(dsp, "Failed to read SCRATCH2_3: %d\n", ret);
+               return;
+       }
 
        adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
                 scratch[0] & 0xFFFF,
index 0caa1f4..18e7177 100644 (file)
@@ -101,22 +101,42 @@ config SND_SST_ATOM_HIFI2_PLATFORM_ACPI
          codec, then enable this option by saying Y or m. This is a
          recommended option
 
-config SND_SOC_INTEL_SKYLAKE_SSP_CLK
-       tristate
-
 config SND_SOC_INTEL_SKYLAKE
        tristate "SKL/BXT/KBL/GLK/CNL... Platforms"
        depends on PCI && ACPI
+       select SND_SOC_INTEL_SKYLAKE_COMMON
+       help
+         If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/
+         GeminiLake or CannonLake platform with the DSP enabled in the BIOS
+         then enable this option by saying Y or m.
+
+if  SND_SOC_INTEL_SKYLAKE
+
+config SND_SOC_INTEL_SKYLAKE_SSP_CLK
+       tristate
+
+config SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
+       bool "HDAudio codec support"
+       help
+         If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/
+         GeminiLake or CannonLake platform with an HDaudio codec
+         then enable this option by saying Y
+
+config SND_SOC_INTEL_SKYLAKE_COMMON
+       tristate
        select SND_HDA_EXT_CORE
        select SND_HDA_DSP_LOADER
        select SND_SOC_TOPOLOGY
        select SND_SOC_INTEL_SST
+       select SND_SOC_HDAC_HDA if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
        select SND_SOC_ACPI_INTEL_MATCH
        help
          If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/
          GeminiLake or CannonLake platform with the DSP enabled in the BIOS
          then enable this option by saying Y or m.
 
+endif ## SND_SOC_INTEL_SKYLAKE
+
 config SND_SOC_ACPI_INTEL_MATCH
        tristate
        select SND_SOC_ACPI if ACPI
index 73ca135..b177db2 100644 (file)
@@ -293,16 +293,6 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH
          Say Y if you have such a device.
          If unsure select "N".
 
-config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH
-       tristate "SKL/KBL/BXT/APL with HDA Codecs"
-       select SND_SOC_HDAC_HDMI
-       select SND_SOC_HDAC_HDA
-       help
-         This adds support for ASoC machine driver for Intel platforms
-         SKL/KBL/BXT/APL with iDisp, HDA audio codecs.
-          Say Y or m if you have such a device. This is a recommended option.
-         If unsure select "N".
-
 config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH
        tristate "GLK with RT5682 and MAX98357A in I2S Mode"
        depends on MFD_INTEL_LPSS && I2C && ACPI
@@ -319,4 +309,18 @@ config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH
 
 endif ## SND_SOC_INTEL_SKYLAKE
 
+if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
+
+config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH
+       tristate "SKL/KBL/BXT/APL with HDA Codecs"
+       select SND_SOC_HDAC_HDMI
+       # SND_SOC_HDAC_HDA is already selected
+       help
+         This adds support for ASoC machine driver for Intel platforms
+         SKL/KBL/BXT/APL with iDisp, HDA audio codecs.
+          Say Y or m if you have such a device. This is a recommended option.
+         If unsure select "N".
+
+endif ## SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
+
 endif ## SND_SOC_INTEL_MACH
index db6976f..9d9f6e4 100644 (file)
@@ -19,6 +19,7 @@
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
+#include <linux/dmi.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -35,6 +36,8 @@
 #define CHT_PLAT_CLK_3_HZ      19200000
 #define CHT_CODEC_DAI  "HiFi"
 
+#define QUIRK_PMC_PLT_CLK_0                            0x01
+
 struct cht_mc_private {
        struct clk *mclk;
        struct snd_soc_jack jack;
@@ -385,11 +388,29 @@ static struct snd_soc_card snd_soc_card_cht = {
        .num_controls = ARRAY_SIZE(cht_mc_controls),
 };
 
+static const struct dmi_system_id cht_max98090_quirk_table[] = {
+       {
+               /* Swanky model Chromebook (Toshiba Chromebook 2) */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Swanky"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {}
+};
+
 static int snd_cht_mc_probe(struct platform_device *pdev)
 {
+       const struct dmi_system_id *dmi_id;
        struct device *dev = &pdev->dev;
        int ret_val = 0;
        struct cht_mc_private *drv;
+       const char *mclk_name;
+       int quirks = 0;
+
+       dmi_id = dmi_first_match(cht_max98090_quirk_table);
+       if (dmi_id)
+               quirks = (unsigned long)dmi_id->driver_data;
 
        drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
        if (!drv)
@@ -411,11 +432,16 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
        snd_soc_card_cht.dev = &pdev->dev;
        snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
 
-       drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
+       if (quirks & QUIRK_PMC_PLT_CLK_0)
+               mclk_name = "pmc_plt_clk_0";
+       else
+               mclk_name = "pmc_plt_clk_3";
+
+       drv->mclk = devm_clk_get(&pdev->dev, mclk_name);
        if (IS_ERR(drv->mclk)) {
                dev_err(&pdev->dev,
-                       "Failed to get MCLK from pmc_plt_clk_3: %ld\n",
-                       PTR_ERR(drv->mclk));
+                       "Failed to get MCLK from %s: %ld\n",
+                       mclk_name, PTR_ERR(drv->mclk));
                return PTR_ERR(drv->mclk);
        }
 
index 2922562..7487f38 100644 (file)
@@ -37,7 +37,9 @@
 #include "skl.h"
 #include "skl-sst-dsp.h"
 #include "skl-sst-ipc.h"
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
 #include "../../../soc/codecs/hdac_hda.h"
+#endif
 
 /*
  * initialize the PCI registers
@@ -658,6 +660,8 @@ static void skl_clock_device_unregister(struct skl *skl)
                platform_device_unregister(skl->clk_dev);
 }
 
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
+
 #define IDISP_INTEL_VENDOR_ID  0x80860000
 
 /*
@@ -676,6 +680,8 @@ static void load_codec_module(struct hda_codec *codec)
 #endif
 }
 
+#endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */
+
 /*
  * Probe the given codec address
  */
@@ -685,9 +691,11 @@ static int probe_codec(struct hdac_bus *bus, int addr)
                (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
        unsigned int res = -1;
        struct skl *skl = bus_to_skl(bus);
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
        struct hdac_hda_priv *hda_codec;
-       struct hdac_device *hdev;
        int err;
+#endif
+       struct hdac_device *hdev;
 
        mutex_lock(&bus->cmd_mutex);
        snd_hdac_bus_send_cmd(bus, cmd);
@@ -697,6 +705,7 @@ static int probe_codec(struct hdac_bus *bus, int addr)
                return -EIO;
        dev_dbg(bus->dev, "codec #%d probed OK: %x\n", addr, res);
 
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
        hda_codec = devm_kzalloc(&skl->pci->dev, sizeof(*hda_codec),
                                 GFP_KERNEL);
        if (!hda_codec)
@@ -715,6 +724,13 @@ static int probe_codec(struct hdac_bus *bus, int addr)
                load_codec_module(&hda_codec->codec);
        }
        return 0;
+#else
+       hdev = devm_kzalloc(&skl->pci->dev, sizeof(*hdev), GFP_KERNEL);
+       if (!hdev)
+               return -ENOMEM;
+
+       return snd_hdac_ext_bus_device_init(bus, addr, hdev);
+#endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */
 }
 
 /* Codec initialization */
@@ -815,6 +831,12 @@ static void skl_probe_work(struct work_struct *work)
                }
        }
 
+       /*
+        * we are done probing so decrement link counts
+        */
+       list_for_each_entry(hlink, &bus->hlink_list, list)
+               snd_hdac_ext_bus_link_put(bus, hlink);
+
        if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
                err = snd_hdac_display_power(bus, false);
                if (err < 0) {
@@ -824,12 +846,6 @@ static void skl_probe_work(struct work_struct *work)
                }
        }
 
-       /*
-        * we are done probing so decrement link counts
-        */
-       list_for_each_entry(hlink, &bus->hlink_list, list)
-               snd_hdac_ext_bus_link_put(bus, hlink);
-
        /* configure PM */
        pm_runtime_put_noidle(bus->dev);
        pm_runtime_allow(bus->dev);
@@ -870,7 +886,7 @@ static int skl_create(struct pci_dev *pci,
        hbus = skl_to_hbus(skl);
        bus = skl_to_bus(skl);
 
-#if IS_ENABLED(CONFIG_SND_SOC_HDAC_HDA)
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
        ext_ops = snd_soc_hdac_hda_get_ops();
 #endif
        snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops, ext_ops);
index d5ae9eb..fed45b4 100644 (file)
@@ -36,6 +36,8 @@
 #include "../codecs/twl6040.h"
 
 struct abe_twl6040 {
+       struct snd_soc_card card;
+       struct snd_soc_dai_link dai_links[2];
        int     jack_detection; /* board can detect jack events */
        int     mclk_freq;      /* MCLK frequency speed for twl6040 */
 };
@@ -208,40 +210,10 @@ static int omap_abe_dmic_init(struct snd_soc_pcm_runtime *rtd)
                                ARRAY_SIZE(dmic_audio_map));
 }
 
-/* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link abe_twl6040_dai_links[] = {
-       {
-               .name = "TWL6040",
-               .stream_name = "TWL6040",
-               .codec_dai_name = "twl6040-legacy",
-               .codec_name = "twl6040-codec",
-               .init = omap_abe_twl6040_init,
-               .ops = &omap_abe_ops,
-       },
-       {
-               .name = "DMIC",
-               .stream_name = "DMIC Capture",
-               .codec_dai_name = "dmic-hifi",
-               .codec_name = "dmic-codec",
-               .init = omap_abe_dmic_init,
-               .ops = &omap_abe_dmic_ops,
-       },
-};
-
-/* Audio machine driver */
-static struct snd_soc_card omap_abe_card = {
-       .owner = THIS_MODULE,
-
-       .dapm_widgets = twl6040_dapm_widgets,
-       .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets),
-       .dapm_routes = audio_map,
-       .num_dapm_routes = ARRAY_SIZE(audio_map),
-};
-
 static int omap_abe_probe(struct platform_device *pdev)
 {
        struct device_node *node = pdev->dev.of_node;
-       struct snd_soc_card *card = &omap_abe_card;
+       struct snd_soc_card *card;
        struct device_node *dai_node;
        struct abe_twl6040 *priv;
        int num_links = 0;
@@ -252,12 +224,18 @@ static int omap_abe_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       card->dev = &pdev->dev;
-
        priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL);
        if (priv == NULL)
                return -ENOMEM;
 
+       card = &priv->card;
+       card->dev = &pdev->dev;
+       card->owner = THIS_MODULE;
+       card->dapm_widgets = twl6040_dapm_widgets;
+       card->num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets);
+       card->dapm_routes = audio_map;
+       card->num_dapm_routes = ARRAY_SIZE(audio_map);
+
        if (snd_soc_of_parse_card_name(card, "ti,model")) {
                dev_err(&pdev->dev, "Card name is not provided\n");
                return -ENODEV;
@@ -274,14 +252,27 @@ static int omap_abe_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "McPDM node is not provided\n");
                return -EINVAL;
        }
-       abe_twl6040_dai_links[0].cpu_of_node = dai_node;
-       abe_twl6040_dai_links[0].platform_of_node = dai_node;
+
+       priv->dai_links[0].name = "DMIC";
+       priv->dai_links[0].stream_name = "TWL6040";
+       priv->dai_links[0].cpu_of_node = dai_node;
+       priv->dai_links[0].platform_of_node = dai_node;
+       priv->dai_links[0].codec_dai_name = "twl6040-legacy";
+       priv->dai_links[0].codec_name = "twl6040-codec";
+       priv->dai_links[0].init = omap_abe_twl6040_init;
+       priv->dai_links[0].ops = &omap_abe_ops;
 
        dai_node = of_parse_phandle(node, "ti,dmic", 0);
        if (dai_node) {
                num_links = 2;
-               abe_twl6040_dai_links[1].cpu_of_node = dai_node;
-               abe_twl6040_dai_links[1].platform_of_node = dai_node;
+               priv->dai_links[1].name = "TWL6040";
+               priv->dai_links[1].stream_name = "DMIC Capture";
+               priv->dai_links[1].cpu_of_node = dai_node;
+               priv->dai_links[1].platform_of_node = dai_node;
+               priv->dai_links[1].codec_dai_name = "dmic-hifi";
+               priv->dai_links[1].codec_name = "dmic-codec";
+               priv->dai_links[1].init = omap_abe_dmic_init;
+               priv->dai_links[1].ops = &omap_abe_dmic_ops;
        } else {
                num_links = 1;
        }
@@ -300,7 +291,7 @@ static int omap_abe_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       card->dai_link = abe_twl6040_dai_links;
+       card->dai_link = priv->dai_links;
        card->num_links = num_links;
 
        snd_soc_card_set_drvdata(card, priv);
index fe96627..cba9645 100644 (file)
@@ -48,6 +48,8 @@ struct omap_dmic {
        struct device *dev;
        void __iomem *io_base;
        struct clk *fclk;
+       struct pm_qos_request pm_qos_req;
+       int latency;
        int fclk_freq;
        int out_freq;
        int clk_div;
@@ -124,6 +126,8 @@ static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream,
 
        mutex_lock(&dmic->mutex);
 
+       pm_qos_remove_request(&dmic->pm_qos_req);
+
        if (!dai->active)
                dmic->active = 0;
 
@@ -228,6 +232,8 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
        /* packet size is threshold * channels */
        dma_data = snd_soc_dai_get_dma_data(dai, substream);
        dma_data->maxburst = dmic->threshold * channels;
+       dmic->latency = (OMAP_DMIC_THRES_MAX - dmic->threshold) * USEC_PER_SEC /
+                       params_rate(params);
 
        return 0;
 }
@@ -238,6 +244,9 @@ static int omap_dmic_dai_prepare(struct snd_pcm_substream *substream,
        struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
        u32 ctrl;
 
+       if (pm_qos_request_active(&dmic->pm_qos_req))
+               pm_qos_update_request(&dmic->pm_qos_req, dmic->latency);
+
        /* Configure uplink threshold */
        omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold);
 
index d0ebb6b..2d6decb 100644 (file)
@@ -308,9 +308,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
                        pkt_size = channels;
                }
 
-               latency = ((((buffer_size - pkt_size) / channels) * 1000)
-                                / (params->rate_num / params->rate_den));
-
+               latency = (buffer_size - pkt_size) / channels;
+               latency = latency * USEC_PER_SEC /
+                         (params->rate_num / params->rate_den);
                mcbsp->latency[substream->stream] = latency;
 
                omap_mcbsp_set_threshold(substream, pkt_size);
index 4c1be36..7d5bdc5 100644 (file)
@@ -54,6 +54,8 @@ struct omap_mcpdm {
        unsigned long phys_base;
        void __iomem *io_base;
        int irq;
+       struct pm_qos_request pm_qos_req;
+       int latency[2];
 
        struct mutex mutex;
 
@@ -277,6 +279,9 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
                                  struct snd_soc_dai *dai)
 {
        struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+       int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
+       int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
 
        mutex_lock(&mcpdm->mutex);
 
@@ -289,6 +294,14 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
                }
        }
 
+       if (mcpdm->latency[stream2])
+               pm_qos_update_request(&mcpdm->pm_qos_req,
+                                     mcpdm->latency[stream2]);
+       else if (mcpdm->latency[stream1])
+               pm_qos_remove_request(&mcpdm->pm_qos_req);
+
+       mcpdm->latency[stream1] = 0;
+
        mutex_unlock(&mcpdm->mutex);
 }
 
@@ -300,7 +313,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
        int stream = substream->stream;
        struct snd_dmaengine_dai_dma_data *dma_data;
        u32 threshold;
-       int channels;
+       int channels, latency;
        int link_mask = 0;
 
        channels = params_channels(params);
@@ -344,14 +357,25 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
 
                dma_data->maxburst =
                                (MCPDM_DN_THRES_MAX - threshold) * channels;
+               latency = threshold;
        } else {
                /* If playback is not running assume a stereo stream to come */
                if (!mcpdm->config[!stream].link_mask)
                        mcpdm->config[!stream].link_mask = (0x3 << 3);
 
                dma_data->maxburst = threshold * channels;
+               latency = (MCPDM_DN_THRES_MAX - threshold);
        }
 
+       /*
+        * The DMA must act to a DMA request within latency time (usec) to avoid
+        * under/overflow
+        */
+       mcpdm->latency[stream] = latency * USEC_PER_SEC / params_rate(params);
+
+       if (!mcpdm->latency[stream])
+               mcpdm->latency[stream] = 10;
+
        /* Check if we need to restart McPDM with this stream */
        if (mcpdm->config[stream].link_mask &&
            mcpdm->config[stream].link_mask != link_mask)
@@ -366,6 +390,20 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
                                  struct snd_soc_dai *dai)
 {
        struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+       struct pm_qos_request *pm_qos_req = &mcpdm->pm_qos_req;
+       int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
+       int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
+       int latency = mcpdm->latency[stream2];
+
+       /* Prevent omap hardware from hitting off between FIFO fills */
+       if (!latency || mcpdm->latency[stream1] < latency)
+               latency = mcpdm->latency[stream1];
+
+       if (pm_qos_request_active(pm_qos_req))
+               pm_qos_update_request(pm_qos_req, latency);
+       else if (latency)
+               pm_qos_add_request(pm_qos_req, PM_QOS_CPU_DMA_LATENCY, latency);
 
        if (!omap_mcpdm_active(mcpdm)) {
                omap_mcpdm_start(mcpdm);
@@ -427,6 +465,9 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
        free_irq(mcpdm->irq, (void *)mcpdm);
        pm_runtime_disable(mcpdm->dev);
 
+       if (pm_qos_request_active(&mcpdm->pm_qos_req))
+               pm_qos_remove_request(&mcpdm->pm_qos_req);
+
        return 0;
 }
 
index eb1b9da..4715527 100644 (file)
@@ -13,6 +13,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
        struct device_node *cpu = NULL;
        struct device *dev = card->dev;
        struct snd_soc_dai_link *link;
+       struct of_phandle_args args;
        int ret, num_links;
 
        ret = snd_soc_of_parse_card_name(card, "model");
@@ -47,12 +48,14 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
                        goto err;
                }
 
-               link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0);
-               if (!link->cpu_of_node) {
+               ret = of_parse_phandle_with_args(cpu, "sound-dai",
+                                       "#sound-dai-cells", 0, &args);
+               if (ret) {
                        dev_err(card->dev, "error getting cpu phandle\n");
-                       ret = -EINVAL;
                        goto err;
                }
+               link->cpu_of_node = args.np;
+               link->id = args.args[0];
 
                ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name);
                if (ret) {
index 60ff4a2..8f6c8fc 100644 (file)
@@ -1112,204 +1112,204 @@ static int q6afe_of_xlate_dai_name(struct snd_soc_component *component,
 }
 
 static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = {
-       SND_SOC_DAPM_AIF_OUT("HDMI_RX", "HDMI Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_RX", "Slimbus1 Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_RX", "Slimbus2 Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_RX", "Slimbus3 Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_RX", "Slimbus4 Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_RX", "Slimbus5 Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_RX", "Slimbus6 Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_1_TX", "Slimbus1 Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_2_TX", "Slimbus2 Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_3_TX", "Slimbus3 Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_4_TX", "Slimbus4 Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_5_TX", "Slimbus5 Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_6_TX", "Slimbus6 Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_RX", "Quaternary MI2S Playback",
+       SND_SOC_DAPM_AIF_IN("HDMI_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_0_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_1_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_2_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_3_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_4_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_5_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_6_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("QUAT_MI2S_RX", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX", "Quaternary MI2S Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_TX", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_MI2S_RX", "Tertiary MI2S Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_MI2S_RX", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_MI2S_TX", "Tertiary MI2S Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_MI2S_TX", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX", "Secondary MI2S Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX", "Secondary MI2S Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_MI2S_TX", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX_SD1",
+       SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX_SD1",
                        "Secondary MI2S Playback SD1",
                        0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRI_MI2S_RX", "Primary MI2S Playback",
+       SND_SOC_DAPM_AIF_IN("PRI_MI2S_RX", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRI_MI2S_TX", "Primary MI2S Capture",
+       SND_SOC_DAPM_AIF_OUT("PRI_MI2S_TX", NULL,
                                                0, 0, 0, 0),
 
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_0", "Primary TDM0 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_0", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_1", "Primary TDM1 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_1", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_2", "Primary TDM2 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_2", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_3", "Primary TDM3 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_3", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_4", "Primary TDM4 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_4", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_5", "Primary TDM5 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_5", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_6", "Primary TDM6 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_6", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_7", "Primary TDM7 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_7", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_0", "Primary TDM0 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_0", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_1", "Primary TDM1 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_1", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_2", "Primary TDM2 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_2", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_3", "Primary TDM3 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_3", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_4", "Primary TDM4 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_4", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_5", "Primary TDM5 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_5", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_6", "Primary TDM6 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_6", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_7", "Primary TDM7 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_7", NULL,
                                                0, 0, 0, 0),
 
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_0", "Secondary TDM0 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_0", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_1", "Secondary TDM1 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_1", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_2", "Secondary TDM2 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_2", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_3", "Secondary TDM3 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_3", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_4", "Secondary TDM4 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_4", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_5", "Secondary TDM5 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_5", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_6", "Secondary TDM6 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_6", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_7", "Secondary TDM7 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_7", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_0", "Secondary TDM0 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_0", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_1", "Secondary TDM1 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_1", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_2", "Secondary TDM2 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_2", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_3", "Secondary TDM3 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_3", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_4", "Secondary TDM4 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_4", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_5", "Secondary TDM5 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_5", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_6", "Secondary TDM6 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_6", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_7", "Secondary TDM7 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_7", NULL,
                                                0, 0, 0, 0),
 
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_0", "Tertiary TDM0 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_0", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_1", "Tertiary TDM1 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_1", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_2", "Tertiary TDM2 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_2", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_3", "Tertiary TDM3 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_3", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_4", "Tertiary TDM4 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_4", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_5", "Tertiary TDM5 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_5", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_6", "Tertiary TDM6 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_6", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_7", "Tertiary TDM7 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_7", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_0", "Tertiary TDM0 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_0", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_1", "Tertiary TDM1 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_1", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_2", "Tertiary TDM2 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_2", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_3", "Tertiary TDM3 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_3", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_4", "Tertiary TDM4 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_4", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_5", "Tertiary TDM5 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_5", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_6", "Tertiary TDM6 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_6", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_7", "Tertiary TDM7 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_7", NULL,
                                                0, 0, 0, 0),
 
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_0", "Quaternary TDM0 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_0", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_1", "Quaternary TDM1 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_1", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_2", "Quaternary TDM2 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_2", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_3", "Quaternary TDM3 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_3", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_4", "Quaternary TDM4 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_4", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_5", "Quaternary TDM5 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_5", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_6", "Quaternary TDM6 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_6", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_7", "Quaternary TDM7 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_7", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_0", "Quaternary TDM0 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_0", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_1", "Quaternary TDM1 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_1", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_2", "Quaternary TDM2 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_2", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_3", "Quaternary TDM3 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_3", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_4", "Quaternary TDM4 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_4", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_5", "Quaternary TDM5 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_5", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_6", "Quaternary TDM6 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_6", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_7", "Quaternary TDM7 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_7", NULL,
                                                0, 0, 0, 0),
 
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_0", "Quinary TDM0 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_0", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_1", "Quinary TDM1 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_1", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_2", "Quinary TDM2 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_2", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_3", "Quinary TDM3 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_3", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_4", "Quinary TDM4 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_4", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_5", "Quinary TDM5 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_5", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_6", "Quinary TDM6 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_6", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_7", "Quinary TDM7 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_7", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_0", "Quinary TDM0 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_0", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_1", "Quinary TDM1 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_1", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_2", "Quinary TDM2 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_2", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_3", "Quinary TDM3 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_3", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_4", "Quinary TDM4 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_4", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_5", "Quinary TDM5 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_5", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_6", "Quinary TDM6 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_6", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_7", "Quinary TDM7 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_7", NULL,
                                                0, 0, 0, 0),
 };
 
index 000775b..829b5e9 100644 (file)
 #define AFE_PORT_I2S_SD1               0x2
 #define AFE_PORT_I2S_SD2               0x3
 #define AFE_PORT_I2S_SD3               0x4
-#define AFE_PORT_I2S_SD0_MASK          BIT(0x1)
-#define AFE_PORT_I2S_SD1_MASK          BIT(0x2)
-#define AFE_PORT_I2S_SD2_MASK          BIT(0x3)
-#define AFE_PORT_I2S_SD3_MASK          BIT(0x4)
-#define AFE_PORT_I2S_SD0_1_MASK                GENMASK(2, 1)
-#define AFE_PORT_I2S_SD2_3_MASK                GENMASK(4, 3)
-#define AFE_PORT_I2S_SD0_1_2_MASK      GENMASK(3, 1)
-#define AFE_PORT_I2S_SD0_1_2_3_MASK    GENMASK(4, 1)
+#define AFE_PORT_I2S_SD0_MASK          BIT(0x0)
+#define AFE_PORT_I2S_SD1_MASK          BIT(0x1)
+#define AFE_PORT_I2S_SD2_MASK          BIT(0x2)
+#define AFE_PORT_I2S_SD3_MASK          BIT(0x3)
+#define AFE_PORT_I2S_SD0_1_MASK                GENMASK(1, 0)
+#define AFE_PORT_I2S_SD2_3_MASK                GENMASK(3, 2)
+#define AFE_PORT_I2S_SD0_1_2_MASK      GENMASK(2, 0)
+#define AFE_PORT_I2S_SD0_1_2_3_MASK    GENMASK(3, 0)
 #define AFE_PORT_I2S_QUAD01            0x5
 #define AFE_PORT_I2S_QUAD23            0x6
 #define AFE_PORT_I2S_6CHS              0x7
index a16c71c..86115de 100644 (file)
@@ -122,7 +122,6 @@ static struct snd_pcm_hardware q6asm_dai_hardware_playback = {
                        .rate_max =     48000,                          \
                },                                                      \
                .name = "MultiMedia"#num,                               \
-               .probe = fe_dai_probe,                                  \
                .id = MSM_FRONTEND_DAI_MULTIMEDIA##num,                 \
        }
 
@@ -511,38 +510,6 @@ static void q6asm_dai_pcm_free(struct snd_pcm *pcm)
        }
 }
 
-static const struct snd_soc_dapm_route afe_pcm_routes[] = {
-       {"MM_DL1",  NULL, "MultiMedia1 Playback" },
-       {"MM_DL2",  NULL, "MultiMedia2 Playback" },
-       {"MM_DL3",  NULL, "MultiMedia3 Playback" },
-       {"MM_DL4",  NULL, "MultiMedia4 Playback" },
-       {"MM_DL5",  NULL, "MultiMedia5 Playback" },
-       {"MM_DL6",  NULL, "MultiMedia6 Playback" },
-       {"MM_DL7",  NULL, "MultiMedia7 Playback" },
-       {"MM_DL7",  NULL, "MultiMedia8 Playback" },
-       {"MultiMedia1 Capture", NULL, "MM_UL1"},
-       {"MultiMedia2 Capture", NULL, "MM_UL2"},
-       {"MultiMedia3 Capture", NULL, "MM_UL3"},
-       {"MultiMedia4 Capture", NULL, "MM_UL4"},
-       {"MultiMedia5 Capture", NULL, "MM_UL5"},
-       {"MultiMedia6 Capture", NULL, "MM_UL6"},
-       {"MultiMedia7 Capture", NULL, "MM_UL7"},
-       {"MultiMedia8 Capture", NULL, "MM_UL8"},
-
-};
-
-static int fe_dai_probe(struct snd_soc_dai *dai)
-{
-       struct snd_soc_dapm_context *dapm;
-
-       dapm = snd_soc_component_get_dapm(dai->component);
-       snd_soc_dapm_add_routes(dapm, afe_pcm_routes,
-                               ARRAY_SIZE(afe_pcm_routes));
-
-       return 0;
-}
-
-
 static const struct snd_soc_component_driver q6asm_fe_dai_component = {
        .name           = DRV_NAME,
        .ops            = &q6asm_dai_ops,
index c6b5157..d61b840 100644 (file)
@@ -909,6 +909,25 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"MM_UL6", NULL, "MultiMedia6 Mixer"},
        {"MM_UL7", NULL, "MultiMedia7 Mixer"},
        {"MM_UL8", NULL, "MultiMedia8 Mixer"},
+
+       {"MM_DL1",  NULL, "MultiMedia1 Playback" },
+       {"MM_DL2",  NULL, "MultiMedia2 Playback" },
+       {"MM_DL3",  NULL, "MultiMedia3 Playback" },
+       {"MM_DL4",  NULL, "MultiMedia4 Playback" },
+       {"MM_DL5",  NULL, "MultiMedia5 Playback" },
+       {"MM_DL6",  NULL, "MultiMedia6 Playback" },
+       {"MM_DL7",  NULL, "MultiMedia7 Playback" },
+       {"MM_DL8",  NULL, "MultiMedia8 Playback" },
+
+       {"MultiMedia1 Capture", NULL, "MM_UL1"},
+       {"MultiMedia2 Capture", NULL, "MM_UL2"},
+       {"MultiMedia3 Capture", NULL, "MM_UL3"},
+       {"MultiMedia4 Capture", NULL, "MM_UL4"},
+       {"MultiMedia5 Capture", NULL, "MM_UL5"},
+       {"MultiMedia6 Capture", NULL, "MM_UL6"},
+       {"MultiMedia7 Capture", NULL, "MM_UL7"},
+       {"MultiMedia8 Capture", NULL, "MM_UL8"},
+
 };
 
 static int routing_hw_params(struct snd_pcm_substream *substream,
index 9e7b5fa..4ac78d7 100644 (file)
@@ -33,6 +33,7 @@ static const struct snd_pcm_hardware snd_rockchip_hardware = {
 
 static const struct snd_dmaengine_pcm_config rk_dmaengine_pcm_config = {
        .pcm_hardware = &snd_rockchip_hardware,
+       .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
        .prealloc_buffer_size = 32 * 1024,
 };
 
index fcb4df2..6ec78f3 100644 (file)
@@ -306,7 +306,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
        if (rsnd_ssi_is_multi_slave(mod, io))
                return 0;
 
-       if (ssi->rate) {
+       if (ssi->usrcnt > 1) {
                if (ssi->rate != rate) {
                        dev_err(dev, "SSI parent/child should use same rate\n");
                        return -EINVAL;
index b8e72b5..4fb29f0 100644 (file)
@@ -10,11 +10,17 @@ struct snd_soc_acpi_mach *
 snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines)
 {
        struct snd_soc_acpi_mach *mach;
+       struct snd_soc_acpi_mach *mach_alt;
 
        for (mach = machines; mach->id[0]; mach++) {
                if (acpi_dev_present(mach->id, NULL, -1)) {
-                       if (mach->machine_quirk)
-                               mach = mach->machine_quirk(mach);
+                       if (mach->machine_quirk) {
+                               mach_alt = mach->machine_quirk(mach);
+                               if (!mach_alt)
+                                       continue; /* not full match, ignore */
+                               mach = mach_alt;
+                       }
+
                        return mach;
                }
        }
index 6ddcf12..b29d0f6 100644 (file)
@@ -2131,6 +2131,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
        }
 
        card->instantiated = 1;
+       dapm_mark_endpoints_dirty(card);
        snd_soc_dapm_sync(&card->dapm);
        mutex_unlock(&card->mutex);
        mutex_unlock(&client_mutex);
index ea05cc9..211589b 100644 (file)
@@ -390,7 +390,7 @@ static int stm32_sai_add_mclk_provider(struct stm32_sai_sub_data *sai)
        char *mclk_name, *p, *s = (char *)pname;
        int ret, i = 0;
 
-       mclk = devm_kzalloc(dev, sizeof(mclk), GFP_KERNEL);
+       mclk = devm_kzalloc(dev, sizeof(*mclk), GFP_KERNEL);
        if (!mclk)
                return -ENOMEM;
 
index 66aad0d..8134c3c 100644 (file)
@@ -31,7 +31,7 @@ config SND_SUN8I_CODEC_ANALOG
 config SND_SUN50I_CODEC_ANALOG
        tristate "Allwinner sun50i Codec Analog Controls Support"
        depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
-       select SND_SUNXI_ADDA_PR_REGMAP
+       select SND_SUN8I_ADDA_PR_REGMAP
        help
          Say Y or M if you want to add support for the analog controls for
          the codec embedded in Allwinner A64 SoC.
index 522a72f..92c5de0 100644 (file)
@@ -481,7 +481,11 @@ static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = {
        { "Right Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch",
          "AIF1 Slot 0 Right"},
 
-       /* ADC routes */
+       /* ADC Routes */
+       { "AIF1 Slot 0 Right ADC", NULL, "ADC" },
+       { "AIF1 Slot 0 Left ADC", NULL, "ADC" },
+
+       /* ADC Mixer Routes */
        { "Left Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch",
          "AIF1 Slot 0 Left ADC" },
        { "Right Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch",
@@ -605,16 +609,10 @@ err_pm_disable:
 
 static int sun8i_codec_remove(struct platform_device *pdev)
 {
-       struct snd_soc_card *card = platform_get_drvdata(pdev);
-       struct sun8i_codec *scodec = snd_soc_card_get_drvdata(card);
-
        pm_runtime_disable(&pdev->dev);
        if (!pm_runtime_status_suspended(&pdev->dev))
                sun8i_codec_runtime_suspend(&pdev->dev);
 
-       clk_disable_unprepare(scodec->clk_module);
-       clk_disable_unprepare(scodec->clk_bus);
-
        return 0;
 }
 
index e73c962..079063d 100644 (file)
@@ -1146,10 +1146,8 @@ static int snd_cs4231_playback_open(struct snd_pcm_substream *substream)
        runtime->hw = snd_cs4231_playback;
 
        err = snd_cs4231_open(chip, CS4231_MODE_PLAY);
-       if (err < 0) {
-               snd_free_pages(runtime->dma_area, runtime->dma_bytes);
+       if (err < 0)
                return err;
-       }
        chip->playback_substream = substream;
        chip->p_periods_sent = 0;
        snd_pcm_set_sync(substream);
@@ -1167,10 +1165,8 @@ static int snd_cs4231_capture_open(struct snd_pcm_substream *substream)
        runtime->hw = snd_cs4231_capture;
 
        err = snd_cs4231_open(chip, CS4231_MODE_RECORD);
-       if (err < 0) {
-               snd_free_pages(runtime->dma_area, runtime->dma_bytes);
+       if (err < 0)
                return err;
-       }
        chip->capture_substream = substream;
        chip->c_periods_sent = 0;
        snd_pcm_set_sync(substream);
index 2bfe4e8..a105947 100644 (file)
@@ -682,9 +682,12 @@ static int usb_audio_probe(struct usb_interface *intf,
 
  __error:
        if (chip) {
+               /* chip->active is inside the chip->card object,
+                * decrement before memory is possibly returned.
+                */
+               atomic_dec(&chip->active);
                if (!chip->num_interfaces)
                        snd_card_free(chip->card);
-               atomic_dec(&chip->active);
        }
        mutex_unlock(&register_mutex);
        return err;
index 849953e..37fc044 100644 (file)
@@ -3382,5 +3382,15 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                .ifnum = QUIRK_NO_INTERFACE
        }
 },
+/* Dell WD19 Dock */
+{
+       USB_DEVICE(0x0bda, 0x402e),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .vendor_name = "Dell",
+               .product_name = "WD19 Dock",
+               .profile_name = "Dell-WD15-Dock",
+               .ifnum = QUIRK_NO_INTERFACE
+       }
+},
 
 #undef USB_DEVICE_VENDOR_SPEC
index 8a945ec..6623caf 100644 (file)
@@ -1373,6 +1373,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
 
+       case USB_ID(0x152a, 0x85de): /* SMSL D1 DAC */
        case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
        case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */
        case USB_ID(0x16b0, 0x06b2): /* NuPrime DAC-10 */
index 89a048c..28c4a50 100644 (file)
 #define X86_FEATURE_LA57               (16*32+16) /* 5-level page tables */
 #define X86_FEATURE_RDPID              (16*32+22) /* RDPID instruction */
 #define X86_FEATURE_CLDEMOTE           (16*32+25) /* CLDEMOTE instruction */
+#define X86_FEATURE_MOVDIRI            (16*32+27) /* MOVDIRI instruction */
+#define X86_FEATURE_MOVDIR64B          (16*32+28) /* MOVDIR64B instruction */
 
 /* AMD-defined CPU features, CPUID level 0x80000007 (EBX), word 17 */
 #define X86_FEATURE_OVERFLOW_RECOV     (17*32+ 0) /* MCA overflow recovery support */
index f216b2f..d74bb94 100644 (file)
@@ -33,6 +33,7 @@ FEATURE_TESTS_BASIC :=                  \
         dwarf_getlocations              \
         fortify-source                  \
         sync-compare-and-swap           \
+        get_current_dir_name            \
         glibc                           \
         gtk2                            \
         gtk2-infobar                    \
index 0516259..304b984 100644 (file)
@@ -7,6 +7,7 @@ FILES=                                          \
          test-dwarf_getlocations.bin            \
          test-fortify-source.bin                \
          test-sync-compare-and-swap.bin         \
+         test-get_current_dir_name.bin          \
          test-glibc.bin                         \
          test-gtk2.bin                          \
          test-gtk2-infobar.bin                  \
@@ -101,6 +102,9 @@ $(OUTPUT)test-bionic.bin:
 $(OUTPUT)test-libelf.bin:
        $(BUILD) -lelf
 
+$(OUTPUT)test-get_current_dir_name.bin:
+       $(BUILD)
+
 $(OUTPUT)test-glibc.bin:
        $(BUILD)
 
index 8dc20a6..56722bf 100644 (file)
 # include "test-libelf-mmap.c"
 #undef main
 
+#define main main_test_get_current_dir_name
+# include "test-get_current_dir_name.c"
+#undef main
+
 #define main main_test_glibc
 # include "test-glibc.c"
 #undef main
@@ -174,6 +178,7 @@ int main(int argc, char *argv[])
        main_test_hello();
        main_test_libelf();
        main_test_libelf_mmap();
+       main_test_get_current_dir_name();
        main_test_glibc();
        main_test_dwarf();
        main_test_dwarf_getlocations();
diff --git a/tools/build/feature/test-get_current_dir_name.c b/tools/build/feature/test-get_current_dir_name.c
new file mode 100644 (file)
index 0000000..573000f
--- /dev/null
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+
+int main(void)
+{
+       free(get_current_dir_name());
+       return 0;
+}
index 0406517..cdc9f4c 100644 (file)
@@ -79,6 +79,8 @@
 #define TIOCGPTLCK     _IOR('T', 0x39, int) /* Get Pty lock state */
 #define TIOCGEXCL      _IOR('T', 0x40, int) /* Get exclusive mode state */
 #define TIOCGPTPEER    _IO('T', 0x41) /* Safely open the slave */
+#define TIOCGISO7816   _IOR('T', 0x42, struct serial_iso7816)
+#define TIOCSISO7816   _IOWR('T', 0x43, struct serial_iso7816)
 
 #define FIONCLEX       0x5450
 #define FIOCLEX                0x5451
index 7f5634c..a4446f4 100644 (file)
@@ -529,6 +529,28 @@ typedef struct drm_i915_irq_wait {
  */
 #define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51
 
+/*
+ * Once upon a time we supposed that writes through the GGTT would be
+ * immediately in physical memory (once flushed out of the CPU path). However,
+ * on a few different processors and chipsets, this is not necessarily the case
+ * as the writes appear to be buffered internally. Thus a read of the backing
+ * storage (physical memory) via a different path (with different physical tags
+ * to the indirect write via the GGTT) will see stale values from before
+ * the GGTT write. Inside the kernel, we can for the most part keep track of
+ * the different read/write domains in use (e.g. set-domain), but the assumption
+ * of coherency is baked into the ABI, hence reporting its true state in this
+ * parameter.
+ *
+ * Reports true when writes via mmap_gtt are immediately visible following an
+ * lfence to flush the WCB.
+ *
+ * Reports false when writes via mmap_gtt are indeterminately delayed in an in
+ * internal buffer and are _not_ immediately visible to third parties accessing
+ * directly via mmap_cpu/mmap_wc. Use of mmap_gtt as part of an IPC
+ * communications channel when reporting false is strongly disadvised.
+ */
+#define I915_PARAM_MMAP_GTT_COHERENT   52
+
 typedef struct drm_i915_getparam {
        __s32 param;
        /*
index c0d7ea0..b17201e 100644 (file)
@@ -212,6 +212,7 @@ struct prctl_mm_map {
 #define PR_SET_SPECULATION_CTRL                53
 /* Speculation control variants */
 # define PR_SPEC_STORE_BYPASS          0
+# define PR_SPEC_INDIRECT_BRANCH       1
 /* Return and control values for PR_SET/GET_SPECULATION_CTRL */
 # define PR_SPEC_NOT_AFFECTED          0
 # define PR_SPEC_PRCTL                 (1UL << 0)
index 6dbb9fa..b8f3cca 100644 (file)
@@ -31,6 +31,8 @@
 #include "elf.h"
 #include "warn.h"
 
+#define MAX_NAME_LEN 128
+
 struct section *find_section_by_name(struct elf *elf, const char *name)
 {
        struct section *sec;
@@ -298,6 +300,8 @@ static int read_symbols(struct elf *elf)
        /* Create parent/child links for any cold subfunctions */
        list_for_each_entry(sec, &elf->sections, list) {
                list_for_each_entry(sym, &sec->symbol_list, list) {
+                       char pname[MAX_NAME_LEN + 1];
+                       size_t pnamelen;
                        if (sym->type != STT_FUNC)
                                continue;
                        sym->pfunc = sym->cfunc = sym;
@@ -305,14 +309,21 @@ static int read_symbols(struct elf *elf)
                        if (!coldstr)
                                continue;
 
-                       coldstr[0] = '\0';
-                       pfunc = find_symbol_by_name(elf, sym->name);
-                       coldstr[0] = '.';
+                       pnamelen = coldstr - sym->name;
+                       if (pnamelen > MAX_NAME_LEN) {
+                               WARN("%s(): parent function name exceeds maximum length of %d characters",
+                                    sym->name, MAX_NAME_LEN);
+                               return -1;
+                       }
+
+                       strncpy(pname, sym->name, pnamelen);
+                       pname[pnamelen] = '\0';
+                       pfunc = find_symbol_by_name(elf, pname);
 
                        if (!pfunc) {
                                WARN("%s(): can't find parent function",
                                     sym->name);
-                               goto err;
+                               return -1;
                        }
 
                        sym->pfunc = pfunc;
index e30d20f..a0e8c23 100644 (file)
@@ -299,6 +299,11 @@ ifndef NO_BIONIC
   endif
 endif
 
+ifeq ($(feature-get_current_dir_name), 1)
+  CFLAGS += -DHAVE_GET_CURRENT_DIR_NAME
+endif
+
+
 ifdef NO_LIBELF
   NO_DWARF := 1
   NO_DEMANGLE := 1
index 3794066..efd0157 100644 (file)
@@ -9,7 +9,7 @@ size=112
 config=0
 sample_period=*
 sample_type=263
-read_format=0
+read_format=0|4
 disabled=1
 inherit=1
 pinned=0
index 5d2a7fd..eae59ad 100644 (file)
@@ -31,6 +31,7 @@ static size_t ioctl__scnprintf_tty_cmd(int nr, int dir, char *bf, size_t size)
        "TCSETSW2", "TCSETSF2", "TIOCGRS48", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
        "TIOCGDEV", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG", "TIOCVHANGUP", "TIOCGPKT",
        "TIOCGPTLCK", [_IOC_NR(TIOCGEXCL)] = "TIOCGEXCL", "TIOCGPTPEER",
+       "TIOCGISO7816", "TIOCSISO7816",
        [_IOC_NR(FIONCLEX)] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
        "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
        "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
index ecd9f9c..b7bf201 100644 (file)
@@ -10,6 +10,7 @@ libperf-y += evlist.o
 libperf-y += evsel.o
 libperf-y += evsel_fprintf.o
 libperf-y += find_bit.o
+libperf-y += get_current_dir_name.o
 libperf-y += kallsyms.o
 libperf-y += levenshtein.o
 libperf-y += llvm-utils.o
index d37bb15..dbc0466 100644 (file)
@@ -1092,7 +1092,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
                attr->exclude_user   = 1;
        }
 
-       if (evsel->own_cpus)
+       if (evsel->own_cpus || evsel->unit)
                evsel->attr.read_format |= PERF_FORMAT_ID;
 
        /*
diff --git a/tools/perf/util/get_current_dir_name.c b/tools/perf/util/get_current_dir_name.c
new file mode 100644 (file)
index 0000000..267aa60
--- /dev/null
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+//
+#ifndef HAVE_GET_CURRENT_DIR_NAME
+#include "util.h"
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdlib.h>
+
+/* Android's 'bionic' library, for one, doesn't have this */
+
+char *get_current_dir_name(void)
+{
+       char pwd[PATH_MAX];
+
+       return getcwd(pwd, sizeof(pwd)) == NULL ? NULL : strdup(pwd);
+}
+#endif // HAVE_GET_CURRENT_DIR_NAME
index cf8bd12..aed170b 100644 (file)
@@ -18,6 +18,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <asm/bug.h>
 
 struct namespaces *namespaces__new(struct namespaces_event *event)
 {
@@ -186,6 +187,7 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,
        char curpath[PATH_MAX];
        int oldns = -1;
        int newns = -1;
+       char *oldcwd = NULL;
 
        if (nc == NULL)
                return;
@@ -199,9 +201,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,
        if (snprintf(curpath, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
                return;
 
+       oldcwd = get_current_dir_name();
+       if (!oldcwd)
+               return;
+
        oldns = open(curpath, O_RDONLY);
        if (oldns < 0)
-               return;
+               goto errout;
 
        newns = open(nsi->mntns_path, O_RDONLY);
        if (newns < 0)
@@ -210,11 +216,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,
        if (setns(newns, CLONE_NEWNS) < 0)
                goto errout;
 
+       nc->oldcwd = oldcwd;
        nc->oldns = oldns;
        nc->newns = newns;
        return;
 
 errout:
+       free(oldcwd);
        if (oldns > -1)
                close(oldns);
        if (newns > -1)
@@ -223,11 +231,16 @@ errout:
 
 void nsinfo__mountns_exit(struct nscookie *nc)
 {
-       if (nc == NULL || nc->oldns == -1 || nc->newns == -1)
+       if (nc == NULL || nc->oldns == -1 || nc->newns == -1 || !nc->oldcwd)
                return;
 
        setns(nc->oldns, CLONE_NEWNS);
 
+       if (nc->oldcwd) {
+               WARN_ON_ONCE(chdir(nc->oldcwd));
+               zfree(&nc->oldcwd);
+       }
+
        if (nc->oldns > -1) {
                close(nc->oldns);
                nc->oldns = -1;
index cae1a9a..d5f46c0 100644 (file)
@@ -38,6 +38,7 @@ struct nsinfo {
 struct nscookie {
        int                     oldns;
        int                     newns;
+       char                    *oldcwd;
 };
 
 int nsinfo__init(struct nsinfo *nsi);
index 14508ee..ece040b 100644 (file)
@@ -59,6 +59,10 @@ int fetch_kernel_version(unsigned int *puint,
 
 const char *perf_tip(const char *dirpath);
 
+#ifndef HAVE_GET_CURRENT_DIR_NAME
+char *get_current_dir_name(void);
+#endif
+
 #ifndef HAVE_SCHED_GETCPU_SUPPORT
 int sched_getcpu(void);
 #endif
index 01ec04b..6c16ac3 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/workqueue.h>
 #include <linux/libnvdimm.h>
+#include <linux/genalloc.h>
 #include <linux/vmalloc.h>
 #include <linux/device.h>
 #include <linux/module.h>
@@ -215,6 +216,8 @@ struct nfit_test {
 
 static struct workqueue_struct *nfit_wq;
 
+static struct gen_pool *nfit_pool;
+
 static struct nfit_test *to_nfit_test(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
@@ -1132,6 +1135,9 @@ static void release_nfit_res(void *data)
        list_del(&nfit_res->list);
        spin_unlock(&nfit_test_lock);
 
+       if (resource_size(&nfit_res->res) >= DIMM_SIZE)
+               gen_pool_free(nfit_pool, nfit_res->res.start,
+                               resource_size(&nfit_res->res));
        vfree(nfit_res->buf);
        kfree(nfit_res);
 }
@@ -1144,7 +1150,7 @@ static void *__test_alloc(struct nfit_test *t, size_t size, dma_addr_t *dma,
                        GFP_KERNEL);
        int rc;
 
-       if (!buf || !nfit_res)
+       if (!buf || !nfit_res || !*dma)
                goto err;
        rc = devm_add_action(dev, release_nfit_res, nfit_res);
        if (rc)
@@ -1164,6 +1170,8 @@ static void *__test_alloc(struct nfit_test *t, size_t size, dma_addr_t *dma,
 
        return nfit_res->buf;
  err:
+       if (*dma && size >= DIMM_SIZE)
+               gen_pool_free(nfit_pool, *dma, size);
        if (buf)
                vfree(buf);
        kfree(nfit_res);
@@ -1172,9 +1180,16 @@ static void *__test_alloc(struct nfit_test *t, size_t size, dma_addr_t *dma,
 
 static void *test_alloc(struct nfit_test *t, size_t size, dma_addr_t *dma)
 {
+       struct genpool_data_align data = {
+               .align = SZ_128M,
+       };
        void *buf = vmalloc(size);
 
-       *dma = (unsigned long) buf;
+       if (size >= DIMM_SIZE)
+               *dma = gen_pool_alloc_algo(nfit_pool, size,
+                               gen_pool_first_fit_align, &data);
+       else
+               *dma = (unsigned long) buf;
        return __test_alloc(t, size, dma, buf);
 }
 
@@ -2839,6 +2854,17 @@ static __init int nfit_test_init(void)
                goto err_register;
        }
 
+       nfit_pool = gen_pool_create(ilog2(SZ_4M), NUMA_NO_NODE);
+       if (!nfit_pool) {
+               rc = -ENOMEM;
+               goto err_register;
+       }
+
+       if (gen_pool_add(nfit_pool, SZ_4G, SZ_4G, NUMA_NO_NODE)) {
+               rc = -ENOMEM;
+               goto err_register;
+       }
+
        for (i = 0; i < NUM_NFITS; i++) {
                struct nfit_test *nfit_test;
                struct platform_device *pdev;
@@ -2894,6 +2920,9 @@ static __init int nfit_test_init(void)
        return 0;
 
  err_register:
+       if (nfit_pool)
+               gen_pool_destroy(nfit_pool);
+
        destroy_workqueue(nfit_wq);
        for (i = 0; i < NUM_NFITS; i++)
                if (instances[i])
@@ -2917,6 +2946,8 @@ static __exit void nfit_test_exit(void)
        platform_driver_unregister(&nfit_test_driver);
        nfit_test_teardown();
 
+       gen_pool_destroy(nfit_pool);
+
        for (i = 0; i < NUM_NFITS; i++)
                put_device(&instances[i]->pdev.dev);
        class_destroy(nfit_test_dimm);
index 6f1f4a6..8574442 100644 (file)
@@ -13,7 +13,7 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/* Test readlink /proc/self/map_files/... with address 0. */
+/* Test readlink /proc/self/map_files/... with minimum address. */
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -47,6 +47,11 @@ static void fail(const char *fmt, unsigned long a, unsigned long b)
 int main(void)
 {
        const unsigned int PAGE_SIZE = sysconf(_SC_PAGESIZE);
+#ifdef __arm__
+       unsigned long va = 2 * PAGE_SIZE;
+#else
+       unsigned long va = 0;
+#endif
        void *p;
        int fd;
        unsigned long a, b;
@@ -55,7 +60,7 @@ int main(void)
        if (fd == -1)
                return 1;
 
-       p = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE|MAP_FILE|MAP_FIXED, fd, 0);
+       p = mmap((void *)va, PAGE_SIZE, PROT_NONE, MAP_PRIVATE|MAP_FILE|MAP_FIXED, fd, 0);
        if (p == MAP_FAILED) {
                if (errno == EPERM)
                        return 2;