Merge tag 'csky-for-linus-5.6-rc3' of git://github.com/c-sky/csky-linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 23 Feb 2020 17:37:41 +0000 (09:37 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 23 Feb 2020 17:37:41 +0000 (09:37 -0800)
Pull csky updates from Guo Ren:
 "Sorry, I missed 5.6-rc1 merge window, but in this pull request the
  most are the fixes and the rests are between fixes and features. The
  only outside modification is the MAINTAINERS file update with our
  mailing list.

   - cache flush implementation fixes

   - ftrace modify panic fix

   - CONFIG_SMP boot problem fix

   - fix pt_regs saving for atomic.S

   - fix fixaddr_init without highmem.

   - fix stack protector support

   - fix fake Tightly-Coupled Memory code compile and use

   - fix some typos and coding convention"

* tag 'csky-for-linus-5.6-rc3' of git://github.com/c-sky/csky-linux: (23 commits)
  csky: Replace <linux/clk-provider.h> by <linux/of_clk.h>
  csky: Implement copy_thread_tls
  csky: Add PCI support
  csky: Minimize defconfig to support buildroot config.fragment
  csky: Add setup_initrd check code
  csky: Cleanup old Kconfig options
  arch/csky: fix some Kconfig typos
  csky: Fixup compile warning for three unimplemented syscalls
  csky: Remove unused cache implementation
  csky: Fixup ftrace modify panic
  csky: Add flush_icache_mm to defer flush icache all
  csky: Optimize abiv2 copy_to_user_page with VM_EXEC
  csky: Enable defer flush_dcache_page for abiv2 cpus (807/810/860)
  csky: Remove unnecessary flush_icache_* implementation
  csky: Support icache flush without specific instructions
  csky/Kconfig: Add Kconfig.platforms to support some drivers
  csky/smp: Fixup boot failed when CONFIG_SMP
  csky: Set regs->usp to kernel sp, when the exception is from kernel
  csky/mm: Fixup export invalid_pte_table symbol
  csky: Separate fixaddr_init from highmem
  ...

363 files changed:
COPYING
Documentation/arm64/memory.rst
Documentation/arm64/tagged-address-abi.rst
Documentation/devicetree/bindings/display/allwinner,sun4i-a10-tcon.yaml
Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml
Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-emc.yaml
Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
Documentation/devicetree/bindings/net/mdio.yaml
Documentation/filesystems/zonefs.txt
Documentation/hwmon/xdpe12284.rst
Documentation/process/embargoed-hardware-issues.rst
Documentation/translations/zh_CN/process/embargoed-hardware-issues.rst
MAINTAINERS
arch/arm64/include/asm/lse.h
arch/arm64/include/asm/memory.h
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/processor.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/head_32.S
arch/powerpc/kernel/head_32.h
arch/powerpc/kernel/head_8xx.S
arch/powerpc/kernel/idle_6xx.S
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/powerpc/mm/book3s32/hash_low.S
arch/powerpc/mm/book3s32/mmu.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/kasan/kasan_init_32.c
arch/powerpc/xmon/xmon.c
arch/s390/Makefile
arch/s390/boot/Makefile
arch/s390/boot/kaslr.c
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/include/asm/page.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/qdio.h
arch/x86/boot/compressed/kaslr_64.c
arch/x86/include/asm/msr-index.h
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/mce/amd.c
arch/x86/kernel/ima_arch.c
arch/x86/xen/enlighten_pv.c
crypto/hash_info.c
drivers/acpi/acpica/evevent.c
drivers/acpi/sleep.c
drivers/char/tpm/Makefile
drivers/char/tpm/tpm2-cmd.c
drivers/char/tpm/tpm_tis_spi.c [deleted file]
drivers/char/tpm/tpm_tis_spi_main.c [new file with mode: 0644]
drivers/fsi/Kconfig
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/modules/hdcp/hdcp2_execution.c
drivers/gpu/drm/amd/powerplay/smu_v11_0.c
drivers/gpu/drm/bridge/tc358767.c
drivers/gpu/drm/bridge/ti-tfp410.c
drivers/gpu/drm/drm_client_modeset.c
drivers/gpu/drm/drm_modes.c
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/gem/i915_gem_context.c
drivers/gpu/drm/i915/gem/i915_gem_object_types.h
drivers/gpu/drm/i915/gem/i915_gem_phys.c
drivers/gpu/drm/i915/gt/intel_breadcrumbs.c
drivers/gpu/drm/i915/gt/intel_gt_requests.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/intel_ring.c
drivers/gpu/drm/i915/gt/intel_ring.h
drivers/gpu/drm/i915/gt/intel_ring_types.h
drivers/gpu/drm/i915/gt/selftest_lrc.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_request.c
drivers/gpu/drm/i915/i915_scheduler.c
drivers/gpu/drm/i915/i915_utils.c
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
drivers/gpu/drm/msm/adreno/a6xx_hfi.c
drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
drivers/gpu/drm/msm/dsi/dsi_manager.c
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c
drivers/gpu/drm/nouveau/dispnv50/wndw.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c
drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c
drivers/gpu/drm/panfrost/panfrost_job.c
drivers/gpu/drm/panfrost/panfrost_mmu.c
drivers/gpu/drm/panfrost/panfrost_perfcnt.c
drivers/gpu/drm/selftests/drm_cmdline_selftests.h
drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
drivers/hwmon/acpi_power_meter.c
drivers/hwmon/w83627ehf.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/iommu/Makefile
drivers/iommu/amd_iommu_init.c
drivers/iommu/intel-iommu.c
drivers/iommu/qcom_iommu.c
drivers/misc/habanalabs/device.c
drivers/misc/habanalabs/goya/goya.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_options.c
drivers/net/dsa/b53/b53_common.c
drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
drivers/net/ethernet/aquantia/atlantic/aq_filters.c
drivers/net/ethernet/aquantia/atlantic/aq_hw.h
drivers/net/ethernet/aquantia/atlantic/aq_nic.c
drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
drivers/net/ethernet/aquantia/atlantic/aq_ring.c
drivers/net/ethernet/aquantia/atlantic/aq_ring.h
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/cnic_defs.h
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/cavium/thunder/thunder_bgx.c
drivers/net/ethernet/cavium/thunder/thunder_bgx.h
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_txrx.h
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h
drivers/net/ethernet/mellanox/mlx5/core/en/health.c
drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c
drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
drivers/net/ethernet/mellanox/mlx5/core/wq.c
drivers/net/ethernet/mellanox/mlx5/core/wq.h
drivers/net/ethernet/micrel/ks8851_mll.c
drivers/net/ethernet/mscc/ocelot_board.c
drivers/net/ethernet/pensando/ionic/ionic_dev.c
drivers/net/ethernet/pensando/ionic/ionic_if.h
drivers/net/ethernet/qlogic/qede/qede.h
drivers/net/ethernet/qlogic/qede/qede_rdma.c
drivers/net/phy/broadcom.c
drivers/net/phy/mdio-bcm-iproc.c
drivers/net/wireguard/device.c
drivers/net/wireguard/receive.c
drivers/net/wireguard/send.c
drivers/net/wireguard/socket.c
drivers/nfc/pn544/i2c.c
drivers/nfc/pn544/pn544.c
drivers/nvme/host/core.c
drivers/nvme/host/multipath.c
drivers/nvme/host/pci.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/chp.c
drivers/s390/cio/qdio_setup.c
drivers/s390/crypto/zcrypt_ep11misc.c
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_qdio.h
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/staging/android/Kconfig
drivers/staging/android/Makefile
drivers/staging/android/TODO
drivers/staging/android/ashmem.c
drivers/staging/android/uapi/vsoc_shm.h [deleted file]
drivers/staging/android/vsoc.c [deleted file]
drivers/staging/greybus/audio_manager.c
drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
drivers/staging/vt6656/dpc.c
drivers/target/iscsi/iscsi_target.c
drivers/target/target_core_transport.c
drivers/thunderbolt/switch.c
drivers/tty/serdev/serdev-ttyport.c
drivers/tty/serial/8250/8250_aspeed_vuart.c
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_of.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/ar933x_uart.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/cpm_uart/cpm_uart_core.c
drivers/tty/serial/imx.c
drivers/tty/serial/qcom_geni_serial.c
drivers/tty/serial/serial-tegra.c
drivers/tty/tty_port.c
drivers/tty/vt/selection.c
drivers/tty/vt/vt.c
drivers/tty/vt/vt_ioctl.c
drivers/usb/core/config.c
drivers/usb/core/hub.c
drivers/usb/core/hub.h
drivers/usb/core/quirks.c
drivers/usb/core/usb.h
drivers/usb/dwc2/gadget.c
drivers/usb/dwc3/debug.h
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/u_audio.c
drivers/usb/gadget/function/u_serial.c
drivers/usb/gadget/udc/udc-xilinx.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci.h
drivers/usb/misc/iowarrior.c
drivers/usb/phy/phy-tegra-usb.c
drivers/usb/serial/ch341.c
drivers/usb/serial/ir-usb.c
drivers/usb/storage/uas.c
drivers/watchdog/Kconfig
drivers/watchdog/da9062_wdt.c
drivers/xen/preempt.c
fs/btrfs/inode.c
fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/keystore.c
fs/ecryptfs/main.c
fs/ecryptfs/messaging.c
fs/io_uring.c
fs/pipe.c
include/acpi/acpixf.h
include/linux/compat.h
include/linux/intel-svm.h
include/linux/irqdomain.h
include/linux/ktime.h
include/linux/mlx5/mlx5_ifc.h
include/linux/netdevice.h
include/linux/rculist_nulls.h
include/linux/skbuff.h
include/linux/swiotlb.h
include/linux/time32.h
include/linux/timekeeping32.h
include/linux/tty.h
include/linux/types.h
include/linux/usb/quirks.h
include/net/flow_dissector.h
include/net/sock.h
include/scsi/iscsi_proto.h
include/sound/rawmidi.h
include/sound/soc-dapm.h
include/uapi/asm-generic/posix_types.h
include/uapi/linux/bpf.h
include/uapi/linux/netfilter/nf_conntrack_common.h
include/uapi/linux/swab.h
include/uapi/linux/time.h
include/uapi/linux/usb/charger.h
ipc/sem.c
kernel/bpf/btf.c
kernel/bpf/hashtab.c
kernel/bpf/offload.c
kernel/compat.c
kernel/dma/contiguous.c
kernel/dma/direct.c
kernel/dma/swiotlb.c
kernel/irq/internals.h
kernel/irq/manage.c
kernel/irq/proc.c
kernel/sysctl.c
kernel/time/time.c
lib/stackdepot.c
lib/string.c
mm/memcontrol.c
mm/mmap.c
mm/mremap.c
mm/sparse.c
mm/swapfile.c
mm/vmscan.c
net/Kconfig
net/bridge/br_stp.c
net/core/dev.c
net/core/fib_rules.c
net/core/rtnetlink.c
net/core/skbuff.c
net/ethtool/bitset.c
net/hsr/hsr_framereg.c
net/ipv4/udp.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/route.c
net/mptcp/Kconfig
net/mptcp/protocol.c
net/mptcp/protocol.h
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_proto_udp.c
net/netfilter/nf_flow_table_offload.c
net/netfilter/nft_set_pipapo.c
net/netfilter/xt_hashlimit.c
net/netlabel/netlabel_domainhash.c
net/netlabel/netlabel_unlabeled.c
net/netlink/af_netlink.c
net/openvswitch/datapath.c
net/openvswitch/flow_netlink.c
net/openvswitch/flow_table.c
net/openvswitch/meter.c
net/openvswitch/vport.c
net/rds/rdma.c
net/sched/cls_flower.c
net/sctp/sm_statefuns.c
net/tls/tls_device.c
net/xdp/xsk.c
net/xdp/xsk_queue.h
scripts/get_maintainer.pl
security/integrity/ima/Kconfig
security/integrity/platform_certs/load_uefi.c
sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_queue.c
sound/core/seq/seq_timer.c
sound/core/seq/seq_timer.h
sound/hda/ext/hdac_ext_controller.c
sound/hda/hdmi_chmap.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_sysfs.c
sound/pci/hda/patch_realtek.c
sound/soc/amd/raven/acp3x-i2s.c
sound/soc/amd/raven/acp3x-pcm-dma.c
sound/soc/amd/raven/pci-acp3x.c
sound/soc/atmel/Kconfig
sound/soc/atmel/Makefile
sound/soc/codecs/hdmi-codec.c
sound/soc/codecs/max98090.c
sound/soc/codecs/max98090.h
sound/soc/fsl/fsl_sai.c
sound/soc/soc-dapm.c
sound/soc/sof/intel/hda-codec.c
sound/soc/sof/intel/hda-dsp.c
sound/soc/sof/intel/hda.c
sound/soc/sunxi/sun8i-codec.c
tools/include/uapi/linux/bpf.h
tools/lib/bpf/libbpf.c
tools/testing/selftests/Makefile
tools/testing/selftests/bpf/prog_tests/select_reuseport.c
tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc
tools/testing/selftests/futex/functional/Makefile
tools/testing/selftests/lib.mk
tools/testing/selftests/net/Makefile
tools/testing/selftests/net/fib_tests.sh
tools/testing/selftests/net/forwarding/mirror_gre.sh
tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh
tools/testing/selftests/openat2/helpers.c
tools/testing/selftests/openat2/resolve_test.c
tools/testing/selftests/rtc/Makefile
tools/testing/selftests/timens/Makefile
tools/testing/selftests/tpm2/test_smoke.sh
tools/testing/selftests/tpm2/test_space.sh
tools/testing/selftests/vm/run_vmtests
tools/testing/selftests/wireguard/qemu/Makefile

diff --git a/COPYING b/COPYING
index da4cb28..a635a38 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -16,3 +16,5 @@ In addition, other licenses may also apply. Please see:
        Documentation/process/license-rules.rst
 
 for more details.
+
+All contributions to the Linux Kernel are subject to this COPYING file.
index 02e0217..cf03b32 100644 (file)
@@ -129,7 +129,7 @@ this logic.
 
 As a single binary will need to support both 48-bit and 52-bit VA
 spaces, the VMEMMAP must be sized large enough for 52-bit VAs and
-also must be sized large enought to accommodate a fixed PAGE_OFFSET.
+also must be sized large enough to accommodate a fixed PAGE_OFFSET.
 
 Most code in the kernel should not need to consider the VA_BITS, for
 code that does need to know the VA size the variables are
index d4a85d5..4a9d9c7 100644 (file)
@@ -44,8 +44,15 @@ The AArch64 Tagged Address ABI has two stages of relaxation depending
 how the user addresses are used by the kernel:
 
 1. User addresses not accessed by the kernel but used for address space
-   management (e.g. ``mmap()``, ``mprotect()``, ``madvise()``). The use
-   of valid tagged pointers in this context is always allowed.
+   management (e.g. ``mprotect()``, ``madvise()``). The use of valid
+   tagged pointers in this context is allowed with the exception of
+   ``brk()``, ``mmap()`` and the ``new_address`` argument to
+   ``mremap()`` as these have the potential to alias with existing
+   user addresses.
+
+   NOTE: This behaviour changed in v5.6 and so some earlier kernels may
+   incorrectly accept valid tagged pointers for the ``brk()``,
+   ``mmap()`` and ``mremap()`` system calls.
 
 2. User addresses accessed by the kernel (e.g. ``write()``). This ABI
    relaxation is disabled by default and the application thread needs to
index 86ad617..5ff9cf2 100644 (file)
@@ -43,9 +43,13 @@ properties:
         - enum:
           - allwinner,sun8i-h3-tcon-tv
           - allwinner,sun50i-a64-tcon-tv
-          - allwinner,sun50i-h6-tcon-tv
         - const: allwinner,sun8i-a83t-tcon-tv
 
+      - items:
+        - enum:
+          - allwinner,sun50i-h6-tcon-tv
+        - const: allwinner,sun8i-r40-tcon-tv
+
   reg:
     maxItems: 1
 
index 9af873b..8453ee3 100644 (file)
@@ -33,24 +33,40 @@ properties:
     maxItems: 1
 
   clocks:
-    minItems: 2
-    maxItems: 3
-    items:
-      - description: The CSI interface clock
-      - description: The CSI ISP clock
-      - description: The CSI DRAM clock
+    oneOf:
+      - items:
+        - description: The CSI interface clock
+        - description: The CSI DRAM clock
+
+      - items:
+        - description: The CSI interface clock
+        - description: The CSI ISP clock
+        - description: The CSI DRAM clock
 
   clock-names:
-    minItems: 2
-    maxItems: 3
-    items:
-      - const: bus
-      - const: isp
-      - const: ram
+    oneOf:
+      - items:
+        - const: bus
+        - const: ram
+
+      - items:
+        - const: bus
+        - const: isp
+        - const: ram
 
   resets:
     maxItems: 1
 
+  # FIXME: This should be made required eventually once every SoC will
+  # have the MBUS declared.
+  interconnects:
+    maxItems: 1
+
+  # FIXME: This should be made required eventually once every SoC will
+  # have the MBUS declared.
+  interconnect-names:
+    const: dma-mem
+
   # See ./video-interfaces.txt for details
   port:
     type: object
index dd18434..3e0a8a9 100644 (file)
@@ -347,6 +347,7 @@ examples:
         interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
 
         #iommu-cells = <1>;
+        #reset-cells = <1>;
     };
 
     external-memory-controller@7001b000 {
@@ -363,20 +364,23 @@ examples:
             timing-0 {
                 clock-frequency = <12750000>;
 
-                nvidia,emc-zcal-cnt-long = <0x00000042>;
-                nvidia,emc-auto-cal-interval = <0x001fffff>;
-                nvidia,emc-ctt-term-ctrl = <0x00000802>;
-                nvidia,emc-cfg = <0x73240000>;
-                nvidia,emc-cfg-2 = <0x000008c5>;
-                nvidia,emc-sel-dpd-ctrl = <0x00040128>;
-                nvidia,emc-bgbias-ctl0 = <0x00000008>;
                 nvidia,emc-auto-cal-config = <0xa1430000>;
                 nvidia,emc-auto-cal-config2 = <0x00000000>;
                 nvidia,emc-auto-cal-config3 = <0x00000000>;
-                nvidia,emc-mode-reset = <0x80001221>;
+                nvidia,emc-auto-cal-interval = <0x001fffff>;
+                nvidia,emc-bgbias-ctl0 = <0x00000008>;
+                nvidia,emc-cfg = <0x73240000>;
+                nvidia,emc-cfg-2 = <0x000008c5>;
+                nvidia,emc-ctt-term-ctrl = <0x00000802>;
                 nvidia,emc-mode-1 = <0x80100003>;
                 nvidia,emc-mode-2 = <0x80200008>;
                 nvidia,emc-mode-4 = <0x00000000>;
+                nvidia,emc-mode-reset = <0x80001221>;
+                nvidia,emc-mrs-wait-cnt = <0x000e000e>;
+                nvidia,emc-sel-dpd-ctrl = <0x00040128>;
+                nvidia,emc-xm2dqspadctrl2 = <0x0130b118>;
+                nvidia,emc-zcal-cnt-long = <0x00000042>;
+                nvidia,emc-zcal-interval = <0x00000000>;
 
                 nvidia,emc-configuration = <
                     0x00000000 /* EMC_RC */
index 19f5508..4a9145e 100644 (file)
@@ -124,7 +124,7 @@ not every application needs SDIO irq, e.g. MMC cards.
                pinctrl-1 = <&mmc1_idle>;
                pinctrl-2 = <&mmc1_sleep>;
                ...
-               interrupts-extended = <&intc 64 &gpio2 28 GPIO_ACTIVE_LOW>;
+               interrupts-extended = <&intc 64 &gpio2 28 IRQ_TYPE_LEVEL_LOW>;
        };
 
        mmc1_idle : pinmux_cirq_pin {
index 5d08d2f..50c3397 100644 (file)
@@ -56,7 +56,6 @@ patternProperties:
 examples:
   - |
     davinci_mdio: mdio@5c030000 {
-        compatible = "ti,davinci_mdio";
         reg = <0x5c030000 0x1000>;
         #address-cells = <1>;
         #size-cells = <0>;
index 935bf22..d54fa98 100644 (file)
@@ -134,7 +134,7 @@ Sequential zone files can only be written sequentially, starting from the file
 end, that is, write operations can only be append writes. Zonefs makes no
 attempt at accepting random writes and will fail any write request that has a
 start offset not corresponding to the end of the file, or to the end of the last
-write issued and still in-flight (for asynchrnous I/O operations).
+write issued and still in-flight (for asynchronous I/O operations).
 
 Since dirty page writeback by the page cache does not guarantee a sequential
 write pattern, zonefs prevents buffered writes and writeable shared mappings
@@ -142,7 +142,7 @@ on sequential files. Only direct I/O writes are accepted for these files.
 zonefs relies on the sequential delivery of write I/O requests to the device
 implemented by the block layer elevator. An elevator implementing the sequential
 write feature for zoned block device (ELEVATOR_F_ZBD_SEQ_WRITE elevator feature)
-must be used. This type of elevator (e.g. mq-deadline) is the set by default
+must be used. This type of elevator (e.g. mq-deadline) is set by default
 for zoned block devices on device initialization.
 
 There are no restrictions on the type of I/O used for read operations in
@@ -196,7 +196,7 @@ additional conditions that result in I/O errors.
   may still happen in the case of a partial failure of a very large direct I/O
   operation split into multiple BIOs/requests or asynchronous I/O operations.
   If one of the write request within the set of sequential write requests
-  issued to the device fails, all write requests after queued after it will
+  issued to the device fails, all write requests queued after it will
   become unaligned and fail.
 
 * Delayed write errors: similarly to regular block devices, if the device side
@@ -207,7 +207,7 @@ additional conditions that result in I/O errors.
   causing all data to be dropped after the sector that caused the error.
 
 All I/O errors detected by zonefs are notified to the user with an error code
-return for the system call that trigered or detected the error. The recovery
+return for the system call that triggered or detected the error. The recovery
 actions taken by zonefs in response to I/O errors depend on the I/O type (read
 vs write) and on the reason for the error (bad sector, unaligned writes or zone
 condition change).
@@ -222,7 +222,7 @@ condition change).
 * A zone condition change to read-only or offline also always triggers zonefs
   I/O error recovery.
 
-Zonefs minimal I/O error recovery may change a file size and file access
+Zonefs minimal I/O error recovery may change a file size and file access
 permissions.
 
 * File size changes:
@@ -237,7 +237,7 @@ permissions.
   A file size may also be reduced to reflect a delayed write error detected on
   fsync(): in this case, the amount of data effectively written in the zone may
   be less than originally indicated by the file inode size. After such I/O
-  error, zonefs always fixes a file inode size to reflect the amount of data
+  error, zonefs always fixes the file inode size to reflect the amount of data
   persistently stored in the file zone.
 
 * Access permission changes:
@@ -281,11 +281,11 @@ Further notes:
   permissions to read-only applies to all files. The file system is remounted
   read-only.
 * Access permission and file size changes due to the device transitioning zones
-  to the offline condition are permanent. Remounting or reformating the device
+  to the offline condition are permanent. Remounting or reformatting the device
   with mkfs.zonefs (mkzonefs) will not change back offline zone files to a good
   state.
 * File access permission changes to read-only due to the device transitioning
-  zones to the read-only condition are permanent. Remounting or reformating
+  zones to the read-only condition are permanent. Remounting or reformatting
   the device will not re-enable file write access.
 * File access permission changes implied by the remount-ro, zone-ro and
   zone-offline mount options are temporary for zones in a good condition.
@@ -301,13 +301,13 @@ Mount options
 
 zonefs define the "errors=<behavior>" mount option to allow the user to specify
 zonefs behavior in response to I/O errors, inode size inconsistencies or zone
-condition chages. The defined behaviors are as follow:
+condition changes. The defined behaviors are as follow:
 * remount-ro (default)
 * zone-ro
 * zone-offline
 * repair
 
-The I/O error actions defined for each behavior is detailed in the previous
+The I/O error actions defined for each behavior are detailed in the previous
 section.
 
 Zonefs User Space Tools
index 6b7ae98..67d1f87 100644 (file)
@@ -24,6 +24,7 @@ This driver implements support for Infineon Multi-phase XDPE122 family
 dual loop voltage regulators.
 The family includes XDPE12284 and XDPE12254 devices.
 The devices from this family complaint with:
+
 - Intel VR13 and VR13HC rev 1.3, IMVP8 rev 1.2 and IMPVP9 rev 1.3 DC-DC
   converter specification.
 - Intel SVID rev 1.9. protocol.
index 33edae6..a19d084 100644 (file)
@@ -244,23 +244,23 @@ disclosure of a particular issue, unless requested by a response team or by
 an involved disclosed party. The current ambassadors list:
 
   ============= ========================================================
-  ARM
+  ARM           Grant Likely <grant.likely@arm.com>
   AMD          Tom Lendacky <tom.lendacky@amd.com>
   IBM
   Intel                Tony Luck <tony.luck@intel.com>
   Qualcomm     Trilok Soni <tsoni@codeaurora.org>
 
-  Microsoft    Sasha Levin <sashal@kernel.org>
+  Microsoft    James Morris <jamorris@linux.microsoft.com>
   VMware
   Xen          Andrew Cooper <andrew.cooper3@citrix.com>
 
-  Canonical    Tyler Hicks <tyhicks@canonical.com>
+  Canonical    John Johansen <john.johansen@canonical.com>
   Debian       Ben Hutchings <ben@decadent.org.uk>
   Oracle       Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
   Red Hat      Josh Poimboeuf <jpoimboe@redhat.com>
   SUSE         Jiri Kosina <jkosina@suse.cz>
 
-  Amazon       Peter Bowen <pzb@amzn.com>
+  Amazon
   Google       Kees Cook <keescook@chromium.org>
   ============= ========================================================
 
index b93f1af..88273eb 100644 (file)
@@ -183,7 +183,7 @@ CVE分配
   VMware
   Xen          Andrew Cooper <andrew.cooper3@citrix.com>
 
-  Canonical    Tyler Hicks <tyhicks@canonical.com>
+  Canonical    John Johansen <john.johansen@canonical.com>
   Debian       Ben Hutchings <ben@decadent.org.uk>
   Oracle       Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
   Red Hat      Josh Poimboeuf <jpoimboe@redhat.com>
index a4b5858..fcd79fc 100644 (file)
@@ -3910,7 +3910,7 @@ S:        Supported
 F:     Documentation/filesystems/ceph.txt
 F:     fs/ceph/
 
-CERTIFICATE HANDLING:
+CERTIFICATE HANDLING
 M:     David Howells <dhowells@redhat.com>
 M:     David Woodhouse <dwmw2@infradead.org>
 L:     keyrings@vger.kernel.org
@@ -3920,7 +3920,7 @@ F:        certs/
 F:     scripts/sign-file.c
 F:     scripts/extract-cert.c
 
-CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM:
+CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM
 L:     devel@driverdev.osuosl.org
 S:     Obsolete
 F:     drivers/staging/wusbcore/
@@ -5933,12 +5933,12 @@ S:      Maintained
 F:     drivers/media/dvb-frontends/ec100*
 
 ECRYPT FILE SYSTEM
-M:     Tyler Hicks <tyhicks@canonical.com>
+M:     Tyler Hicks <code@tyhicks.com>
 L:     ecryptfs@vger.kernel.org
 W:     http://ecryptfs.org
 W:     https://launchpad.net/ecryptfs
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs.git
-S:     Supported
+S:     Odd Fixes
 F:     Documentation/filesystems/ecryptfs.txt
 F:     fs/ecryptfs/
 
@@ -7048,7 +7048,7 @@ L:        kvm@vger.kernel.org
 S:     Supported
 F:     drivers/uio/uio_pci_generic.c
 
-GENERIC VDSO LIBRARY:
+GENERIC VDSO LIBRARY
 M:     Andy Lutomirski <luto@kernel.org>
 M:     Thomas Gleixner <tglx@linutronix.de>
 M:     Vincenzo Frascino <vincenzo.frascino@arm.com>
@@ -8393,7 +8393,7 @@ M:        Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
 M:     Rodrigo Vivi <rodrigo.vivi@intel.com>
 L:     intel-gfx@lists.freedesktop.org
 W:     https://01.org/linuxgraphics/
-B:     https://01.org/linuxgraphics/documentation/how-report-bugs
+B:     https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs
 C:     irc://chat.freenode.net/intel-gfx
 Q:     http://patchwork.freedesktop.org/project/intel-gfx/
 T:     git git://anongit.freedesktop.org/drm-intel
@@ -9279,7 +9279,7 @@ F:        include/keys/trusted-type.h
 F:     security/keys/trusted.c
 F:     include/keys/trusted.h
 
-KEYS/KEYRINGS:
+KEYS/KEYRINGS
 M:     David Howells <dhowells@redhat.com>
 M:     Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
 L:     keyrings@vger.kernel.org
@@ -11485,7 +11485,7 @@ F:      drivers/scsi/mac_scsi.*
 F:     drivers/scsi/sun3_scsi.*
 F:     drivers/scsi/sun3_scsi_vme.c
 
-NCSI LIBRARY:
+NCSI LIBRARY
 M:     Samuel Mendoza-Jonas <sam@mendozajonas.com>
 S:     Maintained
 F:     net/ncsi/
@@ -13513,7 +13513,7 @@ L:      linuxppc-dev@lists.ozlabs.org
 S:     Maintained
 F:     drivers/block/ps3vram.c
 
-PSAMPLE PACKET SAMPLING SUPPORT:
+PSAMPLE PACKET SAMPLING SUPPORT
 M:     Yotam Gigi <yotam.gi@gmail.com>
 S:     Maintained
 F:     net/psample
@@ -14583,10 +14583,10 @@ F:    drivers/media/pci/saa7146/
 F:     include/media/drv-intf/saa7146*
 
 SAFESETID SECURITY MODULE
-M:     Micah Morton <mortonm@chromium.org>
-S:     Supported
-F:     security/safesetid/
-F:     Documentation/admin-guide/LSM/SafeSetID.rst
+M:     Micah Morton <mortonm@chromium.org>
+S:     Supported
+F:     security/safesetid/
+F:     Documentation/admin-guide/LSM/SafeSetID.rst
 
 SAMSUNG AUDIO (ASoC) DRIVERS
 M:     Krzysztof Kozlowski <krzk@kernel.org>
@@ -16553,8 +16553,8 @@ M:      Michael Jamet <michael.jamet@intel.com>
 M:     Mika Westerberg <mika.westerberg@linux.intel.com>
 M:     Yehezkel Bernat <YehezkelShB@gmail.com>
 L:     linux-usb@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt.git
 S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt.git
 F:     Documentation/admin-guide/thunderbolt.rst
 F:     drivers/thunderbolt/
 F:     include/linux/thunderbolt.h
@@ -17081,7 +17081,7 @@ S:      Maintained
 F:     Documentation/admin-guide/ufs.rst
 F:     fs/ufs/
 
-UHID USERSPACE HID IO DRIVER:
+UHID USERSPACE HID IO DRIVER
 M:     David Herrmann <dh.herrmann@googlemail.com>
 L:     linux-input@vger.kernel.org
 S:     Maintained
@@ -17095,18 +17095,18 @@ S:    Maintained
 F:     drivers/usb/common/ulpi.c
 F:     include/linux/ulpi/
 
-ULTRA-WIDEBAND (UWB) SUBSYSTEM:
+ULTRA-WIDEBAND (UWB) SUBSYSTEM
 L:     devel@driverdev.osuosl.org
 S:     Obsolete
 F:     drivers/staging/uwb/
 
-UNICODE SUBSYSTEM:
+UNICODE SUBSYSTEM
 M:     Gabriel Krisman Bertazi <krisman@collabora.com>
 L:     linux-fsdevel@vger.kernel.org
 S:     Supported
 F:     fs/unicode/
 
-UNICORE32 ARCHITECTURE:
+UNICORE32 ARCHITECTURE
 M:     Guan Xuetao <gxt@pku.edu.cn>
 W:     http://mprc.pku.edu.cn/~guanxuetao/linux
 S:     Maintained
@@ -17393,11 +17393,14 @@ F:    drivers/usb/
 F:     include/linux/usb.h
 F:     include/linux/usb/
 
-USB TYPEC PI3USB30532 MUX DRIVER
-M:     Hans de Goede <hdegoede@redhat.com>
+USB TYPEC BUS FOR ALTERNATE MODES
+M:     Heikki Krogerus <heikki.krogerus@linux.intel.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
-F:     drivers/usb/typec/mux/pi3usb30532.c
+F:     Documentation/ABI/testing/sysfs-bus-typec
+F:     Documentation/driver-api/usb/typec_bus.rst
+F:     drivers/usb/typec/altmodes/
+F:     include/linux/usb/typec_altmode.h
 
 USB TYPEC CLASS
 M:     Heikki Krogerus <heikki.krogerus@linux.intel.com>
@@ -17408,14 +17411,11 @@ F:    Documentation/driver-api/usb/typec.rst
 F:     drivers/usb/typec/
 F:     include/linux/usb/typec.h
 
-USB TYPEC BUS FOR ALTERNATE MODES
-M:     Heikki Krogerus <heikki.krogerus@linux.intel.com>
+USB TYPEC PI3USB30532 MUX DRIVER
+M:     Hans de Goede <hdegoede@redhat.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
-F:     Documentation/ABI/testing/sysfs-bus-typec
-F:     Documentation/driver-api/usb/typec_bus.rst
-F:     drivers/usb/typec/altmodes/
-F:     include/linux/usb/typec_altmode.h
+F:     drivers/usb/typec/mux/pi3usb30532.c
 
 USB TYPEC PORT CONTROLLER DRIVERS
 M:     Guenter Roeck <linux@roeck-us.net>
@@ -17792,7 +17792,7 @@ F:      include/linux/vbox_utils.h
 F:     include/uapi/linux/vbox*.h
 F:     drivers/virt/vboxguest/
 
-VIRTUAL BOX SHARED FOLDER VFS DRIVER:
+VIRTUAL BOX SHARED FOLDER VFS DRIVER
 M:     Hans de Goede <hdegoede@redhat.com>
 L:     linux-fsdevel@vger.kernel.org
 S:     Maintained
index d429f77..5d10051 100644 (file)
@@ -6,7 +6,7 @@
 
 #ifdef CONFIG_ARM64_LSE_ATOMICS
 
-#define __LSE_PREAMBLE ".arch armv8-a+lse\n"
+#define __LSE_PREAMBLE ".arch_extension lse\n"
 
 #include <linux/compiler_types.h>
 #include <linux/export.h>
index a4f9ca5..4d94676 100644 (file)
@@ -213,7 +213,7 @@ static inline unsigned long kaslr_offset(void)
        ((__force __typeof__(addr))sign_extend64((__force u64)(addr), 55))
 
 #define untagged_addr(addr)    ({                                      \
-       u64 __addr = (__force u64)addr;                                 \
+       u64 __addr = (__force u64)(addr);                                       \
        __addr &= __untagged_addr(__addr);                              \
        (__force __typeof__(addr))__addr;                               \
 })
index 8633208..080a0bf 100644 (file)
@@ -295,8 +295,13 @@ static inline bool pfn_valid(unsigned long pfn)
 /*
  * Some number of bits at the level of the page table that points to
  * a hugepte are used to encode the size.  This masks those bits.
+ * On 8xx, HW assistance requires 4k alignment for the hugepte.
  */
+#ifdef CONFIG_PPC_8xx
+#define HUGEPD_SHIFT_MASK     0xfff
+#else
 #define HUGEPD_SHIFT_MASK     0x3f
+#endif
 
 #ifndef __ASSEMBLY__
 
index 8387698..eedcbfb 100644 (file)
@@ -168,6 +168,10 @@ struct thread_struct {
        unsigned long   srr1;
        unsigned long   dar;
        unsigned long   dsisr;
+#ifdef CONFIG_PPC_BOOK3S_32
+       unsigned long   r0, r3, r4, r5, r6, r8, r9, r11;
+       unsigned long   lr, ctr;
+#endif
 #endif
        /* Debug Registers */
        struct debug_reg debug;
index c25e562..fcf24a3 100644 (file)
@@ -132,6 +132,18 @@ int main(void)
        OFFSET(SRR1, thread_struct, srr1);
        OFFSET(DAR, thread_struct, dar);
        OFFSET(DSISR, thread_struct, dsisr);
+#ifdef CONFIG_PPC_BOOK3S_32
+       OFFSET(THR0, thread_struct, r0);
+       OFFSET(THR3, thread_struct, r3);
+       OFFSET(THR4, thread_struct, r4);
+       OFFSET(THR5, thread_struct, r5);
+       OFFSET(THR6, thread_struct, r6);
+       OFFSET(THR8, thread_struct, r8);
+       OFFSET(THR9, thread_struct, r9);
+       OFFSET(THR11, thread_struct, r11);
+       OFFSET(THLR, thread_struct, lr);
+       OFFSET(THCTR, thread_struct, ctr);
+#endif
 #endif
 #ifdef CONFIG_SPE
        OFFSET(THREAD_EVR0, thread_struct, evr[0]);
index a1eaffe..7b048ce 100644 (file)
@@ -1184,6 +1184,17 @@ void eeh_handle_special_event(void)
                        eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
                        eeh_handle_normal_event(pe);
                } else {
+                       eeh_for_each_pe(pe, tmp_pe)
+                               eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
+                                       edev->mode &= ~EEH_DEV_NO_HANDLER;
+
+                       /* Notify all devices to be down */
+                       eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
+                       eeh_set_channel_state(pe, pci_channel_io_perm_failure);
+                       eeh_pe_report(
+                               "error_detected(permanent failure)", pe,
+                               eeh_report_failure, NULL);
+
                        pci_lock_rescan_remove();
                        list_for_each_entry(hose, &hose_list, list_node) {
                                phb_pe = eeh_phb_pe_get(hose);
@@ -1192,16 +1203,6 @@ void eeh_handle_special_event(void)
                                    (phb_pe->state & EEH_PE_RECOVERING))
                                        continue;
 
-                               eeh_for_each_pe(pe, tmp_pe)
-                                       eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
-                                               edev->mode &= ~EEH_DEV_NO_HANDLER;
-
-                               /* Notify all devices to be down */
-                               eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
-                               eeh_set_channel_state(pe, pci_channel_io_perm_failure);
-                               eeh_pe_report(
-                                       "error_detected(permanent failure)", pe,
-                                       eeh_report_failure, NULL);
                                bus = eeh_pe_bus_get(phb_pe);
                                if (!bus) {
                                        pr_err("%s: Cannot find PCI bus for "
index 0713daa..16af0d8 100644 (file)
@@ -783,7 +783,7 @@ fast_exception_return:
 1:     lis     r3,exc_exit_restart_end@ha
        addi    r3,r3,exc_exit_restart_end@l
        cmplw   r12,r3
-#if CONFIG_PPC_BOOK3S_601
+#ifdef CONFIG_PPC_BOOK3S_601
        bge     2b
 #else
        bge     3f
@@ -791,7 +791,7 @@ fast_exception_return:
        lis     r4,exc_exit_restart@ha
        addi    r4,r4,exc_exit_restart@l
        cmplw   r12,r4
-#if CONFIG_PPC_BOOK3S_601
+#ifdef CONFIG_PPC_BOOK3S_601
        blt     2b
 #else
        blt     3f
@@ -1354,12 +1354,17 @@ _GLOBAL(enter_rtas)
        mtspr   SPRN_SRR0,r8
        mtspr   SPRN_SRR1,r9
        RFI
-1:     tophys(r9,r1)
+1:     tophys_novmstack r9, r1
+#ifdef CONFIG_VMAP_STACK
+       li      r0, MSR_KERNEL & ~MSR_IR        /* can take DTLB miss */
+       mtmsr   r0
+       isync
+#endif
        lwz     r8,INT_FRAME_SIZE+4(r9) /* get return address */
        lwz     r9,8(r9)        /* original msr value */
        addi    r1,r1,INT_FRAME_SIZE
        li      r0,0
-       tophys(r7, r2)
+       tophys_novmstack r7, r2
        stw     r0, THREAD + RTAS_SP(r7)
        mtspr   SPRN_SRR0,r8
        mtspr   SPRN_SRR1,r9
index 0493fca..97c8879 100644 (file)
@@ -290,17 +290,55 @@ MachineCheck:
 7:     EXCEPTION_PROLOG_2
        addi    r3,r1,STACK_FRAME_OVERHEAD
 #ifdef CONFIG_PPC_CHRP
-       bne     cr1,1f
+#ifdef CONFIG_VMAP_STACK
+       mfspr   r4, SPRN_SPRG_THREAD
+       tovirt(r4, r4)
+       lwz     r4, RTAS_SP(r4)
+       cmpwi   cr1, r4, 0
 #endif
-       EXC_XFER_STD(0x200, machine_check_exception)
-#ifdef CONFIG_PPC_CHRP
-1:     b       machine_check_in_rtas
+       beq     cr1, machine_check_tramp
+       b       machine_check_in_rtas
+#else
+       b       machine_check_tramp
 #endif
 
 /* Data access exception. */
        . = 0x300
        DO_KVM  0x300
 DataAccess:
+#ifdef CONFIG_VMAP_STACK
+       mtspr   SPRN_SPRG_SCRATCH0,r10
+       mfspr   r10, SPRN_SPRG_THREAD
+BEGIN_MMU_FTR_SECTION
+       stw     r11, THR11(r10)
+       mfspr   r10, SPRN_DSISR
+       mfcr    r11
+#ifdef CONFIG_PPC_KUAP
+       andis.  r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH | DSISR_PROTFAULT)@h
+#else
+       andis.  r10, r10, (DSISR_BAD_FAULT_32S | DSISR_DABRMATCH)@h
+#endif
+       mfspr   r10, SPRN_SPRG_THREAD
+       beq     hash_page_dsi
+.Lhash_page_dsi_cont:
+       mtcr    r11
+       lwz     r11, THR11(r10)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+       mtspr   SPRN_SPRG_SCRATCH1,r11
+       mfspr   r11, SPRN_DAR
+       stw     r11, DAR(r10)
+       mfspr   r11, SPRN_DSISR
+       stw     r11, DSISR(r10)
+       mfspr   r11, SPRN_SRR0
+       stw     r11, SRR0(r10)
+       mfspr   r11, SPRN_SRR1          /* check whether user or kernel */
+       stw     r11, SRR1(r10)
+       mfcr    r10
+       andi.   r11, r11, MSR_PR
+
+       EXCEPTION_PROLOG_1
+       b       handle_page_fault_tramp_1
+#else  /* CONFIG_VMAP_STACK */
        EXCEPTION_PROLOG handle_dar_dsisr=1
        get_and_save_dar_dsisr_on_stack r4, r5, r11
 BEGIN_MMU_FTR_SECTION
@@ -316,11 +354,32 @@ BEGIN_MMU_FTR_SECTION
 FTR_SECTION_ELSE
        b       handle_page_fault_tramp_2
 ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
+#endif /* CONFIG_VMAP_STACK */
 
 /* Instruction access exception. */
        . = 0x400
        DO_KVM  0x400
 InstructionAccess:
+#ifdef CONFIG_VMAP_STACK
+       mtspr   SPRN_SPRG_SCRATCH0,r10
+       mtspr   SPRN_SPRG_SCRATCH1,r11
+       mfspr   r10, SPRN_SPRG_THREAD
+       mfspr   r11, SPRN_SRR0
+       stw     r11, SRR0(r10)
+       mfspr   r11, SPRN_SRR1          /* check whether user or kernel */
+       stw     r11, SRR1(r10)
+       mfcr    r10
+BEGIN_MMU_FTR_SECTION
+       andis.  r11, r11, SRR1_ISI_NOPT@h       /* no pte found? */
+       bne     hash_page_isi
+.Lhash_page_isi_cont:
+       mfspr   r11, SPRN_SRR1          /* check whether user or kernel */
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+       andi.   r11, r11, MSR_PR
+
+       EXCEPTION_PROLOG_1
+       EXCEPTION_PROLOG_2
+#else  /* CONFIG_VMAP_STACK */
        EXCEPTION_PROLOG
        andis.  r0,r9,SRR1_ISI_NOPT@h   /* no pte found? */
        beq     1f                      /* if so, try to put a PTE */
@@ -329,6 +388,7 @@ InstructionAccess:
 BEGIN_MMU_FTR_SECTION
        bl      hash_page
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+#endif /* CONFIG_VMAP_STACK */
 1:     mr      r4,r12
        andis.  r5,r9,DSISR_SRR1_MATCH_32S@h /* Filter relevant SRR1 bits */
        stw     r4, _DAR(r11)
@@ -344,7 +404,7 @@ Alignment:
        EXCEPTION_PROLOG handle_dar_dsisr=1
        save_dar_dsisr_on_stack r4, r5, r11
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       EXC_XFER_STD(0x600, alignment_exception)
+       b       alignment_exception_tramp
 
 /* Program check exception */
        EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)
@@ -645,15 +705,100 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU)
 
        . = 0x3000
 
+machine_check_tramp:
+       EXC_XFER_STD(0x200, machine_check_exception)
+
+alignment_exception_tramp:
+       EXC_XFER_STD(0x600, alignment_exception)
+
 handle_page_fault_tramp_1:
+#ifdef CONFIG_VMAP_STACK
+       EXCEPTION_PROLOG_2 handle_dar_dsisr=1
+#endif
        lwz     r4, _DAR(r11)
        lwz     r5, _DSISR(r11)
        /* fall through */
 handle_page_fault_tramp_2:
        EXC_XFER_LITE(0x300, handle_page_fault)
 
+#ifdef CONFIG_VMAP_STACK
+.macro save_regs_thread                thread
+       stw     r0, THR0(\thread)
+       stw     r3, THR3(\thread)
+       stw     r4, THR4(\thread)
+       stw     r5, THR5(\thread)
+       stw     r6, THR6(\thread)
+       stw     r8, THR8(\thread)
+       stw     r9, THR9(\thread)
+       mflr    r0
+       stw     r0, THLR(\thread)
+       mfctr   r0
+       stw     r0, THCTR(\thread)
+.endm
+
+.macro restore_regs_thread     thread
+       lwz     r0, THLR(\thread)
+       mtlr    r0
+       lwz     r0, THCTR(\thread)
+       mtctr   r0
+       lwz     r0, THR0(\thread)
+       lwz     r3, THR3(\thread)
+       lwz     r4, THR4(\thread)
+       lwz     r5, THR5(\thread)
+       lwz     r6, THR6(\thread)
+       lwz     r8, THR8(\thread)
+       lwz     r9, THR9(\thread)
+.endm
+
+hash_page_dsi:
+       save_regs_thread        r10
+       mfdsisr r3
+       mfdar   r4
+       mfsrr0  r5
+       mfsrr1  r9
+       rlwinm  r3, r3, 32 - 15, _PAGE_RW       /* DSISR_STORE -> _PAGE_RW */
+       bl      hash_page
+       mfspr   r10, SPRN_SPRG_THREAD
+       restore_regs_thread r10
+       b       .Lhash_page_dsi_cont
+
+hash_page_isi:
+       mr      r11, r10
+       mfspr   r10, SPRN_SPRG_THREAD
+       save_regs_thread        r10
+       li      r3, 0
+       lwz     r4, SRR0(r10)
+       lwz     r9, SRR1(r10)
+       bl      hash_page
+       mfspr   r10, SPRN_SPRG_THREAD
+       restore_regs_thread r10
+       mr      r10, r11
+       b       .Lhash_page_isi_cont
+
+       .globl fast_hash_page_return
+fast_hash_page_return:
+       andis.  r10, r9, SRR1_ISI_NOPT@h        /* Set on ISI, cleared on DSI */
+       mfspr   r10, SPRN_SPRG_THREAD
+       restore_regs_thread r10
+       bne     1f
+
+       /* DSI */
+       mtcr    r11
+       lwz     r11, THR11(r10)
+       mfspr   r10, SPRN_SPRG_SCRATCH0
+       SYNC
+       RFI
+
+1:     /* ISI */
+       mtcr    r11
+       mfspr   r11, SPRN_SPRG_SCRATCH1
+       mfspr   r10, SPRN_SPRG_SCRATCH0
+       SYNC
+       RFI
+
 stack_overflow:
        vmap_stack_overflow_exception
+#endif
 
 AltiVecUnavailable:
        EXCEPTION_PROLOG
index a6a5fbb..9db162f 100644 (file)
 .endm
 
 .macro EXCEPTION_PROLOG_2 handle_dar_dsisr=0
+#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
+BEGIN_MMU_FTR_SECTION
+       mtcr    r10
+FTR_SECTION_ELSE
+       stw     r10, _CCR(r11)
+ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
+#else
        stw     r10,_CCR(r11)           /* save registers */
+#endif
+       mfspr   r10, SPRN_SPRG_SCRATCH0
        stw     r12,GPR12(r11)
        stw     r9,GPR9(r11)
-       mfspr   r10,SPRN_SPRG_SCRATCH0
        stw     r10,GPR10(r11)
+#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
+BEGIN_MMU_FTR_SECTION
+       mfcr    r10
+       stw     r10, _CCR(r11)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+#endif
        mfspr   r12,SPRN_SPRG_SCRATCH1
        stw     r12,GPR11(r11)
        mflr    r10
        stw     r10, _DSISR(r11)
        .endif
        lwz     r9, SRR1(r12)
+#if defined(CONFIG_VMAP_STACK) && defined(CONFIG_PPC_BOOK3S)
+BEGIN_MMU_FTR_SECTION
+       andi.   r10, r9, MSR_PR
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_HPTE_TABLE)
+#endif
        lwz     r12, SRR0(r12)
 #else
        mfspr   r12,SPRN_SRR0
index 9922306..073a651 100644 (file)
@@ -256,7 +256,7 @@ InstructionTLBMiss:
         * set.  All other Linux PTE bits control the behavior
         * of the MMU.
         */
-       rlwimi  r10, r10, 0, 0x0f00     /* Clear bits 20-23 */
+       rlwinm  r10, r10, 0, ~0x0f00    /* Clear bits 20-23 */
        rlwimi  r10, r10, 4, 0x0400     /* Copy _PAGE_EXEC into bit 21 */
        ori     r10, r10, RPN_PATTERN | 0x200 /* Set 22 and 24-27 */
        mtspr   SPRN_MI_RPN, r10        /* Update TLB entry */
index 0ffdd18..433d97b 100644 (file)
@@ -166,7 +166,11 @@ BEGIN_FTR_SECTION
        mfspr   r9,SPRN_HID0
        andis.  r9,r9,HID0_NAP@h
        beq     1f
+#ifdef CONFIG_VMAP_STACK
+       addis   r9, r11, nap_save_msscr0@ha
+#else
        addis   r9,r11,(nap_save_msscr0-KERNELBASE)@ha
+#endif
        lwz     r9,nap_save_msscr0@l(r9)
        mtspr   SPRN_MSSCR0, r9
        sync
@@ -174,7 +178,11 @@ BEGIN_FTR_SECTION
 1:
 END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
 BEGIN_FTR_SECTION
+#ifdef CONFIG_VMAP_STACK
+       addis   r9, r11, nap_save_hid1@ha
+#else
        addis   r9,r11,(nap_save_hid1-KERNELBASE)@ha
+#endif
        lwz     r9,nap_save_hid1@l(r9)
        mtspr   SPRN_HID1, r9
 END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
index e6c30ce..d215f95 100644 (file)
@@ -200,14 +200,27 @@ unsigned long get_tm_stackpointer(struct task_struct *tsk)
         * normal/non-checkpointed stack pointer.
         */
 
+       unsigned long ret = tsk->thread.regs->gpr[1];
+
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        BUG_ON(tsk != current);
 
        if (MSR_TM_ACTIVE(tsk->thread.regs->msr)) {
+               preempt_disable();
                tm_reclaim_current(TM_CAUSE_SIGNAL);
                if (MSR_TM_TRANSACTIONAL(tsk->thread.regs->msr))
-                       return tsk->thread.ckpt_regs.gpr[1];
+                       ret = tsk->thread.ckpt_regs.gpr[1];
+
+               /*
+                * If we treclaim, we must clear the current thread's TM bits
+                * before re-enabling preemption. Otherwise we might be
+                * preempted and have the live MSR[TS] changed behind our back
+                * (tm_recheckpoint_new_task() would recheckpoint). Besides, we
+                * enter the signal handler in non-transactional state.
+                */
+               tsk->thread.regs->msr &= ~MSR_TS_MASK;
+               preempt_enable();
        }
 #endif
-       return tsk->thread.regs->gpr[1];
+       return ret;
 }
index 98600b2..1b090a7 100644 (file)
@@ -489,19 +489,11 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame,
  */
 static int save_tm_user_regs(struct pt_regs *regs,
                             struct mcontext __user *frame,
-                            struct mcontext __user *tm_frame, int sigret)
+                            struct mcontext __user *tm_frame, int sigret,
+                            unsigned long msr)
 {
-       unsigned long msr = regs->msr;
-
        WARN_ON(tm_suspend_disabled);
 
-       /* Remove TM bits from thread's MSR.  The MSR in the sigcontext
-        * just indicates to userland that we were doing a transaction, but we
-        * don't want to return in transactional state.  This also ensures
-        * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
-        */
-       regs->msr &= ~MSR_TS_MASK;
-
        /* Save both sets of general registers */
        if (save_general_regs(&current->thread.ckpt_regs, frame)
            || save_general_regs(regs, tm_frame))
@@ -912,6 +904,10 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
        int sigret;
        unsigned long tramp;
        struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       /* Save the thread's msr before get_tm_stackpointer() changes it */
+       unsigned long msr = regs->msr;
+#endif
 
        BUG_ON(tsk != current);
 
@@ -944,13 +940,13 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        tm_frame = &rt_sf->uc_transact.uc_mcontext;
-       if (MSR_TM_ACTIVE(regs->msr)) {
+       if (MSR_TM_ACTIVE(msr)) {
                if (__put_user((unsigned long)&rt_sf->uc_transact,
                               &rt_sf->uc.uc_link) ||
                    __put_user((unsigned long)tm_frame,
                               &rt_sf->uc_transact.uc_regs))
                        goto badframe;
-               if (save_tm_user_regs(regs, frame, tm_frame, sigret))
+               if (save_tm_user_regs(regs, frame, tm_frame, sigret, msr))
                        goto badframe;
        }
        else
@@ -1369,6 +1365,10 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
        int sigret;
        unsigned long tramp;
        struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       /* Save the thread's msr before get_tm_stackpointer() changes it */
+       unsigned long msr = regs->msr;
+#endif
 
        BUG_ON(tsk != current);
 
@@ -1402,9 +1402,9 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
        tm_mctx = &frame->mctx_transact;
-       if (MSR_TM_ACTIVE(regs->msr)) {
+       if (MSR_TM_ACTIVE(msr)) {
                if (save_tm_user_regs(regs, &frame->mctx, &frame->mctx_transact,
-                                     sigret))
+                                     sigret, msr))
                        goto badframe;
        }
        else
index 1175155..84ed2e7 100644 (file)
@@ -192,7 +192,8 @@ static long setup_sigcontext(struct sigcontext __user *sc,
 static long setup_tm_sigcontexts(struct sigcontext __user *sc,
                                 struct sigcontext __user *tm_sc,
                                 struct task_struct *tsk,
-                                int signr, sigset_t *set, unsigned long handler)
+                                int signr, sigset_t *set, unsigned long handler,
+                                unsigned long msr)
 {
        /* When CONFIG_ALTIVEC is set, we _always_ setup v_regs even if the
         * process never used altivec yet (MSR_VEC is zero in pt_regs of
@@ -207,12 +208,11 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
        elf_vrreg_t __user *tm_v_regs = sigcontext_vmx_regs(tm_sc);
 #endif
        struct pt_regs *regs = tsk->thread.regs;
-       unsigned long msr = tsk->thread.regs->msr;
        long err = 0;
 
        BUG_ON(tsk != current);
 
-       BUG_ON(!MSR_TM_ACTIVE(regs->msr));
+       BUG_ON(!MSR_TM_ACTIVE(msr));
 
        WARN_ON(tm_suspend_disabled);
 
@@ -222,13 +222,6 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
         */
        msr |= tsk->thread.ckpt_regs.msr & (MSR_FP | MSR_VEC | MSR_VSX);
 
-       /* Remove TM bits from thread's MSR.  The MSR in the sigcontext
-        * just indicates to userland that we were doing a transaction, but we
-        * don't want to return in transactional state.  This also ensures
-        * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
-        */
-       regs->msr &= ~MSR_TS_MASK;
-
 #ifdef CONFIG_ALTIVEC
        err |= __put_user(v_regs, &sc->v_regs);
        err |= __put_user(tm_v_regs, &tm_sc->v_regs);
@@ -824,6 +817,10 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
        unsigned long newsp = 0;
        long err = 0;
        struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       /* Save the thread's msr before get_tm_stackpointer() changes it */
+       unsigned long msr = regs->msr;
+#endif
 
        BUG_ON(tsk != current);
 
@@ -841,7 +838,7 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
        err |= __put_user(0, &frame->uc.uc_flags);
        err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]);
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-       if (MSR_TM_ACTIVE(regs->msr)) {
+       if (MSR_TM_ACTIVE(msr)) {
                /* The ucontext_t passed to userland points to the second
                 * ucontext_t (for transactional state) with its uc_link ptr.
                 */
@@ -849,7 +846,8 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
                err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
                                            &frame->uc_transact.uc_mcontext,
                                            tsk, ksig->sig, NULL,
-                                           (unsigned long)ksig->ka.sa.sa_handler);
+                                           (unsigned long)ksig->ka.sa.sa_handler,
+                                           msr);
        } else
 #endif
        {
index c11b0a0..2015c4f 100644 (file)
 #include <asm/feature-fixups.h>
 #include <asm/code-patching-asm.h>
 
-#ifdef CONFIG_VMAP_STACK
-#define ADDR_OFFSET    0
-#else
-#define ADDR_OFFSET    PAGE_OFFSET
-#endif
-
 #ifdef CONFIG_SMP
        .section .bss
        .align  2
@@ -53,8 +47,8 @@ mmu_hash_lock:
        .text
 _GLOBAL(hash_page)
 #ifdef CONFIG_SMP
-       lis     r8, (mmu_hash_lock - ADDR_OFFSET)@h
-       ori     r8, r8, (mmu_hash_lock - ADDR_OFFSET)@l
+       lis     r8, (mmu_hash_lock - PAGE_OFFSET)@h
+       ori     r8, r8, (mmu_hash_lock - PAGE_OFFSET)@l
        lis     r0,0x0fff
        b       10f
 11:    lwz     r6,0(r8)
@@ -72,12 +66,9 @@ _GLOBAL(hash_page)
        cmplw   0,r4,r0
        ori     r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */
        mfspr   r5, SPRN_SPRG_PGDIR     /* phys page-table root */
-#ifdef CONFIG_VMAP_STACK
-       tovirt(r5, r5)
-#endif
        blt+    112f                    /* assume user more likely */
-       lis     r5, (swapper_pg_dir - ADDR_OFFSET)@ha   /* if kernel address, use */
-       addi    r5 ,r5 ,(swapper_pg_dir - ADDR_OFFSET)@l        /* kernel page table */
+       lis     r5, (swapper_pg_dir - PAGE_OFFSET)@ha   /* if kernel address, use */
+       addi    r5 ,r5 ,(swapper_pg_dir - PAGE_OFFSET)@l        /* kernel page table */
        rlwimi  r3,r9,32-12,29,29       /* MSR_PR -> _PAGE_USER */
 112:
 #ifndef CONFIG_PTE_64BIT
@@ -89,9 +80,6 @@ _GLOBAL(hash_page)
        lwzx    r8,r8,r5                /* Get L1 entry */
        rlwinm. r8,r8,0,0,20            /* extract pt base address */
 #endif
-#ifdef CONFIG_VMAP_STACK
-       tovirt(r8, r8)
-#endif
 #ifdef CONFIG_SMP
        beq-    hash_page_out           /* return if no mapping */
 #else
@@ -143,30 +131,36 @@ retry:
        bne-    retry                   /* retry if someone got there first */
 
        mfsrin  r3,r4                   /* get segment reg for segment */
+#ifndef CONFIG_VMAP_STACK
        mfctr   r0
        stw     r0,_CTR(r11)
+#endif
        bl      create_hpte             /* add the hash table entry */
 
 #ifdef CONFIG_SMP
        eieio
-       lis     r8, (mmu_hash_lock - ADDR_OFFSET)@ha
+       lis     r8, (mmu_hash_lock - PAGE_OFFSET)@ha
        li      r0,0
-       stw     r0, (mmu_hash_lock - ADDR_OFFSET)@l(r8)
+       stw     r0, (mmu_hash_lock - PAGE_OFFSET)@l(r8)
 #endif
 
+#ifdef CONFIG_VMAP_STACK
+       b       fast_hash_page_return
+#else
        /* Return from the exception */
        lwz     r5,_CTR(r11)
        mtctr   r5
        lwz     r0,GPR0(r11)
        lwz     r8,GPR8(r11)
        b       fast_exception_return
+#endif
 
 #ifdef CONFIG_SMP
 hash_page_out:
        eieio
-       lis     r8, (mmu_hash_lock - ADDR_OFFSET)@ha
+       lis     r8, (mmu_hash_lock - PAGE_OFFSET)@ha
        li      r0,0
-       stw     r0, (mmu_hash_lock - ADDR_OFFSET)@l(r8)
+       stw     r0, (mmu_hash_lock - PAGE_OFFSET)@l(r8)
        blr
 #endif /* CONFIG_SMP */
 
@@ -341,7 +335,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
        patch_site      1f, patch__hash_page_A1
        patch_site      2f, patch__hash_page_A2
        /* Get the address of the primary PTE group in the hash table (r3) */
-0:     lis     r0, (Hash_base - ADDR_OFFSET)@h /* base address of hash table */
+0:     lis     r0, (Hash_base - PAGE_OFFSET)@h /* base address of hash table */
 1:     rlwimi  r0,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT    /* VSID -> hash */
 2:     rlwinm  r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
        xor     r3,r3,r0                /* make primary hash */
@@ -355,10 +349,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
        beq+    10f                     /* no PTE: go look for an empty slot */
        tlbie   r4
 
-       lis     r4, (htab_hash_searches - ADDR_OFFSET)@ha
-       lwz     r6, (htab_hash_searches - ADDR_OFFSET)@l(r4)
+       lis     r4, (htab_hash_searches - PAGE_OFFSET)@ha
+       lwz     r6, (htab_hash_searches - PAGE_OFFSET)@l(r4)
        addi    r6,r6,1                 /* count how many searches we do */
-       stw     r6, (htab_hash_searches - ADDR_OFFSET)@l(r4)
+       stw     r6, (htab_hash_searches - PAGE_OFFSET)@l(r4)
 
        /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
        mtctr   r0
@@ -390,10 +384,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
        beq+    found_empty
 
        /* update counter of times that the primary PTEG is full */
-       lis     r4, (primary_pteg_full - ADDR_OFFSET)@ha
-       lwz     r6, (primary_pteg_full - ADDR_OFFSET)@l(r4)
+       lis     r4, (primary_pteg_full - PAGE_OFFSET)@ha
+       lwz     r6, (primary_pteg_full - PAGE_OFFSET)@l(r4)
        addi    r6,r6,1
-       stw     r6, (primary_pteg_full - ADDR_OFFSET)@l(r4)
+       stw     r6, (primary_pteg_full - PAGE_OFFSET)@l(r4)
 
        patch_site      0f, patch__hash_page_C
        /* Search the secondary PTEG for an empty slot */
@@ -427,8 +421,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT)
         * lockup here but that shouldn't happen
         */
 
-1:     lis     r4, (next_slot - ADDR_OFFSET)@ha        /* get next evict slot */
-       lwz     r6, (next_slot - ADDR_OFFSET)@l(r4)
+1:     lis     r4, (next_slot - PAGE_OFFSET)@ha        /* get next evict slot */
+       lwz     r6, (next_slot - PAGE_OFFSET)@l(r4)
        addi    r6,r6,HPTE_SIZE                 /* search for candidate */
        andi.   r6,r6,7*HPTE_SIZE
        stw     r6,next_slot@l(r4)
index 0a1c65a..f888cbb 100644 (file)
@@ -413,7 +413,7 @@ void __init MMU_init_hw(void)
 void __init MMU_init_hw_patch(void)
 {
        unsigned int hmask = Hash_mask >> (16 - LG_HPTEG_SIZE);
-       unsigned int hash;
+       unsigned int hash = (unsigned int)Hash - PAGE_OFFSET;
 
        if (ppc_md.progress)
                ppc_md.progress("hash:patch", 0x345);
@@ -425,11 +425,6 @@ void __init MMU_init_hw_patch(void)
        /*
         * Patch up the instructions in hashtable.S:create_hpte
         */
-       if (IS_ENABLED(CONFIG_VMAP_STACK))
-               hash = (unsigned int)Hash;
-       else
-               hash = (unsigned int)Hash - PAGE_OFFSET;
-
        modify_instruction_site(&patch__hash_page_A0, 0xffff, hash >> 16);
        modify_instruction_site(&patch__hash_page_A1, 0x7c0, hash_mb << 6);
        modify_instruction_site(&patch__hash_page_A2, 0x7c0, hash_mb2 << 6);
@@ -439,8 +434,7 @@ void __init MMU_init_hw_patch(void)
        /*
         * Patch up the instructions in hashtable.S:flush_hash_page
         */
-       modify_instruction_site(&patch__flush_hash_A0, 0xffff,
-                               ((unsigned int)Hash - PAGE_OFFSET) >> 16);
+       modify_instruction_site(&patch__flush_hash_A0, 0xffff, hash >> 16);
        modify_instruction_site(&patch__flush_hash_A1, 0x7c0, hash_mb << 6);
        modify_instruction_site(&patch__flush_hash_A2, 0x7c0, hash_mb2 << 6);
        modify_instruction_site(&patch__flush_hash_B, 0xffff, hmask);
index 73d4873..33b3461 100644 (file)
@@ -53,20 +53,24 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
        if (pshift >= pdshift) {
                cachep = PGT_CACHE(PTE_T_ORDER);
                num_hugepd = 1 << (pshift - pdshift);
+               new = NULL;
        } else if (IS_ENABLED(CONFIG_PPC_8xx)) {
-               cachep = PGT_CACHE(PTE_INDEX_SIZE);
+               cachep = NULL;
                num_hugepd = 1;
+               new = pte_alloc_one(mm);
        } else {
                cachep = PGT_CACHE(pdshift - pshift);
                num_hugepd = 1;
+               new = NULL;
        }
 
-       if (!cachep) {
+       if (!cachep && !new) {
                WARN_ONCE(1, "No page table cache created for hugetlb tables");
                return -ENOMEM;
        }
 
-       new = kmem_cache_alloc(cachep, pgtable_gfp_flags(mm, GFP_KERNEL));
+       if (cachep)
+               new = kmem_cache_alloc(cachep, pgtable_gfp_flags(mm, GFP_KERNEL));
 
        BUG_ON(pshift > HUGEPD_SHIFT_MASK);
        BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK);
@@ -97,7 +101,10 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp,
        if (i < num_hugepd) {
                for (i = i - 1 ; i >= 0; i--, hpdp--)
                        *hpdp = __hugepd(0);
-               kmem_cache_free(cachep, new);
+               if (cachep)
+                       kmem_cache_free(cachep, new);
+               else
+                       pte_free(mm, new);
        } else {
                kmemleak_ignore(new);
        }
@@ -324,8 +331,7 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif
        if (shift >= pdshift)
                hugepd_free(tlb, hugepte);
        else if (IS_ENABLED(CONFIG_PPC_8xx))
-               pgtable_free_tlb(tlb, hugepte,
-                                get_hugepd_cache_index(PTE_INDEX_SIZE));
+               pgtable_free_tlb(tlb, hugepte, 0);
        else
                pgtable_free_tlb(tlb, hugepte,
                                 get_hugepd_cache_index(pdshift - shift));
@@ -639,12 +645,13 @@ static int __init hugetlbpage_init(void)
                 * if we have pdshift and shift value same, we don't
                 * use pgt cache for hugepd.
                 */
-               if (pdshift > shift && IS_ENABLED(CONFIG_PPC_8xx))
-                       pgtable_cache_add(PTE_INDEX_SIZE);
-               else if (pdshift > shift)
-                       pgtable_cache_add(pdshift - shift);
-               else if (IS_ENABLED(CONFIG_PPC_FSL_BOOK3E) || IS_ENABLED(CONFIG_PPC_8xx))
+               if (pdshift > shift) {
+                       if (!IS_ENABLED(CONFIG_PPC_8xx))
+                               pgtable_cache_add(pdshift - shift);
+               } else if (IS_ENABLED(CONFIG_PPC_FSL_BOOK3E) ||
+                          IS_ENABLED(CONFIG_PPC_8xx)) {
                        pgtable_cache_add(PTE_T_ORDER);
+               }
 
                configured = true;
        }
index 16dd95b..db5664d 100644 (file)
@@ -185,8 +185,7 @@ u8 __initdata early_hash[256 << 10] __aligned(256 << 10) = {0};
 
 static void __init kasan_early_hash_table(void)
 {
-       unsigned int hash = IS_ENABLED(CONFIG_VMAP_STACK) ? (unsigned int)early_hash :
-                                                           __pa(early_hash);
+       unsigned int hash = __pa(early_hash);
 
        modify_instruction_site(&patch__hash_page_A0, 0xffff, hash >> 16);
        modify_instruction_site(&patch__flush_hash_A0, 0xffff, hash >> 16);
index e8c84d2..0ec9640 100644 (file)
@@ -3435,6 +3435,11 @@ getstring(char *s, int size)
        int c;
 
        c = skipbl();
+       if (c == '\n') {
+               *s = 0;
+               return;
+       }
+
        do {
                if( size > 1 ){
                        *s++ = c;
index e0e3a46..8dfa2cf 100644 (file)
@@ -146,7 +146,7 @@ all: bzImage
 #KBUILD_IMAGE is necessary for packaging targets like rpm-pkg, deb-pkg...
 KBUILD_IMAGE   := $(boot)/bzImage
 
-install: vmlinux
+install:
        $(Q)$(MAKE) $(build)=$(boot) $@
 
 bzImage: vmlinux
index e2c47d3..0ff9261 100644 (file)
@@ -70,7 +70,7 @@ $(obj)/compressed/vmlinux: $(obj)/startup.a FORCE
 $(obj)/startup.a: $(OBJECTS) FORCE
        $(call if_changed,ar)
 
-install: $(CONFIGURE) $(obj)/bzImage
+install:
        sh -x  $(srctree)/$(obj)/install.sh $(KERNELRELEASE) $(obj)/bzImage \
              System.map "$(INSTALL_PATH)"
 
index 5d12352..5591243 100644 (file)
@@ -75,7 +75,7 @@ static unsigned long get_random(unsigned long limit)
                *(unsigned long *) prng.parm_block ^= seed;
                for (i = 0; i < 16; i++) {
                        cpacf_kmc(CPACF_KMC_PRNG, prng.parm_block,
-                                 (char *) entropy, (char *) entropy,
+                                 (u8 *) entropy, (u8 *) entropy,
                                  sizeof(entropy));
                        memcpy(prng.parm_block, entropy, sizeof(entropy));
                }
index 2e60c80..0c86ba1 100644 (file)
@@ -53,6 +53,7 @@ CONFIG_VFIO_AP=m
 CONFIG_CRASH_DUMP=y
 CONFIG_HIBERNATION=y
 CONFIG_PM_DEBUG=y
+CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
 CONFIG_KVM=m
@@ -474,7 +475,6 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_EMULEX is not set
 # CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_GOOGLE is not set
-# CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -684,7 +684,6 @@ CONFIG_CRYPTO_ADIANTUM=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
-CONFIG_CRYPTO_XXHASH=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
@@ -748,7 +747,6 @@ CONFIG_DEBUG_INFO_DWARF4=y
 CONFIG_GDB_SCRIPTS=y
 CONFIG_FRAME_WARN=1024
 CONFIG_HEADERS_INSTALL=y
-CONFIG_HEADERS_CHECK=y
 CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_PAGEALLOC=y
@@ -772,9 +770,9 @@ CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_MEMORY_NOTIFIER_ERROR_INJECT=m
 CONFIG_DEBUG_PER_CPU_MAPS=y
 CONFIG_DEBUG_SHIRQ=y
+CONFIG_PANIC_ON_OOPS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_WQ_WATCHDOG=y
-CONFIG_PANIC_ON_OOPS=y
 CONFIG_DEBUG_TIMEKEEPING=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_LOCK_STAT=y
@@ -783,9 +781,20 @@ CONFIG_DEBUG_ATOMIC_SLEEP=y
 CONFIG_DEBUG_LOCKING_API_SELFTESTS=y
 CONFIG_DEBUG_SG=y
 CONFIG_DEBUG_NOTIFIERS=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_DEBUG_CREDENTIALS=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=300
+CONFIG_LATENCYTOP=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_STACK_TRACER=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
+CONFIG_SCHED_TRACER=y
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_HIST_TRIGGERS=y
+CONFIG_S390_PTDUMP=y
 CONFIG_NOTIFIER_ERROR_INJECTION=m
 CONFIG_NETDEV_NOTIFIER_ERROR_INJECT=m
 CONFIG_FAULT_INJECTION=y
@@ -796,15 +805,6 @@ CONFIG_FAIL_IO_TIMEOUT=y
 CONFIG_FAIL_FUTEX=y
 CONFIG_FAULT_INJECTION_DEBUG_FS=y
 CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
-CONFIG_LATENCYTOP=y
-CONFIG_IRQSOFF_TRACER=y
-CONFIG_PREEMPT_TRACER=y
-CONFIG_SCHED_TRACER=y
-CONFIG_FTRACE_SYSCALLS=y
-CONFIG_STACK_TRACER=y
-CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_FUNCTION_PROFILER=y
-CONFIG_HIST_TRIGGERS=y
 CONFIG_LKDTM=m
 CONFIG_TEST_LIST_SORT=y
 CONFIG_TEST_SORT=y
@@ -814,5 +814,3 @@ CONFIG_INTERVAL_TREE_TEST=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
-CONFIG_BUG_ON_DATA_CORRUPTION=y
-CONFIG_S390_PTDUMP=y
index 25f7998..6b27d86 100644 (file)
@@ -53,6 +53,7 @@ CONFIG_VFIO_AP=m
 CONFIG_CRASH_DUMP=y
 CONFIG_HIBERNATION=y
 CONFIG_PM_DEBUG=y
+CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y
 CONFIG_CMM=m
 CONFIG_APPLDATA_BASE=y
 CONFIG_KVM=m
@@ -470,7 +471,6 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_EMULEX is not set
 # CONFIG_NET_VENDOR_EZCHIP is not set
 # CONFIG_NET_VENDOR_GOOGLE is not set
-# CONFIG_NET_VENDOR_HP is not set
 # CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
@@ -677,7 +677,6 @@ CONFIG_CRYPTO_ADIANTUM=m
 CONFIG_CRYPTO_XCBC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_CRC32=m
-CONFIG_CRYPTO_XXHASH=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD128=m
 CONFIG_CRYPTO_RMD160=m
@@ -739,18 +738,18 @@ CONFIG_DEBUG_SECTION_MISMATCH=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_PANIC_ON_OOPS=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
 CONFIG_RCU_TORTURE_TEST=m
 CONFIG_RCU_CPU_STALL_TIMEOUT=60
 CONFIG_LATENCYTOP=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_STACK_TRACER=y
 CONFIG_SCHED_TRACER=y
 CONFIG_FTRACE_SYSCALLS=y
-CONFIG_STACK_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_FUNCTION_PROFILER=y
 CONFIG_HIST_TRIGGERS=y
+CONFIG_S390_PTDUMP=y
 CONFIG_LKDTM=m
 CONFIG_PERCPU_TEST=m
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_TEST_BPF=m
-CONFIG_BUG_ON_DATA_CORRUPTION=y
-CONFIG_S390_PTDUMP=y
index 85e944f..1019efd 100644 (file)
@@ -42,7 +42,7 @@ void __storage_key_init_range(unsigned long start, unsigned long end);
 
 static inline void storage_key_init_range(unsigned long start, unsigned long end)
 {
-       if (PAGE_DEFAULT_KEY)
+       if (PAGE_DEFAULT_KEY != 0)
                __storage_key_init_range(start, end);
 }
 
index 361ef5e..aadb3d0 100644 (file)
@@ -84,7 +84,6 @@ void s390_update_cpu_mhz(void);
 void cpu_detect_mhz_feature(void);
 
 extern const struct seq_operations cpuinfo_op;
-extern int sysctl_ieee_emulation_warnings;
 extern void execve_tail(void);
 extern void __bpon(void);
 
index 71e3f01..1e3517b 100644 (file)
@@ -201,7 +201,7 @@ struct slib {
  * @scount: SBAL count
  * @sflags: whole SBAL flags
  * @length: length
- * @addr: address
+ * @addr: absolute data address
 */
 struct qdio_buffer_element {
        u8 eflags;
@@ -211,7 +211,7 @@ struct qdio_buffer_element {
        u8 scount;
        u8 sflags;
        u32 length;
-       void *addr;
+       u64 addr;
 } __attribute__ ((packed, aligned(16)));
 
 /**
@@ -227,7 +227,7 @@ struct qdio_buffer {
  * @sbal: absolute SBAL address
  */
 struct sl_element {
-       unsigned long sbal;
+       u64 sbal;
 } __attribute__ ((packed));
 
 /**
index 748456c..9557c5a 100644 (file)
@@ -29,9 +29,6 @@
 #define __PAGE_OFFSET __PAGE_OFFSET_BASE
 #include "../../mm/ident_map.c"
 
-/* Used by pgtable.h asm code to force instruction serialization. */
-unsigned long __force_order;
-
 /* Used to track our page table allocation area. */
 struct alloc_pgt_data {
        unsigned char *pgt_buf;
index ebe1685..d5e517d 100644 (file)
 #define MSR_K7_HWCR                    0xc0010015
 #define MSR_K7_HWCR_SMMLOCK_BIT                0
 #define MSR_K7_HWCR_SMMLOCK            BIT_ULL(MSR_K7_HWCR_SMMLOCK_BIT)
+#define MSR_K7_HWCR_IRPERF_EN_BIT      30
+#define MSR_K7_HWCR_IRPERF_EN          BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT)
 #define MSR_K7_FID_VID_CTL             0xc0010041
 #define MSR_K7_FID_VID_STATUS          0xc0010042
 
index ac83a0f..1f875fb 100644 (file)
@@ -28,6 +28,7 @@
 
 static const int amd_erratum_383[];
 static const int amd_erratum_400[];
+static const int amd_erratum_1054[];
 static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
 
 /*
@@ -972,6 +973,15 @@ static void init_amd(struct cpuinfo_x86 *c)
        /* AMD CPUs don't reset SS attributes on SYSRET, Xen does. */
        if (!cpu_has(c, X86_FEATURE_XENPV))
                set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+
+       /*
+        * Turn on the Instructions Retired free counter on machines not
+        * susceptible to erratum #1054 "Instructions Retired Performance
+        * Counter May Be Inaccurate".
+        */
+       if (cpu_has(c, X86_FEATURE_IRPERF) &&
+           !cpu_has_amd_erratum(c, amd_erratum_1054))
+               msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT);
 }
 
 #ifdef CONFIG_X86_32
@@ -1099,6 +1109,10 @@ static const int amd_erratum_400[] =
 static const int amd_erratum_383[] =
        AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
 
+/* #1054: Instructions Retired Performance Counter May Be Inaccurate */
+static const int amd_erratum_1054[] =
+       AMD_OSVW_ERRATUM(0, AMD_MODEL_RANGE(0x17, 0, 0, 0x2f, 0xf));
+
 
 static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
 {
index b3a50d9..52de616 100644 (file)
@@ -1163,9 +1163,12 @@ static const struct sysfs_ops threshold_ops = {
        .store                  = store,
 };
 
+static void threshold_block_release(struct kobject *kobj);
+
 static struct kobj_type threshold_ktype = {
        .sysfs_ops              = &threshold_ops,
        .default_attrs          = default_attrs,
+       .release                = threshold_block_release,
 };
 
 static const char *get_name(unsigned int bank, struct threshold_block *b)
@@ -1198,8 +1201,9 @@ static const char *get_name(unsigned int bank, struct threshold_block *b)
        return buf_mcatype;
 }
 
-static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
-                                    unsigned int block, u32 address)
+static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb,
+                                    unsigned int bank, unsigned int block,
+                                    u32 address)
 {
        struct threshold_block *b = NULL;
        u32 low, high;
@@ -1243,16 +1247,12 @@ static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
 
        INIT_LIST_HEAD(&b->miscj);
 
-       if (per_cpu(threshold_banks, cpu)[bank]->blocks) {
-               list_add(&b->miscj,
-                        &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj);
-       } else {
-               per_cpu(threshold_banks, cpu)[bank]->blocks = b;
-       }
+       if (tb->blocks)
+               list_add(&b->miscj, &tb->blocks->miscj);
+       else
+               tb->blocks = b;
 
-       err = kobject_init_and_add(&b->kobj, &threshold_ktype,
-                                  per_cpu(threshold_banks, cpu)[bank]->kobj,
-                                  get_name(bank, b));
+       err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(bank, b));
        if (err)
                goto out_free;
 recurse:
@@ -1260,7 +1260,7 @@ recurse:
        if (!address)
                return 0;
 
-       err = allocate_threshold_blocks(cpu, bank, block, address);
+       err = allocate_threshold_blocks(cpu, tb, bank, block, address);
        if (err)
                goto out_free;
 
@@ -1345,8 +1345,6 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
                goto out_free;
        }
 
-       per_cpu(threshold_banks, cpu)[bank] = b;
-
        if (is_shared_bank(bank)) {
                refcount_set(&b->cpus, 1);
 
@@ -1357,9 +1355,13 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
                }
        }
 
-       err = allocate_threshold_blocks(cpu, bank, 0, msr_ops.misc(bank));
-       if (!err)
-               goto out;
+       err = allocate_threshold_blocks(cpu, b, bank, 0, msr_ops.misc(bank));
+       if (err)
+               goto out_free;
+
+       per_cpu(threshold_banks, cpu)[bank] = b;
+
+       return 0;
 
  out_free:
        kfree(b);
@@ -1368,8 +1370,12 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
        return err;
 }
 
-static void deallocate_threshold_block(unsigned int cpu,
-                                                unsigned int bank)
+static void threshold_block_release(struct kobject *kobj)
+{
+       kfree(to_block(kobj));
+}
+
+static void deallocate_threshold_block(unsigned int cpu, unsigned int bank)
 {
        struct threshold_block *pos = NULL;
        struct threshold_block *tmp = NULL;
@@ -1379,13 +1385,11 @@ static void deallocate_threshold_block(unsigned int cpu,
                return;
 
        list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) {
-               kobject_put(&pos->kobj);
                list_del(&pos->miscj);
-               kfree(pos);
+               kobject_put(&pos->kobj);
        }
 
-       kfree(per_cpu(threshold_banks, cpu)[bank]->blocks);
-       per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
+       kobject_put(&head->blocks->kobj);
 }
 
 static void __threshold_remove_blocks(struct threshold_bank *b)
index 4d4f5d9..2305490 100644 (file)
@@ -10,8 +10,6 @@ extern struct boot_params boot_params;
 
 static enum efi_secureboot_mode get_sb_mode(void)
 {
-       efi_char16_t efi_SecureBoot_name[] = L"SecureBoot";
-       efi_char16_t efi_SetupMode_name[] = L"SecureBoot";
        efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
        efi_status_t status;
        unsigned long size;
@@ -25,7 +23,7 @@ static enum efi_secureboot_mode get_sb_mode(void)
        }
 
        /* Get variable contents into buffer */
-       status = efi.get_variable(efi_SecureBoot_name, &efi_variable_guid,
+       status = efi.get_variable(L"SecureBoot", &efi_variable_guid,
                                  NULL, &size, &secboot);
        if (status == EFI_NOT_FOUND) {
                pr_info("ima: secureboot mode disabled\n");
@@ -38,7 +36,7 @@ static enum efi_secureboot_mode get_sb_mode(void)
        }
 
        size = sizeof(setupmode);
-       status = efi.get_variable(efi_SetupMode_name, &efi_variable_guid,
+       status = efi.get_variable(L"SetupMode", &efi_variable_guid,
                                  NULL, &size, &setupmode);
 
        if (status != EFI_SUCCESS)      /* ignore unknown SetupMode */
index 1f756ff..7940912 100644 (file)
@@ -896,14 +896,15 @@ static u64 xen_read_msr_safe(unsigned int msr, int *err)
 static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
 {
        int ret;
+#ifdef CONFIG_X86_64
+       unsigned int which;
+       u64 base;
+#endif
 
        ret = 0;
 
        switch (msr) {
 #ifdef CONFIG_X86_64
-               unsigned which;
-               u64 base;
-
        case MSR_FS_BASE:               which = SEGBASE_FS; goto set;
        case MSR_KERNEL_GS_BASE:        which = SEGBASE_GS_USER; goto set;
        case MSR_GS_BASE:               which = SEGBASE_GS_KERNEL; goto set;
index c754cb7..a49ff96 100644 (file)
@@ -26,7 +26,7 @@ const char *const hash_algo_name[HASH_ALGO__LAST] = {
        [HASH_ALGO_TGR_128]     = "tgr128",
        [HASH_ALGO_TGR_160]     = "tgr160",
        [HASH_ALGO_TGR_192]     = "tgr192",
-       [HASH_ALGO_SM3_256]     = "sm3-256",
+       [HASH_ALGO_SM3_256]     = "sm3",
        [HASH_ALGO_STREEBOG_256] = "streebog256",
        [HASH_ALGO_STREEBOG_512] = "streebog512",
 };
index 8c83d8c..789d5e9 100644 (file)
@@ -265,4 +265,49 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event)
                 handler) (acpi_gbl_fixed_event_handlers[event].context));
 }
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_any_fixed_event_status_set
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      TRUE or FALSE
+ *
+ * DESCRIPTION: Checks the PM status register for active fixed events
+ *
+ ******************************************************************************/
+
+u32 acpi_any_fixed_event_status_set(void)
+{
+       acpi_status status;
+       u32 in_status;
+       u32 in_enable;
+       u32 i;
+
+       status = acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &in_enable);
+       if (ACPI_FAILURE(status)) {
+               return (FALSE);
+       }
+
+       status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &in_status);
+       if (ACPI_FAILURE(status)) {
+               return (FALSE);
+       }
+
+       /*
+        * Check for all possible Fixed Events and dispatch those that are active
+        */
+       for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
+
+               /* Both the status and enable bits must be on for this event */
+
+               if ((in_status & acpi_gbl_fixed_event_info[i].status_bit_mask) &&
+                   (in_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) {
+                       return (TRUE);
+               }
+       }
+
+       return (FALSE);
+}
+
 #endif                         /* !ACPI_REDUCED_HARDWARE */
index 152f7fc..e5f9592 100644 (file)
@@ -1005,6 +1005,13 @@ static bool acpi_s2idle_wake(void)
                if (irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq)))
                        return true;
 
+               /*
+                * If the status bit of any enabled fixed event is set, the
+                * wakeup is regarded as valid.
+                */
+               if (acpi_any_fixed_event_status_set())
+                       return true;
+
                /*
                 * If there are no EC events to process and at least one of the
                 * other enabled GPEs is active, the wakeup is regarded as a
index 5a0d99d..9567e51 100644 (file)
@@ -21,9 +21,11 @@ tpm-$(CONFIG_EFI) += eventlog/efi.o
 tpm-$(CONFIG_OF) += eventlog/of.o
 obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
 obj-$(CONFIG_TCG_TIS) += tpm_tis.o
-obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi_mod.o
-tpm_tis_spi_mod-y := tpm_tis_spi.o
-tpm_tis_spi_mod-$(CONFIG_TCG_TIS_SPI_CR50) += tpm_tis_spi_cr50.o
+
+obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o
+tpm_tis_spi-y := tpm_tis_spi_main.o
+tpm_tis_spi-$(CONFIG_TCG_TIS_SPI_CR50) += tpm_tis_spi_cr50.o
+
 obj-$(CONFIG_TCG_TIS_I2C_ATMEL) += tpm_i2c_atmel.o
 obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o
 obj-$(CONFIG_TCG_TIS_I2C_NUVOTON) += tpm_i2c_nuvoton.o
index 13696de..7603295 100644 (file)
@@ -525,6 +525,8 @@ static int tpm2_init_bank_info(struct tpm_chip *chip, u32 bank_index)
                return 0;
        }
 
+       bank->crypto_id = HASH_ALGO__LAST;
+
        return tpm2_pcr_read(chip, 0, &digest, &bank->digest_size);
 }
 
diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c
deleted file mode 100644 (file)
index d1754fd..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2015 Infineon Technologies AG
- * Copyright (C) 2016 STMicroelectronics SAS
- *
- * Authors:
- * Peter Huewe <peter.huewe@infineon.com>
- * Christophe Ricard <christophe-h.ricard@st.com>
- *
- * Maintained by: <tpmdd-devel@lists.sourceforge.net>
- *
- * Device driver for TCG/TCPA TPM (trusted platform module).
- * Specifications at www.trustedcomputinggroup.org
- *
- * This device driver implements the TPM interface as defined in
- * the TCG TPM Interface Spec version 1.3, revision 27 via _raw/native
- * SPI access_.
- *
- * It is based on the original tpm_tis device driver from Leendert van
- * Dorn and Kyleen Hall and Jarko Sakkinnen.
- */
-
-#include <linux/acpi.h>
-#include <linux/completion.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include <linux/of_device.h>
-#include <linux/spi/spi.h>
-#include <linux/tpm.h>
-
-#include "tpm.h"
-#include "tpm_tis_core.h"
-#include "tpm_tis_spi.h"
-
-#define MAX_SPI_FRAMESIZE 64
-
-/*
- * TCG SPI flow control is documented in section 6.4 of the spec[1]. In short,
- * keep trying to read from the device until MISO goes high indicating the
- * wait state has ended.
- *
- * [1] https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
- */
-static int tpm_tis_spi_flow_control(struct tpm_tis_spi_phy *phy,
-                                   struct spi_transfer *spi_xfer)
-{
-       struct spi_message m;
-       int ret, i;
-
-       if ((phy->iobuf[3] & 0x01) == 0) {
-               // handle SPI wait states
-               phy->iobuf[0] = 0;
-
-               for (i = 0; i < TPM_RETRY; i++) {
-                       spi_xfer->len = 1;
-                       spi_message_init(&m);
-                       spi_message_add_tail(spi_xfer, &m);
-                       ret = spi_sync_locked(phy->spi_device, &m);
-                       if (ret < 0)
-                               return ret;
-                       if (phy->iobuf[0] & 0x01)
-                               break;
-               }
-
-               if (i == TPM_RETRY)
-                       return -ETIMEDOUT;
-       }
-
-       return 0;
-}
-
-int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
-                        u8 *in, const u8 *out)
-{
-       struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
-       int ret = 0;
-       struct spi_message m;
-       struct spi_transfer spi_xfer;
-       u8 transfer_len;
-
-       spi_bus_lock(phy->spi_device->master);
-
-       while (len) {
-               transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
-
-               phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
-               phy->iobuf[1] = 0xd4;
-               phy->iobuf[2] = addr >> 8;
-               phy->iobuf[3] = addr;
-
-               memset(&spi_xfer, 0, sizeof(spi_xfer));
-               spi_xfer.tx_buf = phy->iobuf;
-               spi_xfer.rx_buf = phy->iobuf;
-               spi_xfer.len = 4;
-               spi_xfer.cs_change = 1;
-
-               spi_message_init(&m);
-               spi_message_add_tail(&spi_xfer, &m);
-               ret = spi_sync_locked(phy->spi_device, &m);
-               if (ret < 0)
-                       goto exit;
-
-               ret = phy->flow_control(phy, &spi_xfer);
-               if (ret < 0)
-                       goto exit;
-
-               spi_xfer.cs_change = 0;
-               spi_xfer.len = transfer_len;
-               spi_xfer.delay_usecs = 5;
-
-               if (in) {
-                       spi_xfer.tx_buf = NULL;
-               } else if (out) {
-                       spi_xfer.rx_buf = NULL;
-                       memcpy(phy->iobuf, out, transfer_len);
-                       out += transfer_len;
-               }
-
-               spi_message_init(&m);
-               spi_message_add_tail(&spi_xfer, &m);
-               reinit_completion(&phy->ready);
-               ret = spi_sync_locked(phy->spi_device, &m);
-               if (ret < 0)
-                       goto exit;
-
-               if (in) {
-                       memcpy(in, phy->iobuf, transfer_len);
-                       in += transfer_len;
-               }
-
-               len -= transfer_len;
-       }
-
-exit:
-       spi_bus_unlock(phy->spi_device->master);
-       return ret;
-}
-
-static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
-                                 u16 len, u8 *result)
-{
-       return tpm_tis_spi_transfer(data, addr, len, result, NULL);
-}
-
-static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr,
-                                  u16 len, const u8 *value)
-{
-       return tpm_tis_spi_transfer(data, addr, len, NULL, value);
-}
-
-int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result)
-{
-       __le16 result_le;
-       int rc;
-
-       rc = data->phy_ops->read_bytes(data, addr, sizeof(u16),
-                                      (u8 *)&result_le);
-       if (!rc)
-               *result = le16_to_cpu(result_le);
-
-       return rc;
-}
-
-int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result)
-{
-       __le32 result_le;
-       int rc;
-
-       rc = data->phy_ops->read_bytes(data, addr, sizeof(u32),
-                                      (u8 *)&result_le);
-       if (!rc)
-               *result = le32_to_cpu(result_le);
-
-       return rc;
-}
-
-int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value)
-{
-       __le32 value_le;
-       int rc;
-
-       value_le = cpu_to_le32(value);
-       rc = data->phy_ops->write_bytes(data, addr, sizeof(u32),
-                                       (u8 *)&value_le);
-
-       return rc;
-}
-
-int tpm_tis_spi_init(struct spi_device *spi, struct tpm_tis_spi_phy *phy,
-                    int irq, const struct tpm_tis_phy_ops *phy_ops)
-{
-       phy->iobuf = devm_kmalloc(&spi->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
-       if (!phy->iobuf)
-               return -ENOMEM;
-
-       phy->spi_device = spi;
-
-       return tpm_tis_core_init(&spi->dev, &phy->priv, irq, phy_ops, NULL);
-}
-
-static const struct tpm_tis_phy_ops tpm_spi_phy_ops = {
-       .read_bytes = tpm_tis_spi_read_bytes,
-       .write_bytes = tpm_tis_spi_write_bytes,
-       .read16 = tpm_tis_spi_read16,
-       .read32 = tpm_tis_spi_read32,
-       .write32 = tpm_tis_spi_write32,
-};
-
-static int tpm_tis_spi_probe(struct spi_device *dev)
-{
-       struct tpm_tis_spi_phy *phy;
-       int irq;
-
-       phy = devm_kzalloc(&dev->dev, sizeof(struct tpm_tis_spi_phy),
-                          GFP_KERNEL);
-       if (!phy)
-               return -ENOMEM;
-
-       phy->flow_control = tpm_tis_spi_flow_control;
-
-       /* If the SPI device has an IRQ then use that */
-       if (dev->irq > 0)
-               irq = dev->irq;
-       else
-               irq = -1;
-
-       init_completion(&phy->ready);
-       return tpm_tis_spi_init(dev, phy, irq, &tpm_spi_phy_ops);
-}
-
-typedef int (*tpm_tis_spi_probe_func)(struct spi_device *);
-
-static int tpm_tis_spi_driver_probe(struct spi_device *spi)
-{
-       const struct spi_device_id *spi_dev_id = spi_get_device_id(spi);
-       tpm_tis_spi_probe_func probe_func;
-
-       probe_func = of_device_get_match_data(&spi->dev);
-       if (!probe_func && spi_dev_id)
-               probe_func = (tpm_tis_spi_probe_func)spi_dev_id->driver_data;
-       if (!probe_func)
-               return -ENODEV;
-
-       return probe_func(spi);
-}
-
-static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_spi_resume);
-
-static int tpm_tis_spi_remove(struct spi_device *dev)
-{
-       struct tpm_chip *chip = spi_get_drvdata(dev);
-
-       tpm_chip_unregister(chip);
-       tpm_tis_remove(chip);
-       return 0;
-}
-
-static const struct spi_device_id tpm_tis_spi_id[] = {
-       { "tpm_tis_spi", (unsigned long)tpm_tis_spi_probe },
-       { "cr50", (unsigned long)cr50_spi_probe },
-       {}
-};
-MODULE_DEVICE_TABLE(spi, tpm_tis_spi_id);
-
-static const struct of_device_id of_tis_spi_match[] = {
-       { .compatible = "st,st33htpm-spi", .data = tpm_tis_spi_probe },
-       { .compatible = "infineon,slb9670", .data = tpm_tis_spi_probe },
-       { .compatible = "tcg,tpm_tis-spi", .data = tpm_tis_spi_probe },
-       { .compatible = "google,cr50", .data = cr50_spi_probe },
-       {}
-};
-MODULE_DEVICE_TABLE(of, of_tis_spi_match);
-
-static const struct acpi_device_id acpi_tis_spi_match[] = {
-       {"SMO0768", 0},
-       {}
-};
-MODULE_DEVICE_TABLE(acpi, acpi_tis_spi_match);
-
-static struct spi_driver tpm_tis_spi_driver = {
-       .driver = {
-               .name = "tpm_tis_spi",
-               .pm = &tpm_tis_pm,
-               .of_match_table = of_match_ptr(of_tis_spi_match),
-               .acpi_match_table = ACPI_PTR(acpi_tis_spi_match),
-       },
-       .probe = tpm_tis_spi_driver_probe,
-       .remove = tpm_tis_spi_remove,
-       .id_table = tpm_tis_spi_id,
-};
-module_spi_driver(tpm_tis_spi_driver);
-
-MODULE_DESCRIPTION("TPM Driver for native SPI access");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c
new file mode 100644 (file)
index 0000000..d1754fd
--- /dev/null
@@ -0,0 +1,298 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2015 Infineon Technologies AG
+ * Copyright (C) 2016 STMicroelectronics SAS
+ *
+ * Authors:
+ * Peter Huewe <peter.huewe@infineon.com>
+ * Christophe Ricard <christophe-h.ricard@st.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.3, revision 27 via _raw/native
+ * SPI access_.
+ *
+ * It is based on the original tpm_tis device driver from Leendert van
+ * Dorn and Kyleen Hall and Jarko Sakkinnen.
+ */
+
+#include <linux/acpi.h>
+#include <linux/completion.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/of_device.h>
+#include <linux/spi/spi.h>
+#include <linux/tpm.h>
+
+#include "tpm.h"
+#include "tpm_tis_core.h"
+#include "tpm_tis_spi.h"
+
+#define MAX_SPI_FRAMESIZE 64
+
+/*
+ * TCG SPI flow control is documented in section 6.4 of the spec[1]. In short,
+ * keep trying to read from the device until MISO goes high indicating the
+ * wait state has ended.
+ *
+ * [1] https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
+ */
+static int tpm_tis_spi_flow_control(struct tpm_tis_spi_phy *phy,
+                                   struct spi_transfer *spi_xfer)
+{
+       struct spi_message m;
+       int ret, i;
+
+       if ((phy->iobuf[3] & 0x01) == 0) {
+               // handle SPI wait states
+               phy->iobuf[0] = 0;
+
+               for (i = 0; i < TPM_RETRY; i++) {
+                       spi_xfer->len = 1;
+                       spi_message_init(&m);
+                       spi_message_add_tail(spi_xfer, &m);
+                       ret = spi_sync_locked(phy->spi_device, &m);
+                       if (ret < 0)
+                               return ret;
+                       if (phy->iobuf[0] & 0x01)
+                               break;
+               }
+
+               if (i == TPM_RETRY)
+                       return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
+                        u8 *in, const u8 *out)
+{
+       struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
+       int ret = 0;
+       struct spi_message m;
+       struct spi_transfer spi_xfer;
+       u8 transfer_len;
+
+       spi_bus_lock(phy->spi_device->master);
+
+       while (len) {
+               transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE);
+
+               phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1);
+               phy->iobuf[1] = 0xd4;
+               phy->iobuf[2] = addr >> 8;
+               phy->iobuf[3] = addr;
+
+               memset(&spi_xfer, 0, sizeof(spi_xfer));
+               spi_xfer.tx_buf = phy->iobuf;
+               spi_xfer.rx_buf = phy->iobuf;
+               spi_xfer.len = 4;
+               spi_xfer.cs_change = 1;
+
+               spi_message_init(&m);
+               spi_message_add_tail(&spi_xfer, &m);
+               ret = spi_sync_locked(phy->spi_device, &m);
+               if (ret < 0)
+                       goto exit;
+
+               ret = phy->flow_control(phy, &spi_xfer);
+               if (ret < 0)
+                       goto exit;
+
+               spi_xfer.cs_change = 0;
+               spi_xfer.len = transfer_len;
+               spi_xfer.delay_usecs = 5;
+
+               if (in) {
+                       spi_xfer.tx_buf = NULL;
+               } else if (out) {
+                       spi_xfer.rx_buf = NULL;
+                       memcpy(phy->iobuf, out, transfer_len);
+                       out += transfer_len;
+               }
+
+               spi_message_init(&m);
+               spi_message_add_tail(&spi_xfer, &m);
+               reinit_completion(&phy->ready);
+               ret = spi_sync_locked(phy->spi_device, &m);
+               if (ret < 0)
+                       goto exit;
+
+               if (in) {
+                       memcpy(in, phy->iobuf, transfer_len);
+                       in += transfer_len;
+               }
+
+               len -= transfer_len;
+       }
+
+exit:
+       spi_bus_unlock(phy->spi_device->master);
+       return ret;
+}
+
+static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
+                                 u16 len, u8 *result)
+{
+       return tpm_tis_spi_transfer(data, addr, len, result, NULL);
+}
+
+static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr,
+                                  u16 len, const u8 *value)
+{
+       return tpm_tis_spi_transfer(data, addr, len, NULL, value);
+}
+
+int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result)
+{
+       __le16 result_le;
+       int rc;
+
+       rc = data->phy_ops->read_bytes(data, addr, sizeof(u16),
+                                      (u8 *)&result_le);
+       if (!rc)
+               *result = le16_to_cpu(result_le);
+
+       return rc;
+}
+
+int tpm_tis_spi_read32(struct tpm_tis_data *data, u32 addr, u32 *result)
+{
+       __le32 result_le;
+       int rc;
+
+       rc = data->phy_ops->read_bytes(data, addr, sizeof(u32),
+                                      (u8 *)&result_le);
+       if (!rc)
+               *result = le32_to_cpu(result_le);
+
+       return rc;
+}
+
+int tpm_tis_spi_write32(struct tpm_tis_data *data, u32 addr, u32 value)
+{
+       __le32 value_le;
+       int rc;
+
+       value_le = cpu_to_le32(value);
+       rc = data->phy_ops->write_bytes(data, addr, sizeof(u32),
+                                       (u8 *)&value_le);
+
+       return rc;
+}
+
+int tpm_tis_spi_init(struct spi_device *spi, struct tpm_tis_spi_phy *phy,
+                    int irq, const struct tpm_tis_phy_ops *phy_ops)
+{
+       phy->iobuf = devm_kmalloc(&spi->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL);
+       if (!phy->iobuf)
+               return -ENOMEM;
+
+       phy->spi_device = spi;
+
+       return tpm_tis_core_init(&spi->dev, &phy->priv, irq, phy_ops, NULL);
+}
+
+static const struct tpm_tis_phy_ops tpm_spi_phy_ops = {
+       .read_bytes = tpm_tis_spi_read_bytes,
+       .write_bytes = tpm_tis_spi_write_bytes,
+       .read16 = tpm_tis_spi_read16,
+       .read32 = tpm_tis_spi_read32,
+       .write32 = tpm_tis_spi_write32,
+};
+
+static int tpm_tis_spi_probe(struct spi_device *dev)
+{
+       struct tpm_tis_spi_phy *phy;
+       int irq;
+
+       phy = devm_kzalloc(&dev->dev, sizeof(struct tpm_tis_spi_phy),
+                          GFP_KERNEL);
+       if (!phy)
+               return -ENOMEM;
+
+       phy->flow_control = tpm_tis_spi_flow_control;
+
+       /* If the SPI device has an IRQ then use that */
+       if (dev->irq > 0)
+               irq = dev->irq;
+       else
+               irq = -1;
+
+       init_completion(&phy->ready);
+       return tpm_tis_spi_init(dev, phy, irq, &tpm_spi_phy_ops);
+}
+
+typedef int (*tpm_tis_spi_probe_func)(struct spi_device *);
+
+static int tpm_tis_spi_driver_probe(struct spi_device *spi)
+{
+       const struct spi_device_id *spi_dev_id = spi_get_device_id(spi);
+       tpm_tis_spi_probe_func probe_func;
+
+       probe_func = of_device_get_match_data(&spi->dev);
+       if (!probe_func && spi_dev_id)
+               probe_func = (tpm_tis_spi_probe_func)spi_dev_id->driver_data;
+       if (!probe_func)
+               return -ENODEV;
+
+       return probe_func(spi);
+}
+
+static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_spi_resume);
+
+static int tpm_tis_spi_remove(struct spi_device *dev)
+{
+       struct tpm_chip *chip = spi_get_drvdata(dev);
+
+       tpm_chip_unregister(chip);
+       tpm_tis_remove(chip);
+       return 0;
+}
+
+static const struct spi_device_id tpm_tis_spi_id[] = {
+       { "tpm_tis_spi", (unsigned long)tpm_tis_spi_probe },
+       { "cr50", (unsigned long)cr50_spi_probe },
+       {}
+};
+MODULE_DEVICE_TABLE(spi, tpm_tis_spi_id);
+
+static const struct of_device_id of_tis_spi_match[] = {
+       { .compatible = "st,st33htpm-spi", .data = tpm_tis_spi_probe },
+       { .compatible = "infineon,slb9670", .data = tpm_tis_spi_probe },
+       { .compatible = "tcg,tpm_tis-spi", .data = tpm_tis_spi_probe },
+       { .compatible = "google,cr50", .data = cr50_spi_probe },
+       {}
+};
+MODULE_DEVICE_TABLE(of, of_tis_spi_match);
+
+static const struct acpi_device_id acpi_tis_spi_match[] = {
+       {"SMO0768", 0},
+       {}
+};
+MODULE_DEVICE_TABLE(acpi, acpi_tis_spi_match);
+
+static struct spi_driver tpm_tis_spi_driver = {
+       .driver = {
+               .name = "tpm_tis_spi",
+               .pm = &tpm_tis_pm,
+               .of_match_table = of_match_ptr(of_tis_spi_match),
+               .acpi_match_table = ACPI_PTR(acpi_tis_spi_match),
+       },
+       .probe = tpm_tis_spi_driver_probe,
+       .remove = tpm_tis_spi_remove,
+       .id_table = tpm_tis_spi_id,
+};
+module_spi_driver(tpm_tis_spi_driver);
+
+MODULE_DESCRIPTION("TPM Driver for native SPI access");
+MODULE_LICENSE("GPL");
index 92ce6d8..4cc0e63 100644 (file)
@@ -55,6 +55,7 @@ config FSI_MASTER_AST_CF
 
 config FSI_MASTER_ASPEED
        tristate "FSI ASPEED master"
+       depends on HAS_IOMEM
        help
         This option enables a FSI master that is present behind an OPB bridge
         in the AST2600.
index 3a1570d..146f966 100644 (file)
@@ -1013,6 +1013,30 @@ static int psp_dtm_initialize(struct psp_context *psp)
        return 0;
 }
 
+static int psp_dtm_unload(struct psp_context *psp)
+{
+       int ret;
+       struct psp_gfx_cmd_resp *cmd;
+
+       /*
+        * TODO: bypass the unloading in sriov for now
+        */
+       if (amdgpu_sriov_vf(psp->adev))
+               return 0;
+
+       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       psp_prep_ta_unload_cmd_buf(cmd, psp->dtm_context.session_id);
+
+       ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+
+       kfree(cmd);
+
+       return ret;
+}
+
 int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
 {
        /*
@@ -1037,7 +1061,7 @@ static int psp_dtm_terminate(struct psp_context *psp)
        if (!psp->dtm_context.dtm_initialized)
                return 0;
 
-       ret = psp_hdcp_unload(psp);
+       ret = psp_dtm_unload(psp);
        if (ret)
                return ret;
 
index 1785fda..22bbb36 100644 (file)
@@ -3923,11 +3923,13 @@ static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev)
 {
        uint64_t clock;
 
+       amdgpu_gfx_off_ctrl(adev, false);
        mutex_lock(&adev->gfx.gpu_clock_mutex);
        WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
        clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) |
                ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
        mutex_unlock(&adev->gfx.gpu_clock_mutex);
+       amdgpu_gfx_off_ctrl(adev, true);
        return clock;
 }
 
index b33a4eb..3afdbbd 100644 (file)
@@ -1193,6 +1193,14 @@ static bool gfx_v9_0_should_disable_gfxoff(struct pci_dev *pdev)
        return false;
 }
 
+static bool is_raven_kicker(struct amdgpu_device *adev)
+{
+       if (adev->pm.fw_version >= 0x41e2b)
+               return true;
+       else
+               return false;
+}
+
 static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
 {
        if (gfx_v9_0_should_disable_gfxoff(adev->pdev))
@@ -1205,9 +1213,8 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
                break;
        case CHIP_RAVEN:
                if (!(adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8) &&
-                   ((adev->gfx.rlc_fw_version != 106 &&
+                   ((!is_raven_kicker(adev) &&
                      adev->gfx.rlc_fw_version < 531) ||
-                    (adev->gfx.rlc_fw_version == 53815) ||
                     (adev->gfx.rlc_feature_version < 1) ||
                     !adev->gfx.rlc.is_rlc_v2_1))
                        adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
@@ -3959,6 +3966,7 @@ static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev)
 {
        uint64_t clock;
 
+       amdgpu_gfx_off_ctrl(adev, false);
        mutex_lock(&adev->gfx.gpu_clock_mutex);
        if (adev->asic_type == CHIP_VEGA10 && amdgpu_sriov_runtime(adev)) {
                uint32_t tmp, lsb, msb, i = 0;
@@ -3977,6 +3985,7 @@ static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev)
                        ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
        }
        mutex_unlock(&adev->gfx.gpu_clock_mutex);
+       amdgpu_gfx_off_ctrl(adev, true);
        return clock;
 }
 
index 15f3424..2b488df 100644 (file)
@@ -272,7 +272,12 @@ static u32 soc15_get_config_memsize(struct amdgpu_device *adev)
 
 static u32 soc15_get_xclk(struct amdgpu_device *adev)
 {
-       return adev->clock.spll.reference_freq;
+       u32 reference_clock = adev->clock.spll.reference_freq;
+
+       if (adev->asic_type == CHIP_RAVEN)
+               return reference_clock / 4;
+
+       return reference_clock;
 }
 
 
index 63e8a12..e8f66fb 100644 (file)
@@ -1911,7 +1911,7 @@ static void handle_hpd_irq(void *param)
        mutex_lock(&aconnector->hpd_lock);
 
 #ifdef CONFIG_DRM_AMD_DC_HDCP
-       if (adev->asic_type >= CHIP_RAVEN)
+       if (adev->dm.hdcp_workqueue)
                hdcp_reset_display(adev->dm.hdcp_workqueue, aconnector->dc_link->link_index);
 #endif
        if (aconnector->fake_enable)
@@ -2088,8 +2088,10 @@ static void handle_hpd_rx_irq(void *param)
                }
        }
 #ifdef CONFIG_DRM_AMD_DC_HDCP
-       if (hpd_irq_data.bytes.device_service_irq.bits.CP_IRQ)
-               hdcp_handle_cpirq(adev->dm.hdcp_workqueue,  aconnector->base.index);
+           if (hpd_irq_data.bytes.device_service_irq.bits.CP_IRQ) {
+                   if (adev->dm.hdcp_workqueue)
+                           hdcp_handle_cpirq(adev->dm.hdcp_workqueue,  aconnector->base.index);
+           }
 #endif
        if ((dc_link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
            (dc_link->type == dc_connection_mst_branch))
@@ -5702,7 +5704,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
                drm_connector_attach_vrr_capable_property(
                        &aconnector->base);
 #ifdef CONFIG_DRM_AMD_DC_HDCP
-               if (adev->asic_type >= CHIP_RAVEN)
+               if (adev->dm.hdcp_workqueue)
                        drm_connector_attach_content_protection_property(&aconnector->base, true);
 #endif
        }
index f730b94..5524671 100644 (file)
@@ -46,8 +46,8 @@ static inline enum mod_hdcp_status check_hdcp2_capable(struct mod_hdcp *hdcp)
        enum mod_hdcp_status status;
 
        if (is_dp_hdcp(hdcp))
-               status = (hdcp->auth.msg.hdcp2.rxcaps_dp[2] & HDCP_2_2_RX_CAPS_VERSION_VAL) &&
-                               HDCP_2_2_DP_HDCP_CAPABLE(hdcp->auth.msg.hdcp2.rxcaps_dp[0]) ?
+               status = (hdcp->auth.msg.hdcp2.rxcaps_dp[0] == HDCP_2_2_RX_CAPS_VERSION_VAL) &&
+                               HDCP_2_2_DP_HDCP_CAPABLE(hdcp->auth.msg.hdcp2.rxcaps_dp[2]) ?
                                MOD_HDCP_STATUS_SUCCESS :
                                MOD_HDCP_STATUS_HDCP2_NOT_CAPABLE;
        else
index 0dc4947..b06c057 100644 (file)
@@ -898,6 +898,9 @@ int smu_v11_0_system_features_control(struct smu_context *smu,
        if (ret)
                return ret;
 
+       bitmap_zero(feature->enabled, feature->feature_num);
+       bitmap_zero(feature->supported, feature->feature_num);
+
        if (en) {
                ret = smu_feature_get_enabled_mask(smu, feature_mask, 2);
                if (ret)
@@ -907,9 +910,6 @@ int smu_v11_0_system_features_control(struct smu_context *smu,
                            feature->feature_num);
                bitmap_copy(feature->supported, (unsigned long *)&feature_mask,
                            feature->feature_num);
-       } else {
-               bitmap_zero(feature->enabled, feature->feature_num);
-               bitmap_zero(feature->supported, feature->feature_num);
        }
 
        return ret;
index 3709e5a..fbdb42d 100644 (file)
@@ -297,7 +297,7 @@ static inline int tc_poll_timeout(struct tc_data *tc, unsigned int addr,
 
 static int tc_aux_wait_busy(struct tc_data *tc)
 {
-       return tc_poll_timeout(tc, DP0_AUXSTATUS, AUX_BUSY, 0, 1000, 100000);
+       return tc_poll_timeout(tc, DP0_AUXSTATUS, AUX_BUSY, 0, 100, 100000);
 }
 
 static int tc_aux_write_data(struct tc_data *tc, const void *data,
@@ -640,7 +640,7 @@ static int tc_aux_link_setup(struct tc_data *tc)
        if (ret)
                goto err;
 
-       ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000);
+       ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 100, 100000);
        if (ret == -ETIMEDOUT) {
                dev_err(tc->dev, "Timeout waiting for PHY to become ready");
                return ret;
@@ -876,7 +876,7 @@ static int tc_wait_link_training(struct tc_data *tc)
        int ret;
 
        ret = tc_poll_timeout(tc, DP0_LTSTAT, LT_LOOPDONE,
-                             LT_LOOPDONE, 1, 1000);
+                             LT_LOOPDONE, 500, 100000);
        if (ret) {
                dev_err(tc->dev, "Link training timeout waiting for LT_LOOPDONE!\n");
                return ret;
@@ -949,7 +949,7 @@ static int tc_main_link_enable(struct tc_data *tc)
        dp_phy_ctrl &= ~(DP_PHY_RST | PHY_M1_RST | PHY_M0_RST);
        ret = regmap_write(tc->regmap, DP_PHY_CTRL, dp_phy_ctrl);
 
-       ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000);
+       ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 500, 100000);
        if (ret) {
                dev_err(dev, "timeout waiting for phy become ready");
                return ret;
index 6f6d6d1..f195a47 100644 (file)
@@ -140,7 +140,8 @@ static int tfp410_attach(struct drm_bridge *bridge)
                                          dvi->connector_type,
                                          dvi->ddc);
        if (ret) {
-               dev_err(dvi->dev, "drm_connector_init() failed: %d\n", ret);
+               dev_err(dvi->dev, "drm_connector_init_with_ddc() failed: %d\n",
+                       ret);
                return ret;
        }
 
index 6d4a29e..3035584 100644 (file)
@@ -951,7 +951,8 @@ bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation)
         * depending on the hardware this may require the framebuffer
         * to be in a specific tiling format.
         */
-       if ((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180 ||
+       if (((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0 &&
+            (*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180) ||
            !plane->rotation_property)
                return false;
 
index 10336b1..d4d6451 100644 (file)
@@ -1698,6 +1698,13 @@ static int drm_mode_parse_cmdline_options(const char *str,
        if (rotation && freestanding)
                return -EINVAL;
 
+       if (!(rotation & DRM_MODE_ROTATE_MASK))
+               rotation |= DRM_MODE_ROTATE_0;
+
+       /* Make sure there is exactly one rotation defined */
+       if (!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK))
+               return -EINVAL;
+
        mode->rotation_reflection = rotation;
 
        return 0;
index ba95959..907c447 100644 (file)
@@ -75,9 +75,8 @@ config DRM_I915_CAPTURE_ERROR
        help
          This option enables capturing the GPU state when a hang is detected.
          This information is vital for triaging hangs and assists in debugging.
-         Please report any hang to
-           https://bugs.freedesktop.org/enter_bug.cgi?product=DRI
-         for triaging.
+         Please report any hang for triaging according to:
+           https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs
 
          If in doubt, say "Y".
 
index 33f1dc3..d9a61f3 100644 (file)
@@ -4251,7 +4251,9 @@ static bool intel_ddi_is_audio_enabled(struct drm_i915_private *dev_priv,
 void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv,
                                         struct intel_crtc_state *crtc_state)
 {
-       if (INTEL_GEN(dev_priv) >= 11 && crtc_state->port_clock > 594000)
+       if (IS_ELKHARTLAKE(dev_priv) && crtc_state->port_clock > 594000)
+               crtc_state->min_voltage_level = 3;
+       else if (INTEL_GEN(dev_priv) >= 11 && crtc_state->port_clock > 594000)
                crtc_state->min_voltage_level = 1;
        else if (IS_CANNONLAKE(dev_priv) && crtc_state->port_clock > 594000)
                crtc_state->min_voltage_level = 2;
index 064dd99..aa45395 100644 (file)
@@ -11087,7 +11087,7 @@ static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
        u32 base;
 
        if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
-               base = obj->phys_handle->busaddr;
+               base = sg_dma_address(obj->mm.pages->sgl);
        else
                base = intel_plane_ggtt_offset(plane_state);
 
@@ -17433,6 +17433,24 @@ retry:
                         * have readout for pipe gamma enable.
                         */
                        crtc_state->uapi.color_mgmt_changed = true;
+
+                       /*
+                        * FIXME hack to force full modeset when DSC is being
+                        * used.
+                        *
+                        * As long as we do not have full state readout and
+                        * config comparison of crtc_state->dsc, we have no way
+                        * to ensure reliable fastset. Remove once we have
+                        * readout for DSC.
+                        */
+                       if (crtc_state->dsc.compression_enable) {
+                               ret = drm_atomic_add_affected_connectors(state,
+                                                                        &crtc->base);
+                               if (ret)
+                                       goto out;
+                               crtc_state->uapi.mode_changed = true;
+                               drm_dbg_kms(dev, "Force full modeset for DSC\n");
+                       }
                }
        }
 
index a2e57e6..151a1e8 100644 (file)
@@ -565,6 +565,22 @@ static int __context_set_persistence(struct i915_gem_context *ctx, bool state)
                if (!(ctx->i915->caps.scheduler & I915_SCHEDULER_CAP_PREEMPTION))
                        return -ENODEV;
 
+               /*
+                * If the cancel fails, we then need to reset, cleanly!
+                *
+                * If the per-engine reset fails, all hope is lost! We resort
+                * to a full GPU reset in that unlikely case, but realistically
+                * if the engine could not reset, the full reset does not fare
+                * much better. The damage has been done.
+                *
+                * However, if we cannot reset an engine by itself, we cannot
+                * cleanup a hanging persistent context without causing
+                * colateral damage, and we should not pretend we can by
+                * exposing the interface.
+                */
+               if (!intel_has_reset_engine(&ctx->i915->gt))
+                       return -ENODEV;
+
                i915_gem_context_clear_persistence(ctx);
        }
 
index f64ad77..c2174da 100644 (file)
@@ -285,9 +285,6 @@ struct drm_i915_gem_object {
 
                void *gvt_info;
        };
-
-       /** for phys allocated objects */
-       struct drm_dma_handle *phys_handle;
 };
 
 static inline struct drm_i915_gem_object *
index b1b7c1b..b07bb40 100644 (file)
 static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 {
        struct address_space *mapping = obj->base.filp->f_mapping;
-       struct drm_dma_handle *phys;
-       struct sg_table *st;
        struct scatterlist *sg;
-       char *vaddr;
+       struct sg_table *st;
+       dma_addr_t dma;
+       void *vaddr;
+       void *dst;
        int i;
-       int err;
 
        if (WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
                return -EINVAL;
 
-       /* Always aligning to the object size, allows a single allocation
+       /*
+        * Always aligning to the object size, allows a single allocation
         * to handle all possible callers, and given typical object sizes,
         * the alignment of the buddy allocation will naturally match.
         */
-       phys = drm_pci_alloc(obj->base.dev,
-                            roundup_pow_of_two(obj->base.size),
-                            roundup_pow_of_two(obj->base.size));
-       if (!phys)
+       vaddr = dma_alloc_coherent(&obj->base.dev->pdev->dev,
+                                  roundup_pow_of_two(obj->base.size),
+                                  &dma, GFP_KERNEL);
+       if (!vaddr)
                return -ENOMEM;
 
-       vaddr = phys->vaddr;
+       st = kmalloc(sizeof(*st), GFP_KERNEL);
+       if (!st)
+               goto err_pci;
+
+       if (sg_alloc_table(st, 1, GFP_KERNEL))
+               goto err_st;
+
+       sg = st->sgl;
+       sg->offset = 0;
+       sg->length = obj->base.size;
+
+       sg_assign_page(sg, (struct page *)vaddr);
+       sg_dma_address(sg) = dma;
+       sg_dma_len(sg) = obj->base.size;
+
+       dst = vaddr;
        for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
                struct page *page;
-               char *src;
+               void *src;
 
                page = shmem_read_mapping_page(mapping, i);
-               if (IS_ERR(page)) {
-                       err = PTR_ERR(page);
-                       goto err_phys;
-               }
+               if (IS_ERR(page))
+                       goto err_st;
 
                src = kmap_atomic(page);
-               memcpy(vaddr, src, PAGE_SIZE);
-               drm_clflush_virt_range(vaddr, PAGE_SIZE);
+               memcpy(dst, src, PAGE_SIZE);
+               drm_clflush_virt_range(dst, PAGE_SIZE);
                kunmap_atomic(src);
 
                put_page(page);
-               vaddr += PAGE_SIZE;
+               dst += PAGE_SIZE;
        }
 
        intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
 
-       st = kmalloc(sizeof(*st), GFP_KERNEL);
-       if (!st) {
-               err = -ENOMEM;
-               goto err_phys;
-       }
-
-       if (sg_alloc_table(st, 1, GFP_KERNEL)) {
-               kfree(st);
-               err = -ENOMEM;
-               goto err_phys;
-       }
-
-       sg = st->sgl;
-       sg->offset = 0;
-       sg->length = obj->base.size;
-
-       sg_dma_address(sg) = phys->busaddr;
-       sg_dma_len(sg) = obj->base.size;
-
-       obj->phys_handle = phys;
-
        __i915_gem_object_set_pages(obj, st, sg->length);
 
        return 0;
 
-err_phys:
-       drm_pci_free(obj->base.dev, phys);
-
-       return err;
+err_st:
+       kfree(st);
+err_pci:
+       dma_free_coherent(&obj->base.dev->pdev->dev,
+                         roundup_pow_of_two(obj->base.size),
+                         vaddr, dma);
+       return -ENOMEM;
 }
 
 static void
 i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
                               struct sg_table *pages)
 {
+       dma_addr_t dma = sg_dma_address(pages->sgl);
+       void *vaddr = sg_page(pages->sgl);
+
        __i915_gem_object_release_shmem(obj, pages, false);
 
        if (obj->mm.dirty) {
                struct address_space *mapping = obj->base.filp->f_mapping;
-               char *vaddr = obj->phys_handle->vaddr;
+               void *src = vaddr;
                int i;
 
                for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
@@ -115,15 +114,16 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
                                continue;
 
                        dst = kmap_atomic(page);
-                       drm_clflush_virt_range(vaddr, PAGE_SIZE);
-                       memcpy(dst, vaddr, PAGE_SIZE);
+                       drm_clflush_virt_range(src, PAGE_SIZE);
+                       memcpy(dst, src, PAGE_SIZE);
                        kunmap_atomic(dst);
 
                        set_page_dirty(page);
                        if (obj->mm.madv == I915_MADV_WILLNEED)
                                mark_page_accessed(page);
                        put_page(page);
-                       vaddr += PAGE_SIZE;
+
+                       src += PAGE_SIZE;
                }
                obj->mm.dirty = false;
        }
@@ -131,7 +131,9 @@ i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
        sg_free_table(pages);
        kfree(pages);
 
-       drm_pci_free(obj->base.dev, obj->phys_handle);
+       dma_free_coherent(&obj->base.dev->pdev->dev,
+                         roundup_pow_of_two(obj->base.size),
+                         vaddr, dma);
 }
 
 static void phys_release(struct drm_i915_gem_object *obj)
index 0ba524a..cbad7fe 100644 (file)
@@ -136,6 +136,9 @@ static void add_retire(struct intel_breadcrumbs *b, struct intel_timeline *tl)
        struct intel_engine_cs *engine =
                container_of(b, struct intel_engine_cs, breadcrumbs);
 
+       if (unlikely(intel_engine_is_virtual(engine)))
+               engine = intel_virtual_engine_get_sibling(engine, 0);
+
        intel_engine_add_retire(engine, tl);
 }
 
index 7ef1d37..8a5054f 100644 (file)
@@ -99,6 +99,9 @@ static bool add_retire(struct intel_engine_cs *engine,
 void intel_engine_add_retire(struct intel_engine_cs *engine,
                             struct intel_timeline *tl)
 {
+       /* We don't deal well with the engine disappearing beneath us */
+       GEM_BUG_ON(intel_engine_is_virtual(engine));
+
        if (add_retire(engine, tl))
                schedule_work(&engine->retire_work);
 }
index a13a8c4..fe8a59a 100644 (file)
@@ -237,7 +237,8 @@ static void execlists_init_reg_state(u32 *reg_state,
                                     bool close);
 static void
 __execlists_update_reg_state(const struct intel_context *ce,
-                            const struct intel_engine_cs *engine);
+                            const struct intel_engine_cs *engine,
+                            u32 head);
 
 static void mark_eio(struct i915_request *rq)
 {
@@ -1186,12 +1187,11 @@ static void reset_active(struct i915_request *rq,
                head = rq->tail;
        else
                head = active_request(ce->timeline, rq)->head;
-       ce->ring->head = intel_ring_wrap(ce->ring, head);
-       intel_ring_update_space(ce->ring);
+       head = intel_ring_wrap(ce->ring, head);
 
        /* Scrub the context image to prevent replaying the previous batch */
        restore_default_state(ce, engine);
-       __execlists_update_reg_state(ce, engine);
+       __execlists_update_reg_state(ce, engine, head);
 
        /* We've switched away, so this should be a no-op, but intent matters */
        ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
@@ -1321,7 +1321,7 @@ static u64 execlists_update_context(struct i915_request *rq)
 {
        struct intel_context *ce = rq->context;
        u64 desc = ce->lrc_desc;
-       u32 tail;
+       u32 tail, prev;
 
        /*
         * WaIdleLiteRestore:bdw,skl
@@ -1334,9 +1334,15 @@ static u64 execlists_update_context(struct i915_request *rq)
         * subsequent resubmissions (for lite restore). Should that fail us,
         * and we try and submit the same tail again, force the context
         * reload.
+        *
+        * If we need to return to a preempted context, we need to skip the
+        * lite-restore and force it to reload the RING_TAIL. Otherwise, the
+        * HW has a tendency to ignore us rewinding the TAIL to the end of
+        * an earlier request.
         */
        tail = intel_ring_set_tail(rq->ring, rq->tail);
-       if (unlikely(ce->lrc_reg_state[CTX_RING_TAIL] == tail))
+       prev = ce->lrc_reg_state[CTX_RING_TAIL];
+       if (unlikely(intel_ring_direction(rq->ring, tail, prev) <= 0))
                desc |= CTX_DESC_FORCE_RESTORE;
        ce->lrc_reg_state[CTX_RING_TAIL] = tail;
        rq->tail = rq->wa_tail;
@@ -1605,6 +1611,11 @@ last_active(const struct intel_engine_execlists *execlists)
        return *last;
 }
 
+#define for_each_waiter(p__, rq__) \
+       list_for_each_entry_lockless(p__, \
+                                    &(rq__)->sched.waiters_list, \
+                                    wait_link)
+
 static void defer_request(struct i915_request *rq, struct list_head * const pl)
 {
        LIST_HEAD(list);
@@ -1622,7 +1633,7 @@ static void defer_request(struct i915_request *rq, struct list_head * const pl)
                GEM_BUG_ON(i915_request_is_active(rq));
                list_move_tail(&rq->sched.link, pl);
 
-               list_for_each_entry(p, &rq->sched.waiters_list, wait_link) {
+               for_each_waiter(p, rq) {
                        struct i915_request *w =
                                container_of(p->waiter, typeof(*w), sched);
 
@@ -1834,14 +1845,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
                         */
                        __unwind_incomplete_requests(engine);
 
-                       /*
-                        * If we need to return to the preempted context, we
-                        * need to skip the lite-restore and force it to
-                        * reload the RING_TAIL. Otherwise, the HW has a
-                        * tendency to ignore us rewinding the TAIL to the
-                        * end of an earlier request.
-                        */
-                       last->context->lrc_desc |= CTX_DESC_FORCE_RESTORE;
                        last = NULL;
                } else if (need_timeslice(engine, last) &&
                           timer_expired(&engine->execlists.timer)) {
@@ -2860,16 +2863,17 @@ static void execlists_context_unpin(struct intel_context *ce)
 
 static void
 __execlists_update_reg_state(const struct intel_context *ce,
-                            const struct intel_engine_cs *engine)
+                            const struct intel_engine_cs *engine,
+                            u32 head)
 {
        struct intel_ring *ring = ce->ring;
        u32 *regs = ce->lrc_reg_state;
 
-       GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->head));
+       GEM_BUG_ON(!intel_ring_offset_valid(ring, head));
        GEM_BUG_ON(!intel_ring_offset_valid(ring, ring->tail));
 
        regs[CTX_RING_START] = i915_ggtt_offset(ring->vma);
-       regs[CTX_RING_HEAD] = ring->head;
+       regs[CTX_RING_HEAD] = head;
        regs[CTX_RING_TAIL] = ring->tail;
 
        /* RPCS */
@@ -2898,7 +2902,7 @@ __execlists_context_pin(struct intel_context *ce,
 
        ce->lrc_desc = lrc_descriptor(ce, engine) | CTX_DESC_FORCE_RESTORE;
        ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
-       __execlists_update_reg_state(ce, engine);
+       __execlists_update_reg_state(ce, engine, ce->ring->tail);
 
        return 0;
 }
@@ -2939,7 +2943,7 @@ static void execlists_context_reset(struct intel_context *ce)
        /* Scrub away the garbage */
        execlists_init_reg_state(ce->lrc_reg_state,
                                 ce, ce->engine, ce->ring, true);
-       __execlists_update_reg_state(ce, ce->engine);
+       __execlists_update_reg_state(ce, ce->engine, ce->ring->tail);
 
        ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
 }
@@ -3494,6 +3498,7 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
        struct intel_engine_execlists * const execlists = &engine->execlists;
        struct intel_context *ce;
        struct i915_request *rq;
+       u32 head;
 
        mb(); /* paranoia: read the CSB pointers from after the reset */
        clflush(execlists->csb_write);
@@ -3521,15 +3526,15 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
 
        if (i915_request_completed(rq)) {
                /* Idle context; tidy up the ring so we can restart afresh */
-               ce->ring->head = intel_ring_wrap(ce->ring, rq->tail);
+               head = intel_ring_wrap(ce->ring, rq->tail);
                goto out_replay;
        }
 
        /* Context has requests still in-flight; it should not be idle! */
        GEM_BUG_ON(i915_active_is_idle(&ce->active));
        rq = active_request(ce->timeline, rq);
-       ce->ring->head = intel_ring_wrap(ce->ring, rq->head);
-       GEM_BUG_ON(ce->ring->head == ce->ring->tail);
+       head = intel_ring_wrap(ce->ring, rq->head);
+       GEM_BUG_ON(head == ce->ring->tail);
 
        /*
         * If this request hasn't started yet, e.g. it is waiting on a
@@ -3574,10 +3579,9 @@ static void __execlists_reset(struct intel_engine_cs *engine, bool stalled)
 
 out_replay:
        ENGINE_TRACE(engine, "replay {head:%04x, tail:%04x}\n",
-                    ce->ring->head, ce->ring->tail);
-       intel_ring_update_space(ce->ring);
+                    head, ce->ring->tail);
        __execlists_reset_reg_state(ce, engine);
-       __execlists_update_reg_state(ce, engine);
+       __execlists_update_reg_state(ce, engine, head);
        ce->lrc_desc |= CTX_DESC_FORCE_RESTORE; /* paranoid: GPU was reset! */
 
 unwind:
@@ -5220,10 +5224,7 @@ void intel_lr_context_reset(struct intel_engine_cs *engine,
                restore_default_state(ce, engine);
 
        /* Rerun the request; its payload has been neutered (if guilty). */
-       ce->ring->head = head;
-       intel_ring_update_space(ce->ring);
-
-       __execlists_update_reg_state(ce, engine);
+       __execlists_update_reg_state(ce, engine, head);
 }
 
 bool
index 374b28f..6ff803f 100644 (file)
@@ -145,6 +145,7 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size)
 
        kref_init(&ring->ref);
        ring->size = size;
+       ring->wrap = BITS_PER_TYPE(ring->size) - ilog2(size);
 
        /*
         * Workaround an erratum on the i830 which causes a hang if
index ea2839d..5bdce24 100644 (file)
@@ -56,6 +56,14 @@ static inline u32 intel_ring_wrap(const struct intel_ring *ring, u32 pos)
        return pos & (ring->size - 1);
 }
 
+static inline int intel_ring_direction(const struct intel_ring *ring,
+                                      u32 next, u32 prev)
+{
+       typecheck(typeof(ring->size), next);
+       typecheck(typeof(ring->size), prev);
+       return (next - prev) << ring->wrap;
+}
+
 static inline bool
 intel_ring_offset_valid(const struct intel_ring *ring,
                        unsigned int pos)
index d9f17f3..1a189ea 100644 (file)
@@ -39,12 +39,13 @@ struct intel_ring {
         */
        atomic_t pin_count;
 
-       u32 head;
-       u32 tail;
-       u32 emit;
+       u32 head; /* updated during retire, loosely tracks RING_HEAD */
+       u32 tail; /* updated on submission, used for RING_TAIL */
+       u32 emit; /* updated during request construction */
 
        u32 space;
        u32 size;
+       u32 wrap;
        u32 effective_size;
 };
 
index 65718ca..b292f8c 100644 (file)
@@ -186,7 +186,7 @@ static int live_unlite_restore(struct intel_gt *gt, int prio)
                }
                GEM_BUG_ON(!ce[1]->ring->size);
                intel_ring_reset(ce[1]->ring, ce[1]->ring->size / 2);
-               __execlists_update_reg_state(ce[1], engine);
+               __execlists_update_reg_state(ce[1], engine, ce[1]->ring->head);
 
                rq[0] = igt_spinner_create_request(&spin, ce[0], MI_ARB_CHECK);
                if (IS_ERR(rq[0])) {
index c2de2f4..5f6e639 100644 (file)
@@ -180,7 +180,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
                     struct drm_i915_gem_pwrite *args,
                     struct drm_file *file)
 {
-       void *vaddr = obj->phys_handle->vaddr + args->offset;
+       void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
        char __user *user_data = u64_to_user_ptr(args->data_ptr);
 
        /*
@@ -844,10 +844,10 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
                ret = i915_gem_gtt_pwrite_fast(obj, args);
 
        if (ret == -EFAULT || ret == -ENOSPC) {
-               if (obj->phys_handle)
-                       ret = i915_gem_phys_pwrite(obj, args, file);
-               else
+               if (i915_gem_object_has_struct_page(obj))
                        ret = i915_gem_shmem_pwrite(obj, args);
+               else
+                       ret = i915_gem_phys_pwrite(obj, args, file);
        }
 
        i915_gem_object_unpin_pages(obj);
index 594341e..9e401a5 100644 (file)
@@ -1852,7 +1852,8 @@ void i915_error_state_store(struct i915_gpu_coredump *error)
        if (!xchg(&warned, true) &&
            ktime_get_real_seconds() - DRIVER_TIMESTAMP < DAY_AS_SECONDS(180)) {
                pr_info("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n");
-               pr_info("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n");
+               pr_info("Please file a _new_ bug report at https://gitlab.freedesktop.org/drm/intel/issues/new.\n");
+               pr_info("Please see https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs for details.\n");
                pr_info("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n");
                pr_info("The GPU crash dump is required to analyze GPU hangs, so please always attach it.\n");
                pr_info("GPU crash dump saved to /sys/class/drm/card%d/error\n",
index 78a5f5d..f56b046 100644 (file)
@@ -595,6 +595,8 @@ static void __i915_request_ctor(void *arg)
        i915_sw_fence_init(&rq->submit, submit_notify);
        i915_sw_fence_init(&rq->semaphore, semaphore_notify);
 
+       dma_fence_init(&rq->fence, &i915_fence_ops, &rq->lock, 0, 0);
+
        rq->file_priv = NULL;
        rq->capture_list = NULL;
 
@@ -653,25 +655,30 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp)
                }
        }
 
-       ret = intel_timeline_get_seqno(tl, rq, &seqno);
-       if (ret)
-               goto err_free;
-
        rq->i915 = ce->engine->i915;
        rq->context = ce;
        rq->engine = ce->engine;
        rq->ring = ce->ring;
        rq->execution_mask = ce->engine->mask;
 
+       kref_init(&rq->fence.refcount);
+       rq->fence.flags = 0;
+       rq->fence.error = 0;
+       INIT_LIST_HEAD(&rq->fence.cb_list);
+
+       ret = intel_timeline_get_seqno(tl, rq, &seqno);
+       if (ret)
+               goto err_free;
+
+       rq->fence.context = tl->fence_context;
+       rq->fence.seqno = seqno;
+
        RCU_INIT_POINTER(rq->timeline, tl);
        RCU_INIT_POINTER(rq->hwsp_cacheline, tl->hwsp_cacheline);
        rq->hwsp_seqno = tl->hwsp_seqno;
 
        rq->rcustate = get_state_synchronize_rcu(); /* acts as smp_mb() */
 
-       dma_fence_init(&rq->fence, &i915_fence_ops, &rq->lock,
-                      tl->fence_context, seqno);
-
        /* We bump the ref for the fence chain */
        i915_sw_fence_reinit(&i915_request_get(rq)->submit);
        i915_sw_fence_reinit(&i915_request_get(rq)->semaphore);
index 5d96cfb..34b654b 100644 (file)
@@ -423,8 +423,6 @@ bool __i915_sched_node_add_dependency(struct i915_sched_node *node,
 
        if (!node_signaled(signal)) {
                INIT_LIST_HEAD(&dep->dfs_link);
-               list_add(&dep->wait_link, &signal->waiters_list);
-               list_add(&dep->signal_link, &node->signalers_list);
                dep->signaler = signal;
                dep->waiter = node;
                dep->flags = flags;
@@ -434,6 +432,10 @@ bool __i915_sched_node_add_dependency(struct i915_sched_node *node,
                    !node_started(signal))
                        node->flags |= I915_SCHED_HAS_SEMAPHORE_CHAIN;
 
+               /* All set, now publish. Beware the lockless walkers. */
+               list_add(&dep->signal_link, &node->signalers_list);
+               list_add_rcu(&dep->wait_link, &signal->waiters_list);
+
                /*
                 * As we do not allow WAIT to preempt inflight requests,
                 * once we have executed a request, along with triggering
index c47261a..632d695 100644 (file)
@@ -8,9 +8,8 @@
 #include "i915_drv.h"
 #include "i915_utils.h"
 
-#define FDO_BUG_URL "https://bugs.freedesktop.org/enter_bug.cgi?product=DRI"
-#define FDO_BUG_MSG "Please file a bug at " FDO_BUG_URL " against DRM/Intel " \
-                   "providing the dmesg log by booting with drm.debug=0xf"
+#define FDO_BUG_URL "https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs"
+#define FDO_BUG_MSG "Please file a bug on drm/i915; see " FDO_BUG_URL " for details."
 
 void
 __i915_printk(struct drm_i915_private *dev_priv, const char *level,
index 983afea..748cd37 100644 (file)
@@ -796,12 +796,41 @@ bool a6xx_gmu_isidle(struct a6xx_gmu *gmu)
        return true;
 }
 
+#define GBIF_CLIENT_HALT_MASK             BIT(0)
+#define GBIF_ARB_HALT_MASK                BIT(1)
+
+static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu)
+{
+       struct msm_gpu *gpu = &adreno_gpu->base;
+
+       if (!a6xx_has_gbif(adreno_gpu)) {
+               gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf);
+               spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) &
+                                                               0xf) == 0xf);
+               gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0);
+
+               return;
+       }
+
+       /* Halt new client requests on GBIF */
+       gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK);
+       spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) &
+                       (GBIF_CLIENT_HALT_MASK)) == GBIF_CLIENT_HALT_MASK);
+
+       /* Halt all AXI requests on GBIF */
+       gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_ARB_HALT_MASK);
+       spin_until((gpu_read(gpu,  REG_A6XX_GBIF_HALT_ACK) &
+                       (GBIF_ARB_HALT_MASK)) == GBIF_ARB_HALT_MASK);
+
+       /* The GBIF halt needs to be explicitly cleared */
+       gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0);
+}
+
 /* Gracefully try to shut down the GMU and by extension the GPU */
 static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu)
 {
        struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
        struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
-       struct msm_gpu *gpu = &adreno_gpu->base;
        u32 val;
 
        /*
@@ -819,11 +848,7 @@ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu)
                        return;
                }
 
-               /* Clear the VBIF pipe before shutting down */
-               gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf);
-               spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) & 0xf)
-                       == 0xf);
-               gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0);
+               a6xx_bus_clear_pending_transactions(adreno_gpu);
 
                /* tell the GMU we want to slumber */
                a6xx_gmu_notify_slumber(gmu);
index daf0780..68af241 100644 (file)
@@ -378,18 +378,6 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
        struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
        int ret;
 
-       /*
-        * During a previous slumber, GBIF halt is asserted to ensure
-        * no further transaction can go through GPU before GPU
-        * headswitch is turned off.
-        *
-        * This halt is deasserted once headswitch goes off but
-        * incase headswitch doesn't goes off clear GBIF halt
-        * here to ensure GPU wake-up doesn't fail because of
-        * halted GPU transactions.
-        */
-       gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0);
-
        /* Make sure the GMU keeps the GPU on while we set it up */
        a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
 
@@ -470,10 +458,12 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
        /* Select CP0 to always count cycles */
        gpu_write(gpu, REG_A6XX_CP_PERFCTR_CP_SEL_0, PERF_CP_ALWAYS_COUNT);
 
-       gpu_write(gpu, REG_A6XX_RB_NC_MODE_CNTL, 2 << 1);
-       gpu_write(gpu, REG_A6XX_TPL1_NC_MODE_CNTL, 2 << 1);
-       gpu_write(gpu, REG_A6XX_SP_NC_MODE_CNTL, 2 << 1);
-       gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL, 2 << 21);
+       if (adreno_is_a630(adreno_gpu)) {
+               gpu_write(gpu, REG_A6XX_RB_NC_MODE_CNTL, 2 << 1);
+               gpu_write(gpu, REG_A6XX_TPL1_NC_MODE_CNTL, 2 << 1);
+               gpu_write(gpu, REG_A6XX_SP_NC_MODE_CNTL, 2 << 1);
+               gpu_write(gpu, REG_A6XX_UCHE_MODE_CNTL, 2 << 21);
+       }
 
        /* Enable fault detection */
        gpu_write(gpu, REG_A6XX_RBBM_INTERFACE_HANG_INT_CNTL,
@@ -748,39 +738,6 @@ static const u32 a6xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
        REG_ADRENO_DEFINE(REG_ADRENO_CP_RB_CNTL, REG_A6XX_CP_RB_CNTL),
 };
 
-#define GBIF_CLIENT_HALT_MASK             BIT(0)
-#define GBIF_ARB_HALT_MASK                BIT(1)
-
-static void a6xx_bus_clear_pending_transactions(struct adreno_gpu *adreno_gpu)
-{
-       struct msm_gpu *gpu = &adreno_gpu->base;
-
-       if(!a6xx_has_gbif(adreno_gpu)){
-               gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf);
-               spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) &
-                                                               0xf) == 0xf);
-               gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0);
-
-               return;
-       }
-
-       /* Halt new client requests on GBIF */
-       gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_CLIENT_HALT_MASK);
-       spin_until((gpu_read(gpu, REG_A6XX_GBIF_HALT_ACK) &
-                       (GBIF_CLIENT_HALT_MASK)) == GBIF_CLIENT_HALT_MASK);
-
-       /* Halt all AXI requests on GBIF */
-       gpu_write(gpu, REG_A6XX_GBIF_HALT, GBIF_ARB_HALT_MASK);
-       spin_until((gpu_read(gpu,  REG_A6XX_GBIF_HALT_ACK) &
-                       (GBIF_ARB_HALT_MASK)) == GBIF_ARB_HALT_MASK);
-
-       /*
-        * GMU needs DDR access in slumber path. Deassert GBIF halt now
-        * to allow for GMU to access system memory.
-        */
-       gpu_write(gpu, REG_A6XX_GBIF_HALT, 0x0);
-}
-
 static int a6xx_pm_resume(struct msm_gpu *gpu)
 {
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -805,16 +762,6 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
 
        devfreq_suspend_device(gpu->devfreq.devfreq);
 
-       /*
-        * Make sure the GMU is idle before continuing (because some transitions
-        * may use VBIF
-        */
-       a6xx_gmu_wait_for_idle(&a6xx_gpu->gmu);
-
-       /* Clear the VBIF pipe before shutting down */
-       /* FIXME: This accesses the GPU - do we need to make sure it is on? */
-       a6xx_bus_clear_pending_transactions(adreno_gpu);
-
        return a6xx_gmu_stop(a6xx_gpu);
 }
 
index eda11ab..e450e0b 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "a6xx_gmu.h"
 #include "a6xx_gmu.xml.h"
+#include "a6xx_gpu.h"
 
 #define HFI_MSG_ID(val) [val] = #val
 
@@ -216,48 +217,82 @@ static int a6xx_hfi_send_perf_table(struct a6xx_gmu *gmu)
                NULL, 0);
 }
 
-static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu)
+static void a618_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
 {
-       struct a6xx_hfi_msg_bw_table msg = { 0 };
+       /* Send a single "off" entry since the 618 GMU doesn't do bus scaling */
+       msg->bw_level_num = 1;
+
+       msg->ddr_cmds_num = 3;
+       msg->ddr_wait_bitmask = 0x01;
+
+       msg->ddr_cmds_addrs[0] = 0x50000;
+       msg->ddr_cmds_addrs[1] = 0x5003c;
+       msg->ddr_cmds_addrs[2] = 0x5000c;
+
+       msg->ddr_cmds_data[0][0] =  0x40000000;
+       msg->ddr_cmds_data[0][1] =  0x40000000;
+       msg->ddr_cmds_data[0][2] =  0x40000000;
 
        /*
-        * The sdm845 GMU doesn't do bus frequency scaling on its own but it
-        * does need at least one entry in the list because it might be accessed
-        * when the GMU is shutting down. Send a single "off" entry.
+        * These are the CX (CNOC) votes - these are used by the GMU but the
+        * votes are known and fixed for the target
         */
+       msg->cnoc_cmds_num = 1;
+       msg->cnoc_wait_bitmask = 0x01;
+
+       msg->cnoc_cmds_addrs[0] = 0x5007c;
+       msg->cnoc_cmds_data[0][0] =  0x40000000;
+       msg->cnoc_cmds_data[1][0] =  0x60000001;
+}
 
-       msg.bw_level_num = 1;
+static void a6xx_build_bw_table(struct a6xx_hfi_msg_bw_table *msg)
+{
+       /* Send a single "off" entry since the 630 GMU doesn't do bus scaling */
+       msg->bw_level_num = 1;
 
-       msg.ddr_cmds_num = 3;
-       msg.ddr_wait_bitmask = 0x07;
+       msg->ddr_cmds_num = 3;
+       msg->ddr_wait_bitmask = 0x07;
 
-       msg.ddr_cmds_addrs[0] = 0x50000;
-       msg.ddr_cmds_addrs[1] = 0x5005c;
-       msg.ddr_cmds_addrs[2] = 0x5000c;
+       msg->ddr_cmds_addrs[0] = 0x50000;
+       msg->ddr_cmds_addrs[1] = 0x5005c;
+       msg->ddr_cmds_addrs[2] = 0x5000c;
 
-       msg.ddr_cmds_data[0][0] =  0x40000000;
-       msg.ddr_cmds_data[0][1] =  0x40000000;
-       msg.ddr_cmds_data[0][2] =  0x40000000;
+       msg->ddr_cmds_data[0][0] =  0x40000000;
+       msg->ddr_cmds_data[0][1] =  0x40000000;
+       msg->ddr_cmds_data[0][2] =  0x40000000;
 
        /*
         * These are the CX (CNOC) votes.  This is used but the values for the
         * sdm845 GMU are known and fixed so we can hard code them.
         */
 
-       msg.cnoc_cmds_num = 3;
-       msg.cnoc_wait_bitmask = 0x05;
+       msg->cnoc_cmds_num = 3;
+       msg->cnoc_wait_bitmask = 0x05;
 
-       msg.cnoc_cmds_addrs[0] = 0x50034;
-       msg.cnoc_cmds_addrs[1] = 0x5007c;
-       msg.cnoc_cmds_addrs[2] = 0x5004c;
+       msg->cnoc_cmds_addrs[0] = 0x50034;
+       msg->cnoc_cmds_addrs[1] = 0x5007c;
+       msg->cnoc_cmds_addrs[2] = 0x5004c;
 
-       msg.cnoc_cmds_data[0][0] =  0x40000000;
-       msg.cnoc_cmds_data[0][1] =  0x00000000;
-       msg.cnoc_cmds_data[0][2] =  0x40000000;
+       msg->cnoc_cmds_data[0][0] =  0x40000000;
+       msg->cnoc_cmds_data[0][1] =  0x00000000;
+       msg->cnoc_cmds_data[0][2] =  0x40000000;
+
+       msg->cnoc_cmds_data[1][0] =  0x60000001;
+       msg->cnoc_cmds_data[1][1] =  0x20000001;
+       msg->cnoc_cmds_data[1][2] =  0x60000001;
+}
+
+
+static int a6xx_hfi_send_bw_table(struct a6xx_gmu *gmu)
+{
+       struct a6xx_hfi_msg_bw_table msg = { 0 };
+       struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
+       struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
 
-       msg.cnoc_cmds_data[1][0] =  0x60000001;
-       msg.cnoc_cmds_data[1][1] =  0x20000001;
-       msg.cnoc_cmds_data[1][2] =  0x60000001;
+       if (adreno_is_a618(adreno_gpu))
+               a618_build_bw_table(&msg);
+       else
+               a6xx_build_bw_table(&msg);
 
        return a6xx_hfi_send_msg(gmu, HFI_H2F_MSG_BW_TABLE, &msg, sizeof(msg),
                NULL, 0);
index 5286326..a05282d 100644 (file)
@@ -255,13 +255,13 @@ static const struct dpu_format dpu_format_map[] = {
 
        INTERLEAVED_RGB_FMT(RGB565,
                0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
-               C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
+               C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
                false, 2, 0,
                DPU_FETCH_LINEAR, 1),
 
        INTERLEAVED_RGB_FMT(BGR565,
                0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
-               C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
+               C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
                false, 2, 0,
                DPU_FETCH_LINEAR, 1),
 
index 29705e7..80d3cfc 100644 (file)
@@ -12,6 +12,7 @@
 
 #define to_dpu_mdss(x) container_of(x, struct dpu_mdss, base)
 
+#define HW_REV                         0x0
 #define HW_INTR_STATUS                 0x0010
 
 /* Max BW defined in KBps */
@@ -22,6 +23,17 @@ struct dpu_irq_controller {
        struct irq_domain *domain;
 };
 
+struct dpu_hw_cfg {
+       u32 val;
+       u32 offset;
+};
+
+struct dpu_mdss_hw_init_handler {
+       u32 hw_rev;
+       u32 hw_reg_count;
+       struct dpu_hw_cfg* hw_cfg;
+};
+
 struct dpu_mdss {
        struct msm_mdss base;
        void __iomem *mmio;
@@ -32,6 +44,44 @@ struct dpu_mdss {
        u32 num_paths;
 };
 
+static struct dpu_hw_cfg hw_cfg[] = {
+    {
+       /* UBWC global settings */
+       .val = 0x1E,
+       .offset = 0x144,
+    }
+};
+
+static struct dpu_mdss_hw_init_handler cfg_handler[] = {
+    { .hw_rev = DPU_HW_VER_620,
+      .hw_reg_count = ARRAY_SIZE(hw_cfg),
+      .hw_cfg = hw_cfg
+    },
+};
+
+static void dpu_mdss_hw_init(struct dpu_mdss *dpu_mdss, u32 hw_rev)
+{
+       int i;
+       u32 count = 0;
+       struct dpu_hw_cfg *hw_cfg = NULL;
+
+       for (i = 0; i < ARRAY_SIZE(cfg_handler); i++) {
+               if (cfg_handler[i].hw_rev == hw_rev) {
+                       hw_cfg = cfg_handler[i].hw_cfg;
+                       count = cfg_handler[i].hw_reg_count;
+                       break;
+           }
+       }
+
+       for (i = 0; i < count; i++ ) {
+               writel_relaxed(hw_cfg->val,
+                       dpu_mdss->mmio + hw_cfg->offset);
+               hw_cfg++;
+       }
+
+    return;
+}
+
 static int dpu_mdss_parse_data_bus_icc_path(struct drm_device *dev,
                                                struct dpu_mdss *dpu_mdss)
 {
@@ -174,12 +224,18 @@ static int dpu_mdss_enable(struct msm_mdss *mdss)
        struct dpu_mdss *dpu_mdss = to_dpu_mdss(mdss);
        struct dss_module_power *mp = &dpu_mdss->mp;
        int ret;
+       u32 mdss_rev;
 
        dpu_mdss_icc_request_bw(mdss);
 
        ret = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
-       if (ret)
+       if (ret) {
                DPU_ERROR("clock enable failed, ret:%d\n", ret);
+               return ret;
+       }
+
+       mdss_rev = readl_relaxed(dpu_mdss->mmio + HW_REV);
+       dpu_mdss_hw_init(dpu_mdss, mdss_rev);
 
        return ret;
 }
index 05cc04f..e1cc541 100644 (file)
@@ -1109,8 +1109,8 @@ static void mdp5_crtc_wait_for_pp_done(struct drm_crtc *crtc)
        ret = wait_for_completion_timeout(&mdp5_crtc->pp_completion,
                                                msecs_to_jiffies(50));
        if (ret == 0)
-               dev_warn(dev->dev, "pp done time out, lm=%d\n",
-                        mdp5_cstate->pipeline.mixer->lm);
+               dev_warn_ratelimited(dev->dev, "pp done time out, lm=%d\n",
+                                    mdp5_cstate->pipeline.mixer->lm);
 }
 
 static void mdp5_crtc_wait_for_flush_done(struct drm_crtc *crtc)
index 104115d..4864b95 100644 (file)
@@ -336,7 +336,7 @@ static int dsi_mgr_connector_get_modes(struct drm_connector *connector)
        return num;
 }
 
-static int dsi_mgr_connector_mode_valid(struct drm_connector *connector,
+static enum drm_mode_status dsi_mgr_connector_mode_valid(struct drm_connector *connector,
                                struct drm_display_mode *mode)
 {
        int id = dsi_mgr_connector_get_id(connector);
@@ -506,6 +506,7 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
        struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
        struct mipi_dsi_host *host = msm_dsi->host;
        struct drm_panel *panel = msm_dsi->panel;
+       struct msm_dsi_pll *src_pll;
        bool is_dual_dsi = IS_DUAL_DSI();
        int ret;
 
@@ -539,6 +540,10 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
                                                                id, ret);
        }
 
+       /* Save PLL status if it is a clock source */
+       src_pll = msm_dsi_phy_get_pll(msm_dsi->phy);
+       msm_dsi_pll_save_state(src_pll);
+
        ret = msm_dsi_host_power_off(host);
        if (ret)
                pr_err("%s: host %d power off failed,%d\n", __func__, id, ret);
index b0cfa67..f509ebd 100644 (file)
@@ -724,10 +724,6 @@ void msm_dsi_phy_disable(struct msm_dsi_phy *phy)
        if (!phy || !phy->cfg->ops.disable)
                return;
 
-       /* Save PLL status if it is a clock source */
-       if (phy->usecase != MSM_DSI_PHY_SLAVE)
-               msm_dsi_pll_save_state(phy->pll);
-
        phy->cfg->ops.disable(phy);
 
        dsi_phy_regulator_disable(phy);
index 1c89454..6ac04fc 100644 (file)
@@ -411,6 +411,12 @@ static int dsi_pll_10nm_vco_prepare(struct clk_hw *hw)
        if (pll_10nm->slave)
                dsi_pll_enable_pll_bias(pll_10nm->slave);
 
+       rc = dsi_pll_10nm_vco_set_rate(hw,pll_10nm->vco_current_rate, 0);
+       if (rc) {
+               pr_err("vco_set_rate failed, rc=%d\n", rc);
+               return rc;
+       }
+
        /* Start PLL */
        pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_PLL_CNTRL,
                  0x01);
index 8903152..bb737f9 100644 (file)
@@ -458,6 +458,8 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
                asyw->clr.ntfy = armw->ntfy.handle != 0;
                asyw->clr.sema = armw->sema.handle != 0;
                asyw->clr.xlut = armw->xlut.handle != 0;
+               if (asyw->clr.xlut && asyw->visible)
+                       asyw->set.xlut = asyw->xlut.handle != 0;
                asyw->clr.csc  = armw->csc.valid;
                if (wndw->func->image_clr)
                        asyw->clr.image = armw->image.handle[0] != 0;
index c7d7009..8ebbe16 100644 (file)
@@ -2579,6 +2579,7 @@ nv166_chipset = {
 static const struct nvkm_device_chip
 nv167_chipset = {
        .name = "TU117",
+       .acr = tu102_acr_new,
        .bar = tu102_bar_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
@@ -2607,6 +2608,7 @@ nv167_chipset = {
        .disp = tu102_disp_new,
        .dma = gv100_dma_new,
        .fifo = tu102_fifo_new,
+       .gr = tu102_gr_new,
        .nvdec[0] = gm107_nvdec_new,
        .nvenc[0] = gm107_nvenc_new,
        .sec2 = tu102_sec2_new,
@@ -2615,6 +2617,7 @@ nv167_chipset = {
 static const struct nvkm_device_chip
 nv168_chipset = {
        .name = "TU116",
+       .acr = tu102_acr_new,
        .bar = tu102_bar_new,
        .bios = nvkm_bios_new,
        .bus = gf100_bus_new,
@@ -2643,6 +2646,7 @@ nv168_chipset = {
        .disp = tu102_disp_new,
        .dma = gv100_dma_new,
        .fifo = tu102_fifo_new,
+       .gr = tu102_gr_new,
        .nvdec[0] = gm107_nvdec_new,
        .nvenc[0] = gm107_nvenc_new,
        .sec2 = tu102_sec2_new,
index 454668b..a9efa4d 100644 (file)
@@ -164,6 +164,32 @@ MODULE_FIRMWARE("nvidia/tu106/gr/sw_nonctx.bin");
 MODULE_FIRMWARE("nvidia/tu106/gr/sw_bundle_init.bin");
 MODULE_FIRMWARE("nvidia/tu106/gr/sw_method_init.bin");
 
+MODULE_FIRMWARE("nvidia/tu117/gr/fecs_bl.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/fecs_inst.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/fecs_data.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/fecs_sig.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/gpccs_bl.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/gpccs_inst.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/gpccs_data.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/gpccs_sig.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/sw_ctx.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/sw_nonctx.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/sw_bundle_init.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/sw_method_init.bin");
+
+MODULE_FIRMWARE("nvidia/tu116/gr/fecs_bl.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/fecs_inst.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/fecs_data.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/fecs_sig.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/gpccs_bl.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/gpccs_inst.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/gpccs_data.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/gpccs_sig.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/sw_ctx.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/sw_nonctx.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/sw_bundle_init.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/sw_method_init.bin");
+
 static const struct gf100_gr_fwif
 tu102_gr_fwif[] = {
        { 0, gm200_gr_load, &tu102_gr, &gp108_gr_fecs_acr, &gp108_gr_gpccs_acr },
index 7f4b89d..d28d8f3 100644 (file)
@@ -107,6 +107,12 @@ MODULE_FIRMWARE("nvidia/tu104/acr/ucode_unload.bin");
 MODULE_FIRMWARE("nvidia/tu106/acr/unload_bl.bin");
 MODULE_FIRMWARE("nvidia/tu106/acr/ucode_unload.bin");
 
+MODULE_FIRMWARE("nvidia/tu116/acr/unload_bl.bin");
+MODULE_FIRMWARE("nvidia/tu116/acr/ucode_unload.bin");
+
+MODULE_FIRMWARE("nvidia/tu117/acr/unload_bl.bin");
+MODULE_FIRMWARE("nvidia/tu117/acr/ucode_unload.bin");
+
 static const struct nvkm_acr_hsf_fwif
 tu102_acr_unload_fwif[] = {
        {  0, nvkm_acr_hsfw_load, &gp108_acr_unload_0 },
@@ -130,6 +136,8 @@ tu102_acr_asb_0 = {
 MODULE_FIRMWARE("nvidia/tu102/acr/ucode_asb.bin");
 MODULE_FIRMWARE("nvidia/tu104/acr/ucode_asb.bin");
 MODULE_FIRMWARE("nvidia/tu106/acr/ucode_asb.bin");
+MODULE_FIRMWARE("nvidia/tu116/acr/ucode_asb.bin");
+MODULE_FIRMWARE("nvidia/tu117/acr/ucode_asb.bin");
 
 static const struct nvkm_acr_hsf_fwif
 tu102_acr_asb_fwif[] = {
@@ -154,6 +162,12 @@ MODULE_FIRMWARE("nvidia/tu104/acr/ucode_ahesasc.bin");
 MODULE_FIRMWARE("nvidia/tu106/acr/bl.bin");
 MODULE_FIRMWARE("nvidia/tu106/acr/ucode_ahesasc.bin");
 
+MODULE_FIRMWARE("nvidia/tu116/acr/bl.bin");
+MODULE_FIRMWARE("nvidia/tu116/acr/ucode_ahesasc.bin");
+
+MODULE_FIRMWARE("nvidia/tu117/acr/bl.bin");
+MODULE_FIRMWARE("nvidia/tu117/acr/ucode_ahesasc.bin");
+
 static const struct nvkm_acr_hsf_fwif
 tu102_acr_ahesasc_fwif[] = {
        {  0, nvkm_acr_hsfw_load, &tu102_acr_ahesasc_0 },
index 389bad3..10ff5d0 100644 (file)
@@ -51,3 +51,5 @@ MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin");
 MODULE_FIRMWARE("nvidia/tu102/nvdec/scrubber.bin");
 MODULE_FIRMWARE("nvidia/tu104/nvdec/scrubber.bin");
 MODULE_FIRMWARE("nvidia/tu106/nvdec/scrubber.bin");
+MODULE_FIRMWARE("nvidia/tu116/nvdec/scrubber.bin");
+MODULE_FIRMWARE("nvidia/tu117/nvdec/scrubber.bin");
index 7157dfd..9a1a72a 100644 (file)
@@ -280,12 +280,8 @@ static void panfrost_job_cleanup(struct kref *ref)
        }
 
        if (job->bos) {
-               struct panfrost_gem_object *bo;
-
-               for (i = 0; i < job->bo_count; i++) {
-                       bo = to_panfrost_bo(job->bos[i]);
+               for (i = 0; i < job->bo_count; i++)
                        drm_gem_object_put_unlocked(job->bos[i]);
-               }
 
                kvfree(job->bos);
        }
index 763cfca..3107b07 100644 (file)
@@ -151,7 +151,12 @@ u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu)
        as = mmu->as;
        if (as >= 0) {
                int en = atomic_inc_return(&mmu->as_count);
-               WARN_ON(en >= NUM_JOB_SLOTS);
+
+               /*
+                * AS can be retained by active jobs or a perfcnt context,
+                * hence the '+ 1' here.
+                */
+               WARN_ON(en >= (NUM_JOB_SLOTS + 1));
 
                list_move(&mmu->list, &pfdev->as_lru_list);
                goto out;
index 6848204..6913578 100644 (file)
@@ -73,7 +73,7 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
        struct panfrost_file_priv *user = file_priv->driver_priv;
        struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
        struct drm_gem_shmem_object *bo;
-       u32 cfg;
+       u32 cfg, as;
        int ret;
 
        if (user == perfcnt->user)
@@ -126,12 +126,8 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
 
        perfcnt->user = user;
 
-       /*
-        * Always use address space 0 for now.
-        * FIXME: this needs to be updated when we start using different
-        * address space.
-        */
-       cfg = GPU_PERFCNT_CFG_AS(0) |
+       as = panfrost_mmu_as_get(pfdev, perfcnt->mapping->mmu);
+       cfg = GPU_PERFCNT_CFG_AS(as) |
              GPU_PERFCNT_CFG_MODE(GPU_PERFCNT_CFG_MODE_MANUAL);
 
        /*
@@ -195,6 +191,7 @@ static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev,
        drm_gem_shmem_vunmap(&perfcnt->mapping->obj->base.base, perfcnt->buf);
        perfcnt->buf = NULL;
        panfrost_gem_close(&perfcnt->mapping->obj->base.base, file_priv);
+       panfrost_mmu_as_put(pfdev, perfcnt->mapping->mmu);
        panfrost_gem_mapping_put(perfcnt->mapping);
        perfcnt->mapping = NULL;
        pm_runtime_mark_last_busy(pfdev->dev);
index ceac7af..29e367d 100644 (file)
@@ -53,6 +53,7 @@ cmdline_test(drm_cmdline_test_rotate_0)
 cmdline_test(drm_cmdline_test_rotate_90)
 cmdline_test(drm_cmdline_test_rotate_180)
 cmdline_test(drm_cmdline_test_rotate_270)
+cmdline_test(drm_cmdline_test_rotate_multiple)
 cmdline_test(drm_cmdline_test_rotate_invalid_val)
 cmdline_test(drm_cmdline_test_rotate_truncated)
 cmdline_test(drm_cmdline_test_hmirror)
index 520f3e6..d96cd89 100644 (file)
@@ -856,6 +856,17 @@ static int drm_cmdline_test_rotate_270(void *ignored)
        return 0;
 }
 
+static int drm_cmdline_test_rotate_multiple(void *ignored)
+{
+       struct drm_cmdline_mode mode = { };
+
+       FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,rotate=0,rotate=90",
+                                                         &no_connector,
+                                                         &mode));
+
+       return 0;
+}
+
 static int drm_cmdline_test_rotate_invalid_val(void *ignored)
 {
        struct drm_cmdline_mode mode = { };
@@ -888,7 +899,7 @@ static int drm_cmdline_test_hmirror(void *ignored)
        FAIL_ON(!mode.specified);
        FAIL_ON(mode.xres != 720);
        FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.rotation_reflection != DRM_MODE_REFLECT_X);
+       FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_X));
 
        FAIL_ON(mode.refresh_specified);
 
@@ -913,7 +924,7 @@ static int drm_cmdline_test_vmirror(void *ignored)
        FAIL_ON(!mode.specified);
        FAIL_ON(mode.xres != 720);
        FAIL_ON(mode.yres != 480);
-       FAIL_ON(mode.rotation_reflection != DRM_MODE_REFLECT_Y);
+       FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y));
 
        FAIL_ON(mode.refresh_specified);
 
index 4cf2545..0db8ef4 100644 (file)
@@ -355,7 +355,9 @@ static ssize_t show_str(struct device *dev,
        struct acpi_device *acpi_dev = to_acpi_device(dev);
        struct acpi_power_meter_resource *resource = acpi_dev->driver_data;
        acpi_string val;
+       int ret;
 
+       mutex_lock(&resource->lock);
        switch (attr->index) {
        case 0:
                val = resource->model_number;
@@ -372,8 +374,9 @@ static ssize_t show_str(struct device *dev,
                val = "";
                break;
        }
-
-       return sprintf(buf, "%s\n", val);
+       ret = sprintf(buf, "%s\n", val);
+       mutex_unlock(&resource->lock);
+       return ret;
 }
 
 static ssize_t show_val(struct device *dev,
@@ -817,11 +820,12 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
 
        resource = acpi_driver_data(device);
 
-       mutex_lock(&resource->lock);
        switch (event) {
        case METER_NOTIFY_CONFIG:
+               mutex_lock(&resource->lock);
                free_capabilities(resource);
                res = read_capabilities(resource);
+               mutex_unlock(&resource->lock);
                if (res)
                        break;
 
@@ -830,15 +834,12 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
                break;
        case METER_NOTIFY_TRIP:
                sysfs_notify(&device->dev.kobj, NULL, POWER_AVERAGE_NAME);
-               update_meter(resource);
                break;
        case METER_NOTIFY_CAP:
                sysfs_notify(&device->dev.kobj, NULL, POWER_CAP_NAME);
-               update_cap(resource);
                break;
        case METER_NOTIFY_INTERVAL:
                sysfs_notify(&device->dev.kobj, NULL, POWER_AVG_INTERVAL_NAME);
-               update_avg_interval(resource);
                break;
        case METER_NOTIFY_CAPPING:
                sysfs_notify(&device->dev.kobj, NULL, POWER_ALARM_NAME);
@@ -848,7 +849,6 @@ static void acpi_power_meter_notify(struct acpi_device *device, u32 event)
                WARN(1, "Unexpected event %d\n", event);
                break;
        }
-       mutex_unlock(&resource->lock);
 
        acpi_bus_generate_netlink_event(ACPI_POWER_METER_CLASS,
                                        dev_name(&device->dev), event, 0);
@@ -912,8 +912,8 @@ static int acpi_power_meter_remove(struct acpi_device *device)
        resource = acpi_driver_data(device);
        hwmon_device_unregister(resource->hwmon_dev);
 
-       free_capabilities(resource);
        remove_attrs(resource);
+       free_capabilities(resource);
 
        kfree(resource);
        return 0;
index 7ffadc2..5a51201 100644 (file)
@@ -1346,8 +1346,13 @@ w83627ehf_is_visible(const void *drvdata, enum hwmon_sensor_types type,
                /* channel 0.., name 1.. */
                if (!(data->have_temp & (1 << channel)))
                        return 0;
-               if (attr == hwmon_temp_input || attr == hwmon_temp_label)
+               if (attr == hwmon_temp_input)
                        return 0444;
+               if (attr == hwmon_temp_label) {
+                       if (data->temp_label)
+                               return 0444;
+                       return 0;
+               }
                if (channel == 2 && data->temp3_val_only)
                        return 0;
                if (attr == hwmon_temp_max) {
index b273e42..a1a0352 100644 (file)
@@ -2575,6 +2575,17 @@ isert_wait4logout(struct isert_conn *isert_conn)
        }
 }
 
+static void
+isert_wait4cmds(struct iscsi_conn *conn)
+{
+       isert_info("iscsi_conn %p\n", conn);
+
+       if (conn->sess) {
+               target_sess_cmd_list_set_waiting(conn->sess->se_sess);
+               target_wait_for_sess_cmds(conn->sess->se_sess);
+       }
+}
+
 /**
  * isert_put_unsol_pending_cmds() - Drop commands waiting for
  *     unsolicitate dataout
@@ -2622,6 +2633,7 @@ static void isert_wait_conn(struct iscsi_conn *conn)
 
        ib_drain_qp(isert_conn->qp);
        isert_put_unsol_pending_cmds(conn);
+       isert_wait4cmds(conn);
        isert_wait4logout(isert_conn);
 
        queue_work(isert_release_wq, &isert_conn->release_work);
index 2104fb8..9f33fdb 100644 (file)
@@ -14,8 +14,8 @@ obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
 obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o amd_iommu_quirks.o
 obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
-obj-$(CONFIG_ARM_SMMU) += arm-smmu-mod.o
-arm-smmu-mod-objs += arm-smmu.o arm-smmu-impl.o arm-smmu-qcom.o
+obj-$(CONFIG_ARM_SMMU) += arm_smmu.o
+arm_smmu-objs += arm-smmu.o arm-smmu-impl.o arm-smmu-qcom.o
 obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
 obj-$(CONFIG_DMAR_TABLE) += dmar.o
 obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o intel-pasid.o
index 2759a8d..6be3853 100644 (file)
@@ -2523,6 +2523,7 @@ static int __init early_amd_iommu_init(void)
        struct acpi_table_header *ivrs_base;
        acpi_status status;
        int i, remap_cache_sz, ret = 0;
+       u32 pci_id;
 
        if (!amd_iommu_detected)
                return -ENODEV;
@@ -2610,6 +2611,16 @@ static int __init early_amd_iommu_init(void)
        if (ret)
                goto out;
 
+       /* Disable IOMMU if there's Stoney Ridge graphics */
+       for (i = 0; i < 32; i++) {
+               pci_id = read_pci_config(0, i, 0, 0);
+               if ((pci_id & 0xffff) == 0x1002 && (pci_id >> 16) == 0x98e4) {
+                       pr_info("Disable IOMMU on Stoney Ridge\n");
+                       amd_iommu_disabled = true;
+                       break;
+               }
+       }
+
        /* Disable any previously enabled IOMMUs */
        if (!is_kdump_kernel() || amd_iommu_disabled)
                disable_iommus();
@@ -2718,7 +2729,7 @@ static int __init state_next(void)
                ret = early_amd_iommu_init();
                init_state = ret ? IOMMU_INIT_ERROR : IOMMU_ACPI_FINISHED;
                if (init_state == IOMMU_ACPI_FINISHED && amd_iommu_disabled) {
-                       pr_info("AMD IOMMU disabled on kernel command-line\n");
+                       pr_info("AMD IOMMU disabled\n");
                        init_state = IOMMU_CMDLINE_DISABLED;
                        ret = -EINVAL;
                }
index 9dc3767..6fa6de2 100644 (file)
@@ -762,6 +762,11 @@ static int iommu_dummy(struct device *dev)
        return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
 }
 
+static bool attach_deferred(struct device *dev)
+{
+       return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO;
+}
+
 /**
  * is_downstream_to_pci_bridge - test if a device belongs to the PCI
  *                              sub-hierarchy of a candidate PCI-PCI bridge
@@ -2510,8 +2515,7 @@ struct dmar_domain *find_domain(struct device *dev)
 {
        struct device_domain_info *info;
 
-       if (unlikely(dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO ||
-                    dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO))
+       if (unlikely(attach_deferred(dev) || iommu_dummy(dev)))
                return NULL;
 
        if (dev_is_pci(dev))
@@ -2525,18 +2529,14 @@ struct dmar_domain *find_domain(struct device *dev)
        return NULL;
 }
 
-static struct dmar_domain *deferred_attach_domain(struct device *dev)
+static void do_deferred_attach(struct device *dev)
 {
-       if (unlikely(dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO)) {
-               struct iommu_domain *domain;
-
-               dev->archdata.iommu = NULL;
-               domain = iommu_get_domain_for_dev(dev);
-               if (domain)
-                       intel_iommu_attach_device(domain, dev);
-       }
+       struct iommu_domain *domain;
 
-       return find_domain(dev);
+       dev->archdata.iommu = NULL;
+       domain = iommu_get_domain_for_dev(dev);
+       if (domain)
+               intel_iommu_attach_device(domain, dev);
 }
 
 static inline struct device_domain_info *
@@ -2916,7 +2916,7 @@ static int identity_mapping(struct device *dev)
        struct device_domain_info *info;
 
        info = dev->archdata.iommu;
-       if (info && info != DUMMY_DEVICE_DOMAIN_INFO && info != DEFER_DEVICE_DOMAIN_INFO)
+       if (info)
                return (info->domain == si_domain);
 
        return 0;
@@ -3587,6 +3587,9 @@ static bool iommu_need_mapping(struct device *dev)
        if (iommu_dummy(dev))
                return false;
 
+       if (unlikely(attach_deferred(dev)))
+               do_deferred_attach(dev);
+
        ret = identity_mapping(dev);
        if (ret) {
                u64 dma_mask = *dev->dma_mask;
@@ -3635,7 +3638,7 @@ static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
 
        BUG_ON(dir == DMA_NONE);
 
-       domain = deferred_attach_domain(dev);
+       domain = find_domain(dev);
        if (!domain)
                return DMA_MAPPING_ERROR;
 
@@ -3855,7 +3858,7 @@ static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nele
        if (!iommu_need_mapping(dev))
                return dma_direct_map_sg(dev, sglist, nelems, dir, attrs);
 
-       domain = deferred_attach_domain(dev);
+       domain = find_domain(dev);
        if (!domain)
                return 0;
 
@@ -3950,7 +3953,11 @@ bounce_map_single(struct device *dev, phys_addr_t paddr, size_t size,
        int prot = 0;
        int ret;
 
-       domain = deferred_attach_domain(dev);
+       if (unlikely(attach_deferred(dev)))
+               do_deferred_attach(dev);
+
+       domain = find_domain(dev);
+
        if (WARN_ON(dir == DMA_NONE || !domain))
                return DMA_MAPPING_ERROR;
 
@@ -6133,7 +6140,7 @@ intel_iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev)
 static bool intel_iommu_is_attach_deferred(struct iommu_domain *domain,
                                           struct device *dev)
 {
-       return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO;
+       return attach_deferred(dev);
 }
 
 static int
index 39759db..4328da0 100644 (file)
@@ -344,21 +344,19 @@ static void qcom_iommu_domain_free(struct iommu_domain *domain)
 {
        struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain);
 
-       if (WARN_ON(qcom_domain->iommu))    /* forgot to detach? */
-               return;
-
        iommu_put_dma_cookie(domain);
 
-       /* NOTE: unmap can be called after client device is powered off,
-        * for example, with GPUs or anything involving dma-buf.  So we
-        * cannot rely on the device_link.  Make sure the IOMMU is on to
-        * avoid unclocked accesses in the TLB inv path:
-        */
-       pm_runtime_get_sync(qcom_domain->iommu->dev);
-
-       free_io_pgtable_ops(qcom_domain->pgtbl_ops);
-
-       pm_runtime_put_sync(qcom_domain->iommu->dev);
+       if (qcom_domain->iommu) {
+               /*
+                * NOTE: unmap can be called after client device is powered
+                * off, for example, with GPUs or anything involving dma-buf.
+                * So we cannot rely on the device_link.  Make sure the IOMMU
+                * is on to avoid unclocked accesses in the TLB inv path:
+                */
+               pm_runtime_get_sync(qcom_domain->iommu->dev);
+               free_io_pgtable_ops(qcom_domain->pgtbl_ops);
+               pm_runtime_put_sync(qcom_domain->iommu->dev);
+       }
 
        kfree(qcom_domain);
 }
@@ -404,7 +402,7 @@ static void qcom_iommu_detach_dev(struct iommu_domain *domain, struct device *de
        struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain);
        unsigned i;
 
-       if (!qcom_domain->iommu)
+       if (WARN_ON(!qcom_domain->iommu))
                return;
 
        pm_runtime_get_sync(qcom_iommu->dev);
@@ -417,8 +415,6 @@ static void qcom_iommu_detach_dev(struct iommu_domain *domain, struct device *de
                ctx->domain = NULL;
        }
        pm_runtime_put_sync(qcom_iommu->dev);
-
-       qcom_domain->iommu = NULL;
 }
 
 static int qcom_iommu_map(struct iommu_domain *domain, unsigned long iova,
index b155e95..b680b0c 100644 (file)
@@ -598,7 +598,9 @@ int hl_device_set_debug_mode(struct hl_device *hdev, bool enable)
                        goto out;
                }
 
-               hdev->asic_funcs->halt_coresight(hdev);
+               if (!hdev->hard_reset_pending)
+                       hdev->asic_funcs->halt_coresight(hdev);
+
                hdev->in_debug = 0;
 
                goto out;
@@ -1189,6 +1191,7 @@ int hl_device_init(struct hl_device *hdev, struct class *hclass)
        if (hdev->asic_funcs->get_hw_state(hdev) == HL_DEVICE_HW_STATE_DIRTY) {
                dev_info(hdev->dev,
                        "H/W state is dirty, must reset before initializing\n");
+               hdev->asic_funcs->halt_engines(hdev, true);
                hdev->asic_funcs->hw_fini(hdev, true);
        }
 
index 7344e8a..b8a8de2 100644 (file)
@@ -895,6 +895,11 @@ void goya_init_dma_qmans(struct hl_device *hdev)
  */
 static void goya_disable_external_queues(struct hl_device *hdev)
 {
+       struct goya_device *goya = hdev->asic_specific;
+
+       if (!(goya->hw_cap_initialized & HW_CAP_DMA))
+               return;
+
        WREG32(mmDMA_QM_0_GLBL_CFG0, 0);
        WREG32(mmDMA_QM_1_GLBL_CFG0, 0);
        WREG32(mmDMA_QM_2_GLBL_CFG0, 0);
@@ -956,6 +961,11 @@ static int goya_stop_external_queues(struct hl_device *hdev)
 {
        int rc, retval = 0;
 
+       struct goya_device *goya = hdev->asic_specific;
+
+       if (!(goya->hw_cap_initialized & HW_CAP_DMA))
+               return retval;
+
        rc = goya_stop_queue(hdev,
                        mmDMA_QM_0_GLBL_CFG1,
                        mmDMA_QM_0_CP_STS,
@@ -1744,9 +1754,18 @@ void goya_init_tpc_qmans(struct hl_device *hdev)
  */
 static void goya_disable_internal_queues(struct hl_device *hdev)
 {
+       struct goya_device *goya = hdev->asic_specific;
+
+       if (!(goya->hw_cap_initialized & HW_CAP_MME))
+               goto disable_tpc;
+
        WREG32(mmMME_QM_GLBL_CFG0, 0);
        WREG32(mmMME_CMDQ_GLBL_CFG0, 0);
 
+disable_tpc:
+       if (!(goya->hw_cap_initialized & HW_CAP_TPC))
+               return;
+
        WREG32(mmTPC0_QM_GLBL_CFG0, 0);
        WREG32(mmTPC0_CMDQ_GLBL_CFG0, 0);
 
@@ -1782,8 +1801,12 @@ static void goya_disable_internal_queues(struct hl_device *hdev)
  */
 static int goya_stop_internal_queues(struct hl_device *hdev)
 {
+       struct goya_device *goya = hdev->asic_specific;
        int rc, retval = 0;
 
+       if (!(goya->hw_cap_initialized & HW_CAP_MME))
+               goto stop_tpc;
+
        /*
         * Each queue (QMAN) is a separate H/W logic. That means that each
         * QMAN can be stopped independently and failure to stop one does NOT
@@ -1810,6 +1833,10 @@ static int goya_stop_internal_queues(struct hl_device *hdev)
                retval = -EIO;
        }
 
+stop_tpc:
+       if (!(goya->hw_cap_initialized & HW_CAP_TPC))
+               return retval;
+
        rc = goya_stop_queue(hdev,
                        mmTPC0_QM_GLBL_CFG1,
                        mmTPC0_QM_CP_STS,
@@ -1975,6 +2002,11 @@ static int goya_stop_internal_queues(struct hl_device *hdev)
 
 static void goya_dma_stall(struct hl_device *hdev)
 {
+       struct goya_device *goya = hdev->asic_specific;
+
+       if (!(goya->hw_cap_initialized & HW_CAP_DMA))
+               return;
+
        WREG32(mmDMA_QM_0_GLBL_CFG1, 1 << DMA_QM_0_GLBL_CFG1_DMA_STOP_SHIFT);
        WREG32(mmDMA_QM_1_GLBL_CFG1, 1 << DMA_QM_1_GLBL_CFG1_DMA_STOP_SHIFT);
        WREG32(mmDMA_QM_2_GLBL_CFG1, 1 << DMA_QM_2_GLBL_CFG1_DMA_STOP_SHIFT);
@@ -1984,6 +2016,11 @@ static void goya_dma_stall(struct hl_device *hdev)
 
 static void goya_tpc_stall(struct hl_device *hdev)
 {
+       struct goya_device *goya = hdev->asic_specific;
+
+       if (!(goya->hw_cap_initialized & HW_CAP_TPC))
+               return;
+
        WREG32(mmTPC0_CFG_TPC_STALL, 1 << TPC0_CFG_TPC_STALL_V_SHIFT);
        WREG32(mmTPC1_CFG_TPC_STALL, 1 << TPC1_CFG_TPC_STALL_V_SHIFT);
        WREG32(mmTPC2_CFG_TPC_STALL, 1 << TPC2_CFG_TPC_STALL_V_SHIFT);
@@ -1996,6 +2033,11 @@ static void goya_tpc_stall(struct hl_device *hdev)
 
 static void goya_mme_stall(struct hl_device *hdev)
 {
+       struct goya_device *goya = hdev->asic_specific;
+
+       if (!(goya->hw_cap_initialized & HW_CAP_MME))
+               return;
+
        WREG32(mmMME_STALL, 0xFFFFFFFF);
 }
 
@@ -4648,8 +4690,6 @@ static int goya_memset_device_memory(struct hl_device *hdev, u64 addr, u64 size,
 
        rc = goya_send_job_on_qman0(hdev, job);
 
-       hl_cb_put(job->patched_cb);
-
        hl_debugfs_remove_job(hdev, job);
        kfree(job);
        cb->cs_cnt--;
index 48d5ec7..d10805e 100644 (file)
@@ -3526,6 +3526,47 @@ static void bond_fold_stats(struct rtnl_link_stats64 *_res,
        }
 }
 
+#ifdef CONFIG_LOCKDEP
+static int bond_get_lowest_level_rcu(struct net_device *dev)
+{
+       struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
+       struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
+       int cur = 0, max = 0;
+
+       now = dev;
+       iter = &dev->adj_list.lower;
+
+       while (1) {
+               next = NULL;
+               while (1) {
+                       ldev = netdev_next_lower_dev_rcu(now, &iter);
+                       if (!ldev)
+                               break;
+
+                       next = ldev;
+                       niter = &ldev->adj_list.lower;
+                       dev_stack[cur] = now;
+                       iter_stack[cur++] = iter;
+                       if (max <= cur)
+                               max = cur;
+                       break;
+               }
+
+               if (!next) {
+                       if (!cur)
+                               return max;
+                       next = dev_stack[--cur];
+                       niter = iter_stack[cur];
+               }
+
+               now = next;
+               iter = niter;
+       }
+
+       return max;
+}
+#endif
+
 static void bond_get_stats(struct net_device *bond_dev,
                           struct rtnl_link_stats64 *stats)
 {
@@ -3533,11 +3574,17 @@ static void bond_get_stats(struct net_device *bond_dev,
        struct rtnl_link_stats64 temp;
        struct list_head *iter;
        struct slave *slave;
+       int nest_level = 0;
 
-       spin_lock(&bond->stats_lock);
-       memcpy(stats, &bond->bond_stats, sizeof(*stats));
 
        rcu_read_lock();
+#ifdef CONFIG_LOCKDEP
+       nest_level = bond_get_lowest_level_rcu(bond_dev);
+#endif
+
+       spin_lock_nested(&bond->stats_lock, nest_level);
+       memcpy(stats, &bond->bond_stats, sizeof(*stats));
+
        bond_for_each_slave_rcu(bond, slave, iter) {
                const struct rtnl_link_stats64 *new =
                        dev_get_stats(slave->dev, &temp);
@@ -3547,10 +3594,10 @@ static void bond_get_stats(struct net_device *bond_dev,
                /* save off the slave stats for the next run */
                memcpy(&slave->slave_stats, new, sizeof(*new));
        }
-       rcu_read_unlock();
 
        memcpy(&bond->bond_stats, stats, sizeof(*stats));
        spin_unlock(&bond->stats_lock);
+       rcu_read_unlock();
 }
 
 static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd)
@@ -3640,6 +3687,8 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
        case BOND_RELEASE_OLD:
        case SIOCBONDRELEASE:
                res = bond_release(bond_dev, slave_dev);
+               if (!res)
+                       netdev_update_lockdep_key(slave_dev);
                break;
        case BOND_SETHWADDR_OLD:
        case SIOCBONDSETHWADDR:
index ddb3916..215c109 100644 (file)
@@ -1398,6 +1398,8 @@ static int bond_option_slaves_set(struct bonding *bond,
        case '-':
                slave_dbg(bond->dev, dev, "Releasing interface\n");
                ret = bond_release(bond->dev, dev);
+               if (!ret)
+                       netdev_update_lockdep_key(dev);
                break;
 
        default:
index 449a221..1a69286 100644 (file)
@@ -1366,6 +1366,9 @@ void b53_vlan_add(struct dsa_switch *ds, int port,
 
                b53_get_vlan_entry(dev, vid, vl);
 
+               if (vid == 0 && vid == b53_default_pvid(dev))
+                       untagged = true;
+
                vl->members |= BIT(port);
                if (untagged && !dsa_is_cpu_port(ds, port))
                        vl->untag |= BIT(port);
index a1f99be..7b55633 100644 (file)
@@ -722,6 +722,11 @@ static int aq_ethtool_set_priv_flags(struct net_device *ndev, u32 flags)
        if (flags & ~AQ_PRIV_FLAGS_MASK)
                return -EOPNOTSUPP;
 
+       if (hweight32((flags | priv_flags) & AQ_HW_LOOPBACK_MASK) > 1) {
+               netdev_info(ndev, "Can't enable more than one loopback simultaneously\n");
+               return -EINVAL;
+       }
+
        cfg->priv_flags = flags;
 
        if ((priv_flags ^ flags) & BIT(AQ_HW_LOOPBACK_DMA_NET)) {
index 6102251..03ff92b 100644 (file)
@@ -163,7 +163,7 @@ aq_check_approve_fvlan(struct aq_nic_s *aq_nic,
        }
 
        if ((aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
-           (!test_bit(be16_to_cpu(fsp->h_ext.vlan_tci),
+           (!test_bit(be16_to_cpu(fsp->h_ext.vlan_tci) & VLAN_VID_MASK,
                       aq_nic->active_vlans))) {
                netdev_err(aq_nic->ndev,
                           "ethtool: unknown vlan-id specified");
index cc70c60..251767c 100644 (file)
@@ -337,6 +337,8 @@ struct aq_fw_ops {
 
        void (*enable_ptp)(struct aq_hw_s *self, int enable);
 
+       void (*adjust_ptp)(struct aq_hw_s *self, uint64_t adj);
+
        int (*set_eee_rate)(struct aq_hw_s *self, u32 speed);
 
        int (*get_eee_rate)(struct aq_hw_s *self, u32 *rate,
index c85e3e2..e95f6a6 100644 (file)
@@ -533,8 +533,10 @@ unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb,
                                     dx_buff->len,
                                     DMA_TO_DEVICE);
 
-       if (unlikely(dma_mapping_error(aq_nic_get_dev(self), dx_buff->pa)))
+       if (unlikely(dma_mapping_error(aq_nic_get_dev(self), dx_buff->pa))) {
+               ret = 0;
                goto exit;
+       }
 
        first = dx_buff;
        dx_buff->len_pkt = skb->len;
@@ -655,10 +657,6 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb)
        if (likely(frags)) {
                err = self->aq_hw_ops->hw_ring_tx_xmit(self->aq_hw,
                                                       ring, frags);
-               if (err >= 0) {
-                       ++ring->stats.tx.packets;
-                       ring->stats.tx.bytes += skb->len;
-               }
        } else {
                err = NETDEV_TX_BUSY;
        }
index 6b27af0..78b6f32 100644 (file)
@@ -359,7 +359,8 @@ static int aq_suspend_common(struct device *dev, bool deep)
        netif_device_detach(nic->ndev);
        netif_tx_stop_all_queues(nic->ndev);
 
-       aq_nic_stop(nic);
+       if (netif_running(nic->ndev))
+               aq_nic_stop(nic);
 
        if (deep) {
                aq_nic_deinit(nic, !nic->aq_hw->aq_nic_cfg->wol);
@@ -375,7 +376,7 @@ static int atl_resume_common(struct device *dev, bool deep)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
        struct aq_nic_s *nic;
-       int ret;
+       int ret = 0;
 
        nic = pci_get_drvdata(pdev);
 
@@ -390,9 +391,11 @@ static int atl_resume_common(struct device *dev, bool deep)
                        goto err_exit;
        }
 
-       ret = aq_nic_start(nic);
-       if (ret)
-               goto err_exit;
+       if (netif_running(nic->ndev)) {
+               ret = aq_nic_start(nic);
+               if (ret)
+                       goto err_exit;
+       }
 
        netif_device_attach(nic->ndev);
        netif_tx_start_all_queues(nic->ndev);
index 951d86f..bae95a6 100644 (file)
@@ -272,9 +272,12 @@ bool aq_ring_tx_clean(struct aq_ring_s *self)
                        }
                }
 
-               if (unlikely(buff->is_eop))
-                       dev_kfree_skb_any(buff->skb);
+               if (unlikely(buff->is_eop)) {
+                       ++self->stats.rx.packets;
+                       self->stats.tx.bytes += buff->skb->len;
 
+                       dev_kfree_skb_any(buff->skb);
+               }
                buff->pa = 0U;
                buff->eop_index = 0xffffU;
                self->sw_head = aq_ring_next_dx(self, self->sw_head);
@@ -351,7 +354,8 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
                                err = 0;
                                goto err_exit;
                        }
-                       if (buff->is_error || buff->is_cso_err) {
+                       if (buff->is_error ||
+                           (buff->is_lro && buff->is_cso_err)) {
                                buff_ = buff;
                                do {
                                        next_ = buff_->next,
index 991e4d3..2c96f20 100644 (file)
@@ -78,7 +78,8 @@ struct __packed aq_ring_buff_s {
                        u32 is_cleaned:1;
                        u32 is_error:1;
                        u32 is_vlan:1;
-                       u32 rsvd3:4;
+                       u32 is_lro:1;
+                       u32 rsvd3:3;
                        u16 eop_index;
                        u16 rsvd4;
                };
index ec041f7..d20d91c 100644 (file)
@@ -823,6 +823,8 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self,
                        }
                }
 
+               buff->is_lro = !!(HW_ATL_B0_RXD_WB_STAT2_RSCCNT &
+                                 rxd_wb->status);
                if (HW_ATL_B0_RXD_WB_STAT2_EOP & rxd_wb->status) {
                        buff->len = rxd_wb->pkt_len %
                                AQ_CFG_RX_FRAME_MAX;
@@ -835,8 +837,7 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self,
                                rxd_wb->pkt_len > AQ_CFG_RX_FRAME_MAX ?
                                AQ_CFG_RX_FRAME_MAX : rxd_wb->pkt_len;
 
-                       if (HW_ATL_B0_RXD_WB_STAT2_RSCCNT &
-                               rxd_wb->status) {
+                       if (buff->is_lro) {
                                /* LRO */
                                buff->next = rxd_wb->next_desc_ptr;
                                ++ring->stats.rx.lro_packets;
@@ -884,13 +885,16 @@ static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self,
 {
        struct aq_nic_cfg_s *cfg = self->aq_nic_cfg;
        unsigned int i = 0U;
+       u32 vlan_promisc;
+       u32 l2_promisc;
 
-       hw_atl_rpfl2promiscuous_mode_en_set(self,
-                                           IS_FILTER_ENABLED(IFF_PROMISC));
+       l2_promisc = IS_FILTER_ENABLED(IFF_PROMISC) ||
+                    !!(cfg->priv_flags & BIT(AQ_HW_LOOPBACK_DMA_NET));
+       vlan_promisc = l2_promisc || cfg->is_vlan_force_promisc;
 
-       hw_atl_rpf_vlan_prom_mode_en_set(self,
-                                    IS_FILTER_ENABLED(IFF_PROMISC) ||
-                                    cfg->is_vlan_force_promisc);
+       hw_atl_rpfl2promiscuous_mode_en_set(self, l2_promisc);
+
+       hw_atl_rpf_vlan_prom_mode_en_set(self, vlan_promisc);
 
        hw_atl_rpfl2multicast_flr_en_set(self,
                                         IS_FILTER_ENABLED(IFF_ALLMULTI) &&
@@ -1161,6 +1165,8 @@ static int hw_atl_b0_adj_sys_clock(struct aq_hw_s *self, s64 delta)
 {
        self->ptp_clk_offset += delta;
 
+       self->aq_fw_ops->adjust_ptp(self, self->ptp_clk_offset);
+
        return 0;
 }
 
@@ -1211,7 +1217,7 @@ static int hw_atl_b0_gpio_pulse(struct aq_hw_s *self, u32 index,
        fwreq.ptp_gpio_ctrl.index = index;
        fwreq.ptp_gpio_ctrl.period = period;
        /* Apply time offset */
-       fwreq.ptp_gpio_ctrl.start = start - self->ptp_clk_offset;
+       fwreq.ptp_gpio_ctrl.start = start;
 
        size = sizeof(fwreq.msg_id) + sizeof(fwreq.ptp_gpio_ctrl);
        return self->aq_fw_ops->send_fw_request(self, &fwreq, size);
index f547baa..354705f 100644 (file)
@@ -22,6 +22,7 @@
 #define HW_ATL_MIF_ADDR         0x0208U
 #define HW_ATL_MIF_VAL          0x020CU
 
+#define HW_ATL_MPI_RPC_ADDR     0x0334U
 #define HW_ATL_RPC_CONTROL_ADR  0x0338U
 #define HW_ATL_RPC_STATE_ADR    0x033CU
 
@@ -53,15 +54,14 @@ enum mcp_area {
 };
 
 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
-
 static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
                                      enum hal_atl_utils_fw_state_e state);
-
 static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self);
 static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self);
 static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self);
 static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self);
 static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self);
+static u32 aq_fw1x_rpc_get(struct aq_hw_s *self);
 
 int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
 {
@@ -476,6 +476,10 @@ static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
                                        self, self->mbox_addr,
                                        self->mbox_addr != 0U,
                                        1000U, 10000U);
+       err = readx_poll_timeout_atomic(aq_fw1x_rpc_get, self,
+                                       self->rpc_addr,
+                                       self->rpc_addr != 0U,
+                                       1000U, 100000U);
 
        return err;
 }
@@ -531,6 +535,12 @@ int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
                                                self, fw.val,
                                                sw.tid == fw.tid,
                                                1000U, 100000U);
+               if (err < 0)
+                       goto err_exit;
+
+               err = aq_hw_err_from_flags(self);
+               if (err < 0)
+                       goto err_exit;
 
                if (fw.len == 0xFFFFU) {
                        err = hw_atl_utils_fw_rpc_call(self, sw.len);
@@ -1025,6 +1035,11 @@ static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self)
        return aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR);
 }
 
+static u32 aq_fw1x_rpc_get(struct aq_hw_s *self)
+{
+       return aq_hw_read_reg(self, HW_ATL_MPI_RPC_ADDR);
+}
+
 const struct aq_fw_ops aq_fw_1x_ops = {
        .init = hw_atl_utils_mpi_create,
        .deinit = hw_atl_fw1x_deinit,
index 97ebf84..77a4ed6 100644 (file)
@@ -30,6 +30,9 @@
 #define HW_ATL_FW3X_EXT_CONTROL_ADDR     0x378
 #define HW_ATL_FW3X_EXT_STATE_ADDR       0x37c
 
+#define HW_ATL_FW3X_PTP_ADJ_LSW_ADDR    0x50a0
+#define HW_ATL_FW3X_PTP_ADJ_MSW_ADDR    0x50a4
+
 #define HW_ATL_FW2X_CAP_PAUSE            BIT(CAPS_HI_PAUSE)
 #define HW_ATL_FW2X_CAP_ASYM_PAUSE       BIT(CAPS_HI_ASYMMETRIC_PAUSE)
 #define HW_ATL_FW2X_CAP_SLEEP_PROXY      BIT(CAPS_HI_SLEEP_PROXY)
@@ -475,6 +478,14 @@ static void aq_fw3x_enable_ptp(struct aq_hw_s *self, int enable)
        aq_hw_write_reg(self, HW_ATL_FW3X_EXT_CONTROL_ADDR, ptp_opts);
 }
 
+static void aq_fw3x_adjust_ptp(struct aq_hw_s *self, uint64_t adj)
+{
+       aq_hw_write_reg(self, HW_ATL_FW3X_PTP_ADJ_LSW_ADDR,
+                       (adj >>  0) & 0xffffffff);
+       aq_hw_write_reg(self, HW_ATL_FW3X_PTP_ADJ_MSW_ADDR,
+                       (adj >> 32) & 0xffffffff);
+}
+
 static int aq_fw2x_led_control(struct aq_hw_s *self, u32 mode)
 {
        if (self->fw_ver_actual < HW_ATL_FW_VER_LED)
@@ -633,4 +644,5 @@ const struct aq_fw_ops aq_fw_2x_ops = {
        .enable_ptp         = aq_fw3x_enable_ptp,
        .led_control        = aq_fw2x_led_control,
        .set_phyloopback    = aq_fw2x_set_phyloopback,
+       .adjust_ptp         = aq_fw3x_adjust_ptp,
 };
index 597e6fd..fd6e0e4 100644 (file)
@@ -11786,6 +11786,14 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (version_printed++ == 0)
                pr_info("%s", version);
 
+       /* Clear any pending DMA transactions from crash kernel
+        * while loading driver in capture kernel.
+        */
+       if (is_kdump_kernel()) {
+               pci_clear_master(pdev);
+               pcie_flr(pdev);
+       }
+
        max_irqs = bnxt_get_max_irq(pdev);
        dev = alloc_etherdev_mq(sizeof(*bp), max_irqs);
        if (!dev)
@@ -11983,10 +11991,10 @@ static void bnxt_shutdown(struct pci_dev *pdev)
                dev_close(dev);
 
        bnxt_ulp_shutdown(bp);
+       bnxt_clear_int_mode(bp);
+       pci_disable_device(pdev);
 
        if (system_state == SYSTEM_POWER_OFF) {
-               bnxt_clear_int_mode(bp);
-               pci_disable_device(pdev);
                pci_wake_from_d3(pdev, bp->wol);
                pci_set_power_state(pdev, PCI_D3hot);
        }
index b384997..99e2c6d 100644 (file)
@@ -543,13 +543,13 @@ struct l4_kwq_update_pg {
 #define L4_KWQ_UPDATE_PG_RESERVERD2_SHIFT 2
 #endif
 #if defined(__BIG_ENDIAN)
-       u16 reserverd3;
+       u16 reserved3;
        u8 da0;
        u8 da1;
 #elif defined(__LITTLE_ENDIAN)
        u8 da1;
        u8 da0;
-       u16 reserverd3;
+       u16 reserved3;
 #endif
 #if defined(__BIG_ENDIAN)
        u8 da2;
index dbf7070..a3f0f27 100644 (file)
 #define MACB_CAPS_GEM_HAS_PTP                  0x00000040
 #define MACB_CAPS_BD_RD_PREFETCH               0x00000080
 #define MACB_CAPS_NEEDS_RSTONUBR               0x00000100
+#define MACB_CAPS_MACB_IS_EMAC                 0x08000000
 #define MACB_CAPS_FIFO_MODE                    0x10000000
 #define MACB_CAPS_GIGABIT_MODE_AVAILABLE       0x20000000
 #define MACB_CAPS_SG_DISABLED                  0x40000000
index 4508f0d..2c28da1 100644 (file)
@@ -572,8 +572,21 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,
        old_ctrl = ctrl = macb_or_gem_readl(bp, NCFGR);
 
        /* Clear all the bits we might set later */
-       ctrl &= ~(GEM_BIT(GBE) | MACB_BIT(SPD) | MACB_BIT(FD) | MACB_BIT(PAE) |
-                 GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));
+       ctrl &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | MACB_BIT(PAE));
+
+       if (bp->caps & MACB_CAPS_MACB_IS_EMAC) {
+               if (state->interface == PHY_INTERFACE_MODE_RMII)
+                       ctrl |= MACB_BIT(RM9200_RMII);
+       } else {
+               ctrl &= ~(GEM_BIT(GBE) | GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL));
+
+               /* We do not support MLO_PAUSE_RX yet */
+               if (state->pause & MLO_PAUSE_TX)
+                       ctrl |= MACB_BIT(PAE);
+
+               if (state->interface == PHY_INTERFACE_MODE_SGMII)
+                       ctrl |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
+       }
 
        if (state->speed == SPEED_1000)
                ctrl |= GEM_BIT(GBE);
@@ -583,13 +596,6 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,
        if (state->duplex)
                ctrl |= MACB_BIT(FD);
 
-       /* We do not support MLO_PAUSE_RX yet */
-       if (state->pause & MLO_PAUSE_TX)
-               ctrl |= MACB_BIT(PAE);
-
-       if (state->interface == PHY_INTERFACE_MODE_SGMII)
-               ctrl |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
-
        /* Apply the new configuration, if any */
        if (old_ctrl ^ ctrl)
                macb_or_gem_writel(bp, NCFGR, ctrl);
@@ -608,9 +614,10 @@ static void macb_mac_link_down(struct phylink_config *config, unsigned int mode,
        unsigned int q;
        u32 ctrl;
 
-       for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
-               queue_writel(queue, IDR,
-                            bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
+       if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC))
+               for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
+                       queue_writel(queue, IDR,
+                                    bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
 
        /* Disable Rx and Tx */
        ctrl = macb_readl(bp, NCR) & ~(MACB_BIT(RE) | MACB_BIT(TE));
@@ -627,17 +634,19 @@ static void macb_mac_link_up(struct phylink_config *config, unsigned int mode,
        struct macb_queue *queue;
        unsigned int q;
 
-       macb_set_tx_clk(bp->tx_clk, bp->speed, ndev);
+       if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) {
+               macb_set_tx_clk(bp->tx_clk, bp->speed, ndev);
 
-       /* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
-        * cleared the pipeline and control registers.
-        */
-       bp->macbgem_ops.mog_init_rings(bp);
-       macb_init_buffers(bp);
+               /* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
+                * cleared the pipeline and control registers.
+                */
+               bp->macbgem_ops.mog_init_rings(bp);
+               macb_init_buffers(bp);
 
-       for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
-               queue_writel(queue, IER,
-                            bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
+               for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
+                       queue_writel(queue, IER,
+                                    bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
+       }
 
        /* Enable Rx and Tx */
        macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(RE) | MACB_BIT(TE));
@@ -3790,6 +3799,10 @@ static int at91ether_open(struct net_device *dev)
        u32 ctl;
        int ret;
 
+       ret = pm_runtime_get_sync(&lp->pdev->dev);
+       if (ret < 0)
+               return ret;
+
        /* Clear internal statistics */
        ctl = macb_readl(lp, NCR);
        macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT));
@@ -3854,7 +3867,7 @@ static int at91ether_close(struct net_device *dev)
                          q->rx_buffers, q->rx_buffers_dma);
        q->rx_buffers = NULL;
 
-       return 0;
+       return pm_runtime_put(&lp->pdev->dev);
 }
 
 /* Transmit packet */
@@ -4037,7 +4050,6 @@ static int at91ether_init(struct platform_device *pdev)
        struct net_device *dev = platform_get_drvdata(pdev);
        struct macb *bp = netdev_priv(dev);
        int err;
-       u32 reg;
 
        bp->queues[0].bp = bp;
 
@@ -4051,11 +4063,7 @@ static int at91ether_init(struct platform_device *pdev)
 
        macb_writel(bp, NCR, 0);
 
-       reg = MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG);
-       if (bp->phy_interface == PHY_INTERFACE_MODE_RMII)
-               reg |= MACB_BIT(RM9200_RMII);
-
-       macb_writel(bp, NCFGR, reg);
+       macb_writel(bp, NCFGR, MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG));
 
        return 0;
 }
@@ -4214,7 +4222,7 @@ static const struct macb_config sama5d4_config = {
 };
 
 static const struct macb_config emac_config = {
-       .caps = MACB_CAPS_NEEDS_RSTONUBR,
+       .caps = MACB_CAPS_NEEDS_RSTONUBR | MACB_CAPS_MACB_IS_EMAC,
        .clk_init = at91ether_clk_init,
        .init = at91ether_init,
 };
index 17a4110..8ff28ed 100644 (file)
@@ -410,10 +410,19 @@ void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable)
        lmac = &bgx->lmac[lmacid];
 
        cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
-       if (enable)
+       if (enable) {
                cfg |= CMR_PKT_RX_EN | CMR_PKT_TX_EN;
-       else
+
+               /* enable TX FIFO Underflow interrupt */
+               bgx_reg_modify(bgx, lmacid, BGX_GMP_GMI_TXX_INT_ENA_W1S,
+                              GMI_TXX_INT_UNDFLW);
+       } else {
                cfg &= ~(CMR_PKT_RX_EN | CMR_PKT_TX_EN);
+
+               /* Disable TX FIFO Underflow interrupt */
+               bgx_reg_modify(bgx, lmacid, BGX_GMP_GMI_TXX_INT_ENA_W1C,
+                              GMI_TXX_INT_UNDFLW);
+       }
        bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);
 
        if (bgx->is_rgx)
@@ -1535,6 +1544,48 @@ static int bgx_init_phy(struct bgx *bgx)
        return bgx_init_of_phy(bgx);
 }
 
+static irqreturn_t bgx_intr_handler(int irq, void *data)
+{
+       struct bgx *bgx = (struct bgx *)data;
+       u64 status, val;
+       int lmac;
+
+       for (lmac = 0; lmac < bgx->lmac_count; lmac++) {
+               status = bgx_reg_read(bgx, lmac, BGX_GMP_GMI_TXX_INT);
+               if (status & GMI_TXX_INT_UNDFLW) {
+                       pci_err(bgx->pdev, "BGX%d lmac%d UNDFLW\n",
+                               bgx->bgx_id, lmac);
+                       val = bgx_reg_read(bgx, lmac, BGX_CMRX_CFG);
+                       val &= ~CMR_EN;
+                       bgx_reg_write(bgx, lmac, BGX_CMRX_CFG, val);
+                       val |= CMR_EN;
+                       bgx_reg_write(bgx, lmac, BGX_CMRX_CFG, val);
+               }
+               /* clear interrupts */
+               bgx_reg_write(bgx, lmac, BGX_GMP_GMI_TXX_INT, status);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static void bgx_register_intr(struct pci_dev *pdev)
+{
+       struct bgx *bgx = pci_get_drvdata(pdev);
+       int ret;
+
+       ret = pci_alloc_irq_vectors(pdev, BGX_LMAC_VEC_OFFSET,
+                                   BGX_LMAC_VEC_OFFSET, PCI_IRQ_ALL_TYPES);
+       if (ret < 0) {
+               pci_err(pdev, "Req for #%d msix vectors failed\n",
+                       BGX_LMAC_VEC_OFFSET);
+               return;
+       }
+       ret = pci_request_irq(pdev, GMPX_GMI_TX_INT, bgx_intr_handler, NULL,
+                             bgx, "BGX%d", bgx->bgx_id);
+       if (ret)
+               pci_free_irq(pdev, GMPX_GMI_TX_INT, bgx);
+}
+
 static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err;
@@ -1550,7 +1601,7 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        pci_set_drvdata(pdev, bgx);
 
-       err = pci_enable_device(pdev);
+       err = pcim_enable_device(pdev);
        if (err) {
                dev_err(dev, "Failed to enable PCI device\n");
                pci_set_drvdata(pdev, NULL);
@@ -1604,6 +1655,8 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        bgx_init_hw(bgx);
 
+       bgx_register_intr(pdev);
+
        /* Enable all LMACs */
        for (lmac = 0; lmac < bgx->lmac_count; lmac++) {
                err = bgx_lmac_enable(bgx, lmac);
@@ -1620,6 +1673,7 @@ static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 err_enable:
        bgx_vnic[bgx->bgx_id] = NULL;
+       pci_free_irq(pdev, GMPX_GMI_TX_INT, bgx);
 err_release_regions:
        pci_release_regions(pdev);
 err_disable_device:
@@ -1637,6 +1691,8 @@ static void bgx_remove(struct pci_dev *pdev)
        for (lmac = 0; lmac < bgx->lmac_count; lmac++)
                bgx_lmac_disable(bgx, lmac);
 
+       pci_free_irq(pdev, GMPX_GMI_TX_INT, bgx);
+
        bgx_vnic[bgx->bgx_id] = NULL;
        pci_release_regions(pdev);
        pci_disable_device(pdev);
index 2588870..cdea493 100644 (file)
 #define BGX_GMP_GMI_TXX_BURST          0x38228
 #define BGX_GMP_GMI_TXX_MIN_PKT                0x38240
 #define BGX_GMP_GMI_TXX_SGMII_CTL      0x38300
+#define BGX_GMP_GMI_TXX_INT            0x38500
+#define BGX_GMP_GMI_TXX_INT_W1S                0x38508
+#define BGX_GMP_GMI_TXX_INT_ENA_W1C    0x38510
+#define BGX_GMP_GMI_TXX_INT_ENA_W1S    0x38518
+#define  GMI_TXX_INT_PTP_LOST                  BIT_ULL(4)
+#define  GMI_TXX_INT_LATE_COL                  BIT_ULL(3)
+#define  GMI_TXX_INT_XSDEF                     BIT_ULL(2)
+#define  GMI_TXX_INT_XSCOL                     BIT_ULL(1)
+#define  GMI_TXX_INT_UNDFLW                    BIT_ULL(0)
 
 #define BGX_MSIX_VEC_0_29_ADDR         0x400000 /* +(0..29) << 4 */
 #define BGX_MSIX_VEC_0_29_CTL          0x400008
index 1ea3372..e94ae9b 100644 (file)
@@ -1405,6 +1405,8 @@ static struct dm9000_plat_data *dm9000_parse_dt(struct device *dev)
        mac_addr = of_get_mac_address(np);
        if (!IS_ERR(mac_addr))
                ether_addr_copy(pdata->dev_addr, mac_addr);
+       else if (PTR_ERR(mac_addr) == -EPROBE_DEFER)
+               return ERR_CAST(mac_addr);
 
        return pdata;
 }
index b002ab4..77c412a 100644 (file)
@@ -2936,13 +2936,6 @@ ice_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
        else
                return -EINVAL;
 
-       /* Tell the OS link is going down, the link will go back up when fw
-        * says it is ready asynchronously
-        */
-       ice_print_link_msg(vsi, false);
-       netif_carrier_off(netdev);
-       netif_tx_stop_all_queues(netdev);
-
        /* Set the FC mode and only restart AN if link is up */
        status = ice_set_fc(pi, &aq_failures, link_up);
 
@@ -3489,21 +3482,13 @@ ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec,
                return -EINVAL;
        }
 
-       /* hardware only supports an ITR granularity of 2us */
-       if (coalesce_usecs % 2 != 0) {
-               netdev_info(vsi->netdev, "Invalid value, %s-usecs must be even\n",
-                           c_type_str);
-               return -EINVAL;
-       }
-
        if (use_adaptive_coalesce) {
                rc->itr_setting |= ICE_ITR_DYNAMIC;
        } else {
-               /* store user facing value how it was set */
+               /* save the user set usecs */
                rc->itr_setting = coalesce_usecs;
-               /* set to static and convert to value HW understands */
-               rc->target_itr =
-                       ITR_TO_REG(ITR_REG_ALIGN(rc->itr_setting));
+               /* device ITR granularity is in 2 usec increments */
+               rc->target_itr = ITR_REG_ALIGN(rc->itr_setting);
        }
 
        return 0;
@@ -3596,6 +3581,30 @@ ice_is_coalesce_param_invalid(struct net_device *netdev,
        return 0;
 }
 
+/**
+ * ice_print_if_odd_usecs - print message if user tries to set odd [tx|rx]-usecs
+ * @netdev: netdev used for print
+ * @itr_setting: previous user setting
+ * @use_adaptive_coalesce: if adaptive coalesce is enabled or being enabled
+ * @coalesce_usecs: requested value of [tx|rx]-usecs
+ * @c_type_str: either "rx" or "tx" to match user set field of [tx|rx]-usecs
+ */
+static void
+ice_print_if_odd_usecs(struct net_device *netdev, u16 itr_setting,
+                      u32 use_adaptive_coalesce, u32 coalesce_usecs,
+                      const char *c_type_str)
+{
+       if (use_adaptive_coalesce)
+               return;
+
+       itr_setting = ITR_TO_REG(itr_setting);
+
+       if (itr_setting != coalesce_usecs && (coalesce_usecs % 2))
+               netdev_info(netdev, "User set %s-usecs to %d, device only supports even values. Rounding down and attempting to set %s-usecs to %d\n",
+                           c_type_str, coalesce_usecs, c_type_str,
+                           ITR_REG_ALIGN(coalesce_usecs));
+}
+
 /**
  * __ice_set_coalesce - set ITR/INTRL values for the device
  * @netdev: pointer to the netdev associated with this query
@@ -3616,8 +3625,19 @@ __ice_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec,
                return -EINVAL;
 
        if (q_num < 0) {
+               struct ice_q_vector *q_vector = vsi->q_vectors[0];
                int v_idx;
 
+               if (q_vector) {
+                       ice_print_if_odd_usecs(netdev, q_vector->rx.itr_setting,
+                                              ec->use_adaptive_rx_coalesce,
+                                              ec->rx_coalesce_usecs, "rx");
+
+                       ice_print_if_odd_usecs(netdev, q_vector->tx.itr_setting,
+                                              ec->use_adaptive_tx_coalesce,
+                                              ec->tx_coalesce_usecs, "tx");
+               }
+
                ice_for_each_q_vector(vsi, v_idx) {
                        /* In some cases if DCB is configured the num_[rx|tx]q
                         * can be less than vsi->num_q_vectors. This check
index 14a1bf4..7ee00a1 100644 (file)
@@ -222,7 +222,7 @@ enum ice_rx_dtype {
 #define ICE_ITR_GRAN_S         1       /* ITR granularity is always 2us */
 #define ICE_ITR_GRAN_US                BIT(ICE_ITR_GRAN_S)
 #define ICE_ITR_MASK           0x1FFE  /* ITR register value alignment mask */
-#define ITR_REG_ALIGN(setting) __ALIGN_MASK(setting, ~ICE_ITR_MASK)
+#define ITR_REG_ALIGN(setting) ((setting) & ICE_ITR_MASK)
 
 #define ICE_ITR_ADAPTIVE_MIN_INC       0x0002
 #define ICE_ITR_ADAPTIVE_MIN_USECS     0x0002
index 262714d..75c70d4 100644 (file)
@@ -1873,6 +1873,48 @@ error_param:
                                     NULL, 0);
 }
 
+/**
+ * ice_wait_on_vf_reset - poll to make sure a given VF is ready after reset
+ * @vf: The VF being resseting
+ *
+ * The max poll time is about ~800ms, which is about the maximum time it takes
+ * for a VF to be reset and/or a VF driver to be removed.
+ */
+static void ice_wait_on_vf_reset(struct ice_vf *vf)
+{
+       int i;
+
+       for (i = 0; i < ICE_MAX_VF_RESET_TRIES; i++) {
+               if (test_bit(ICE_VF_STATE_INIT, vf->vf_states))
+                       break;
+               msleep(ICE_MAX_VF_RESET_SLEEP_MS);
+       }
+}
+
+/**
+ * ice_check_vf_ready_for_cfg - check if VF is ready to be configured/queried
+ * @vf: VF to check if it's ready to be configured/queried
+ *
+ * The purpose of this function is to make sure the VF is not in reset, not
+ * disabled, and initialized so it can be configured and/or queried by a host
+ * administrator.
+ */
+static int ice_check_vf_ready_for_cfg(struct ice_vf *vf)
+{
+       struct ice_pf *pf;
+
+       ice_wait_on_vf_reset(vf);
+
+       if (ice_is_vf_disabled(vf))
+               return -EINVAL;
+
+       pf = vf->pf;
+       if (ice_check_vf_init(pf, vf))
+               return -EBUSY;
+
+       return 0;
+}
+
 /**
  * ice_set_vf_spoofchk
  * @netdev: network interface device structure
@@ -1890,16 +1932,16 @@ int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena)
        enum ice_status status;
        struct device *dev;
        struct ice_vf *vf;
-       int ret = 0;
+       int ret;
 
        dev = ice_pf_to_dev(pf);
        if (ice_validate_vf_id(pf, vf_id))
                return -EINVAL;
 
        vf = &pf->vf[vf_id];
-
-       if (ice_check_vf_init(pf, vf))
-               return -EBUSY;
+       ret = ice_check_vf_ready_for_cfg(vf);
+       if (ret)
+               return ret;
 
        vf_vsi = pf->vsi[vf->lan_vsi_idx];
        if (!vf_vsi) {
@@ -2696,7 +2738,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
        struct ice_vsi *vsi;
        struct device *dev;
        struct ice_vf *vf;
-       int ret = 0;
+       int ret;
 
        dev = ice_pf_to_dev(pf);
        if (ice_validate_vf_id(pf, vf_id))
@@ -2714,13 +2756,15 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
 
        vf = &pf->vf[vf_id];
        vsi = pf->vsi[vf->lan_vsi_idx];
-       if (ice_check_vf_init(pf, vf))
-               return -EBUSY;
+
+       ret = ice_check_vf_ready_for_cfg(vf);
+       if (ret)
+               return ret;
 
        if (le16_to_cpu(vsi->info.pvid) == vlanprio) {
                /* duplicate request, so just return success */
                dev_dbg(dev, "Duplicate pvid %d request\n", vlanprio);
-               return ret;
+               return 0;
        }
 
        /* If PVID, then remove all filters on the old VLAN */
@@ -2731,7 +2775,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
        if (vlan_id || qos) {
                ret = ice_vsi_manage_pvid(vsi, vlanprio, true);
                if (ret)
-                       goto error_set_pvid;
+                       return ret;
        } else {
                ice_vsi_manage_pvid(vsi, 0, false);
                vsi->info.pvid = 0;
@@ -2744,7 +2788,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
                /* add new VLAN filter for each MAC */
                ret = ice_vsi_add_vlan(vsi, vlan_id);
                if (ret)
-                       goto error_set_pvid;
+                       return ret;
        }
 
        /* The Port VLAN needs to be saved across resets the same as the
@@ -2752,8 +2796,7 @@ ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos,
         */
        vf->port_vlan_id = le16_to_cpu(vsi->info.pvid);
 
-error_set_pvid:
-       return ret;
+       return 0;
 }
 
 /**
@@ -3236,23 +3279,6 @@ ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi)
        return 0;
 }
 
-/**
- * ice_wait_on_vf_reset
- * @vf: The VF being resseting
- *
- * Poll to make sure a given VF is ready after reset
- */
-static void ice_wait_on_vf_reset(struct ice_vf *vf)
-{
-       int i;
-
-       for (i = 0; i < ICE_MAX_VF_RESET_WAIT; i++) {
-               if (test_bit(ICE_VF_STATE_INIT, vf->vf_states))
-                       break;
-               msleep(20);
-       }
-}
-
 /**
  * ice_set_vf_mac
  * @netdev: network interface device structure
@@ -3265,29 +3291,21 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
 {
        struct ice_pf *pf = ice_netdev_to_pf(netdev);
        struct ice_vf *vf;
-       int ret = 0;
+       int ret;
 
        if (ice_validate_vf_id(pf, vf_id))
                return -EINVAL;
 
-       vf = &pf->vf[vf_id];
-       /* Don't set MAC on disabled VF */
-       if (ice_is_vf_disabled(vf))
-               return -EINVAL;
-
-       /* In case VF is in reset mode, wait until it is completed. Depending
-        * on factors like queue disabling routine, this could take ~250ms
-        */
-       ice_wait_on_vf_reset(vf);
-
-       if (ice_check_vf_init(pf, vf))
-               return -EBUSY;
-
        if (is_zero_ether_addr(mac) || is_multicast_ether_addr(mac)) {
                netdev_err(netdev, "%pM not a valid unicast address\n", mac);
                return -EINVAL;
        }
 
+       vf = &pf->vf[vf_id];
+       ret = ice_check_vf_ready_for_cfg(vf);
+       if (ret)
+               return ret;
+
        /* copy MAC into dflt_lan_addr and trigger a VF reset. The reset
         * flow will use the updated dflt_lan_addr and add a MAC filter
         * using ice_add_mac. Also set pf_set_mac to indicate that the PF has
@@ -3299,7 +3317,7 @@ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
                    vf_id, mac);
 
        ice_vc_reset_vf(vf);
-       return ret;
+       return 0;
 }
 
 /**
@@ -3314,22 +3332,15 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted)
 {
        struct ice_pf *pf = ice_netdev_to_pf(netdev);
        struct ice_vf *vf;
+       int ret;
 
        if (ice_validate_vf_id(pf, vf_id))
                return -EINVAL;
 
        vf = &pf->vf[vf_id];
-       /* Don't set Trusted Mode on disabled VF */
-       if (ice_is_vf_disabled(vf))
-               return -EINVAL;
-
-       /* In case VF is in reset mode, wait until it is completed. Depending
-        * on factors like queue disabling routine, this could take ~250ms
-        */
-       ice_wait_on_vf_reset(vf);
-
-       if (ice_check_vf_init(pf, vf))
-               return -EBUSY;
+       ret = ice_check_vf_ready_for_cfg(vf);
+       if (ret)
+               return ret;
 
        /* Check if already trusted */
        if (trusted == vf->trusted)
@@ -3355,13 +3366,15 @@ int ice_set_vf_link_state(struct net_device *netdev, int vf_id, int link_state)
 {
        struct ice_pf *pf = ice_netdev_to_pf(netdev);
        struct ice_vf *vf;
+       int ret;
 
        if (ice_validate_vf_id(pf, vf_id))
                return -EINVAL;
 
        vf = &pf->vf[vf_id];
-       if (ice_check_vf_init(pf, vf))
-               return -EBUSY;
+       ret = ice_check_vf_ready_for_cfg(vf);
+       if (ret)
+               return ret;
 
        switch (link_state) {
        case IFLA_VF_LINK_STATE_AUTO:
@@ -3397,14 +3410,15 @@ int ice_get_vf_stats(struct net_device *netdev, int vf_id,
        struct ice_eth_stats *stats;
        struct ice_vsi *vsi;
        struct ice_vf *vf;
+       int ret;
 
        if (ice_validate_vf_id(pf, vf_id))
                return -EINVAL;
 
        vf = &pf->vf[vf_id];
-
-       if (ice_check_vf_init(pf, vf))
-               return -EBUSY;
+       ret = ice_check_vf_ready_for_cfg(vf);
+       if (ret)
+               return ret;
 
        vsi = pf->vsi[vf->lan_vsi_idx];
        if (!vsi)
index 4647d63..ac67982 100644 (file)
@@ -38,7 +38,8 @@
 #define ICE_MAX_POLICY_INTR_PER_VF     33
 #define ICE_MIN_INTR_PER_VF            (ICE_MIN_QS_PER_VF + 1)
 #define ICE_DFLT_INTR_PER_VF           (ICE_DFLT_QS_PER_VF + 1)
-#define ICE_MAX_VF_RESET_WAIT          15
+#define ICE_MAX_VF_RESET_TRIES         40
+#define ICE_MAX_VF_RESET_SLEEP_MS      20
 
 #define ice_for_each_vf(pf, i) \
        for ((i) = 0; (i) < (pf)->num_alloc_vfs; (i)++)
index 3a97564..20b907d 100644 (file)
@@ -200,7 +200,7 @@ int mlx5e_health_report(struct mlx5e_priv *priv,
        netdev_err(priv->netdev, err_str);
 
        if (!reporter)
-               return err_ctx->recover(&err_ctx->ctx);
+               return err_ctx->recover(err_ctx->ctx);
 
        return devlink_health_report(reporter, err_str, err_ctx);
 }
index 7c8796d..a226277 100644 (file)
@@ -179,6 +179,14 @@ mlx5e_tx_dma_unmap(struct device *pdev, struct mlx5e_sq_dma *dma)
        }
 }
 
+static inline void mlx5e_rqwq_reset(struct mlx5e_rq *rq)
+{
+       if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ)
+               mlx5_wq_ll_reset(&rq->mpwqe.wq);
+       else
+               mlx5_wq_cyc_reset(&rq->wqe.wq);
+}
+
 /* SW parser related functions */
 
 struct mlx5e_swp_spec {
index 454d345..9669836 100644 (file)
@@ -712,6 +712,9 @@ int mlx5e_modify_rq_state(struct mlx5e_rq *rq, int curr_state, int next_state)
        if (!in)
                return -ENOMEM;
 
+       if (curr_state == MLX5_RQC_STATE_RST && next_state == MLX5_RQC_STATE_RDY)
+               mlx5e_rqwq_reset(rq);
+
        rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);
 
        MLX5_SET(modify_rq_in, in, rq_state, curr_state);
index 5acf60b..e49acd0 100644 (file)
@@ -459,12 +459,16 @@ static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
 
 static int esw_legacy_enable(struct mlx5_eswitch *esw)
 {
-       int ret;
+       struct mlx5_vport *vport;
+       int ret, i;
 
        ret = esw_create_legacy_table(esw);
        if (ret)
                return ret;
 
+       mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
+               vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
+
        ret = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_LEGACY_SRIOV_VPORT_EVENTS);
        if (ret)
                esw_destroy_legacy_table(esw);
@@ -2452,25 +2456,17 @@ out:
 
 int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
 {
-       int err = 0;
-
        if (!esw)
                return -EOPNOTSUPP;
 
        if (!ESW_ALLOWED(esw))
                return -EPERM;
 
-       mutex_lock(&esw->state_lock);
-       if (esw->mode != MLX5_ESWITCH_LEGACY) {
-               err = -EOPNOTSUPP;
-               goto out;
-       }
+       if (esw->mode != MLX5_ESWITCH_LEGACY)
+               return -EOPNOTSUPP;
 
        *setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
-
-out:
-       mutex_unlock(&esw->state_lock);
-       return err;
+       return 0;
 }
 
 int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
index 979f13b..1a57b2b 100644 (file)
@@ -1172,7 +1172,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw,
                return -EINVAL;
        }
 
-       mlx5_eswitch_disable(esw, true);
+       mlx5_eswitch_disable(esw, false);
        mlx5_eswitch_update_num_of_vfs(esw, esw->dev->priv.sriov.num_vfs);
        err = mlx5_eswitch_enable(esw, MLX5_ESWITCH_OFFLOADS);
        if (err) {
@@ -2065,7 +2065,7 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw,
 {
        int err, err1;
 
-       mlx5_eswitch_disable(esw, true);
+       mlx5_eswitch_disable(esw, false);
        err = mlx5_eswitch_enable(esw, MLX5_ESWITCH_LEGACY);
        if (err) {
                NL_SET_ERR_MSG_MOD(extack, "Failed setting eswitch to legacy");
index c5a446e..4276194 100644 (file)
@@ -35,7 +35,7 @@
 static const unsigned int ESW_POOLS[] = { 4 * 1024 * 1024,
                                          1 * 1024 * 1024,
                                          64 * 1024,
-                                         4 * 1024, };
+                                         128 };
 
 struct mlx5_esw_chains_priv {
        struct rhashtable chains_ht;
index c6c7d1d..aade62a 100644 (file)
@@ -2307,7 +2307,9 @@ static int dr_ste_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
        struct mlx5dr_cmd_vport_cap *vport_cap;
        struct mlx5dr_domain *dmn = sb->dmn;
        struct mlx5dr_cmd_caps *caps;
+       u8 *bit_mask = sb->bit_mask;
        u8 *tag = hw_ste->tag;
+       bool source_gvmi_set;
 
        DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn);
 
@@ -2328,7 +2330,8 @@ static int dr_ste_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
        if (!vport_cap)
                return -EINVAL;
 
-       if (vport_cap->vport_gvmi)
+       source_gvmi_set = MLX5_GET(ste_src_gvmi_qp, bit_mask, source_gvmi);
+       if (vport_cap->vport_gvmi && source_gvmi_set)
                MLX5_SET(ste_src_gvmi_qp, tag, source_gvmi, vport_cap->vport_gvmi);
 
        misc->source_eswitch_owner_vhca_id = 0;
index 3abfc81..c202719 100644 (file)
@@ -66,15 +66,20 @@ static int mlx5_cmd_dr_create_flow_table(struct mlx5_flow_root_namespace *ns,
                                         struct mlx5_flow_table *next_ft)
 {
        struct mlx5dr_table *tbl;
+       u32 flags;
        int err;
 
        if (mlx5_dr_is_fw_table(ft->flags))
                return mlx5_fs_cmd_get_fw_cmds()->create_flow_table(ns, ft,
                                                                    log_size,
                                                                    next_ft);
+       flags = ft->flags;
+       /* turn off encap/decap if not supported for sw-str by fw */
+       if (!MLX5_CAP_FLOWTABLE(ns->dev, sw_owner_reformat_supported))
+               flags = ft->flags & ~(MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT |
+                                     MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
 
-       tbl = mlx5dr_table_create(ns->fs_dr_domain.dr_domain,
-                                 ft->level, ft->flags);
+       tbl = mlx5dr_table_create(ns->fs_dr_domain.dr_domain, ft->level, flags);
        if (!tbl) {
                mlx5_core_err(ns->dev, "Failed creating dr flow_table\n");
                return -EINVAL;
index 02f7e4a..01f075f 100644 (file)
@@ -94,6 +94,13 @@ void mlx5_wq_cyc_wqe_dump(struct mlx5_wq_cyc *wq, u16 ix, u8 nstrides)
        print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1, wqe, len, false);
 }
 
+void mlx5_wq_cyc_reset(struct mlx5_wq_cyc *wq)
+{
+       wq->wqe_ctr = 0;
+       wq->cur_sz = 0;
+       mlx5_wq_cyc_update_db_record(wq);
+}
+
 int mlx5_wq_qp_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
                      void *qpc, struct mlx5_wq_qp *wq,
                      struct mlx5_wq_ctrl *wq_ctrl)
@@ -192,6 +199,19 @@ err_db_free:
        return err;
 }
 
+static void mlx5_wq_ll_init_list(struct mlx5_wq_ll *wq)
+{
+       struct mlx5_wqe_srq_next_seg *next_seg;
+       int i;
+
+       for (i = 0; i < wq->fbc.sz_m1; i++) {
+               next_seg = mlx5_wq_ll_get_wqe(wq, i);
+               next_seg->next_wqe_index = cpu_to_be16(i + 1);
+       }
+       next_seg = mlx5_wq_ll_get_wqe(wq, i);
+       wq->tail_next = &next_seg->next_wqe_index;
+}
+
 int mlx5_wq_ll_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
                      void *wqc, struct mlx5_wq_ll *wq,
                      struct mlx5_wq_ctrl *wq_ctrl)
@@ -199,9 +219,7 @@ int mlx5_wq_ll_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
        u8 log_wq_stride = MLX5_GET(wq, wqc, log_wq_stride);
        u8 log_wq_sz     = MLX5_GET(wq, wqc, log_wq_sz);
        struct mlx5_frag_buf_ctrl *fbc = &wq->fbc;
-       struct mlx5_wqe_srq_next_seg *next_seg;
        int err;
-       int i;
 
        err = mlx5_db_alloc_node(mdev, &wq_ctrl->db, param->db_numa_node);
        if (err) {
@@ -220,13 +238,7 @@ int mlx5_wq_ll_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
 
        mlx5_init_fbc(wq_ctrl->buf.frags, log_wq_stride, log_wq_sz, fbc);
 
-       for (i = 0; i < fbc->sz_m1; i++) {
-               next_seg = mlx5_wq_ll_get_wqe(wq, i);
-               next_seg->next_wqe_index = cpu_to_be16(i + 1);
-       }
-       next_seg = mlx5_wq_ll_get_wqe(wq, i);
-       wq->tail_next = &next_seg->next_wqe_index;
-
+       mlx5_wq_ll_init_list(wq);
        wq_ctrl->mdev = mdev;
 
        return 0;
@@ -237,6 +249,15 @@ err_db_free:
        return err;
 }
 
+void mlx5_wq_ll_reset(struct mlx5_wq_ll *wq)
+{
+       wq->head = 0;
+       wq->wqe_ctr = 0;
+       wq->cur_sz = 0;
+       mlx5_wq_ll_init_list(wq);
+       mlx5_wq_ll_update_db_record(wq);
+}
+
 void mlx5_wq_destroy(struct mlx5_wq_ctrl *wq_ctrl)
 {
        mlx5_frag_buf_free(wq_ctrl->mdev, &wq_ctrl->buf);
index d9a94bc..4cadc33 100644 (file)
@@ -80,6 +80,7 @@ int mlx5_wq_cyc_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
                       void *wqc, struct mlx5_wq_cyc *wq,
                       struct mlx5_wq_ctrl *wq_ctrl);
 void mlx5_wq_cyc_wqe_dump(struct mlx5_wq_cyc *wq, u16 ix, u8 nstrides);
+void mlx5_wq_cyc_reset(struct mlx5_wq_cyc *wq);
 
 int mlx5_wq_qp_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
                      void *qpc, struct mlx5_wq_qp *wq,
@@ -92,6 +93,7 @@ int mlx5_cqwq_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
 int mlx5_wq_ll_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
                      void *wqc, struct mlx5_wq_ll *wq,
                      struct mlx5_wq_ctrl *wq_ctrl);
+void mlx5_wq_ll_reset(struct mlx5_wq_ll *wq);
 
 void mlx5_wq_destroy(struct mlx5_wq_ctrl *wq_ctrl);
 
index a41a90c..1c9e70c 100644 (file)
@@ -156,24 +156,6 @@ static int msg_enable;
  * chip is busy transferring packet data (RX/TX FIFO accesses).
  */
 
-/**
- * ks_rdreg8 - read 8 bit register from device
- * @ks   : The chip information
- * @offset: The register address
- *
- * Read a 8bit register from the chip, returning the result
- */
-static u8 ks_rdreg8(struct ks_net *ks, int offset)
-{
-       u16 data;
-       u8 shift_bit = offset & 0x03;
-       u8 shift_data = (offset & 1) << 3;
-       ks->cmd_reg_cache = (u16) offset | (u16)(BE0 << shift_bit);
-       iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
-       data  = ioread16(ks->hw_addr);
-       return (u8)(data >> shift_data);
-}
-
 /**
  * ks_rdreg16 - read 16 bit register from device
  * @ks   : The chip information
@@ -184,27 +166,11 @@ static u8 ks_rdreg8(struct ks_net *ks, int offset)
 
 static u16 ks_rdreg16(struct ks_net *ks, int offset)
 {
-       ks->cmd_reg_cache = (u16)offset | ((BE1 | BE0) << (offset & 0x02));
+       ks->cmd_reg_cache = (u16)offset | ((BE3 | BE2) >> (offset & 0x02));
        iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
        return ioread16(ks->hw_addr);
 }
 
-/**
- * ks_wrreg8 - write 8bit register value to chip
- * @ks: The chip information
- * @offset: The register address
- * @value: The value to write
- *
- */
-static void ks_wrreg8(struct ks_net *ks, int offset, u8 value)
-{
-       u8  shift_bit = (offset & 0x03);
-       u16 value_write = (u16)(value << ((offset & 1) << 3));
-       ks->cmd_reg_cache = (u16)offset | (BE0 << shift_bit);
-       iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
-       iowrite16(value_write, ks->hw_addr);
-}
-
 /**
  * ks_wrreg16 - write 16bit register value to chip
  * @ks: The chip information
@@ -215,7 +181,7 @@ static void ks_wrreg8(struct ks_net *ks, int offset, u8 value)
 
 static void ks_wrreg16(struct ks_net *ks, int offset, u16 value)
 {
-       ks->cmd_reg_cache = (u16)offset | ((BE1 | BE0) << (offset & 0x02));
+       ks->cmd_reg_cache = (u16)offset | ((BE3 | BE2) >> (offset & 0x02));
        iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
        iowrite16(value, ks->hw_addr);
 }
@@ -231,7 +197,7 @@ static inline void ks_inblk(struct ks_net *ks, u16 *wptr, u32 len)
 {
        len >>= 1;
        while (len--)
-               *wptr++ = (u16)ioread16(ks->hw_addr);
+               *wptr++ = be16_to_cpu(ioread16(ks->hw_addr));
 }
 
 /**
@@ -245,7 +211,7 @@ static inline void ks_outblk(struct ks_net *ks, u16 *wptr, u32 len)
 {
        len >>= 1;
        while (len--)
-               iowrite16(*wptr++, ks->hw_addr);
+               iowrite16(cpu_to_be16(*wptr++), ks->hw_addr);
 }
 
 static void ks_disable_int(struct ks_net *ks)
@@ -324,8 +290,7 @@ static void ks_read_config(struct ks_net *ks)
        u16 reg_data = 0;
 
        /* Regardless of bus width, 8 bit read should always work.*/
-       reg_data = ks_rdreg8(ks, KS_CCR) & 0x00FF;
-       reg_data |= ks_rdreg8(ks, KS_CCR+1) << 8;
+       reg_data = ks_rdreg16(ks, KS_CCR);
 
        /* addr/data bus are multiplexed */
        ks->sharedbus = (reg_data & CCR_SHARED) == CCR_SHARED;
@@ -429,7 +394,7 @@ static inline void ks_read_qmu(struct ks_net *ks, u16 *buf, u32 len)
 
        /* 1. set sudo DMA mode */
        ks_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI);
-       ks_wrreg8(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff);
+       ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA);
 
        /* 2. read prepend data */
        /**
@@ -446,7 +411,7 @@ static inline void ks_read_qmu(struct ks_net *ks, u16 *buf, u32 len)
        ks_inblk(ks, buf, ALIGN(len, 4));
 
        /* 4. reset sudo DMA Mode */
-       ks_wrreg8(ks, KS_RXQCR, ks->rc_rxqcr);
+       ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
 }
 
 /**
@@ -679,13 +644,13 @@ static void ks_write_qmu(struct ks_net *ks, u8 *pdata, u16 len)
        ks->txh.txw[1] = cpu_to_le16(len);
 
        /* 1. set sudo-DMA mode */
-       ks_wrreg8(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff);
+       ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA);
        /* 2. write status/lenth info */
        ks_outblk(ks, ks->txh.txw, 4);
        /* 3. write pkt data */
        ks_outblk(ks, (u16 *)pdata, ALIGN(len, 4));
        /* 4. reset sudo-DMA mode */
-       ks_wrreg8(ks, KS_RXQCR, ks->rc_rxqcr);
+       ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
        /* 5. Enqueue Tx(move the pkt from TX buffer into TXQ) */
        ks_wrreg16(ks, KS_TXQCR, TXQCR_METFE);
        /* 6. wait until TXQCR_METFE is auto-cleared */
index b388208..1135a18 100644 (file)
@@ -114,6 +114,14 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
                if (err != 4)
                        break;
 
+               /* At this point the IFH was read correctly, so it is safe to
+                * presume that there is no error. The err needs to be reset
+                * otherwise a frame could come in CPU queue between the while
+                * condition and the check for error later on. And in that case
+                * the new frame is just removed and not processed.
+                */
+               err = 0;
+
                ocelot_parse_ifh(ifh, &info);
 
                ocelot_port = ocelot->ports[info.port];
index 87f82f3..46107de 100644 (file)
@@ -103,7 +103,7 @@ int ionic_heartbeat_check(struct ionic *ionic)
 {
        struct ionic_dev *idev = &ionic->idev;
        unsigned long hb_time;
-       u32 fw_status;
+       u8 fw_status;
        u32 hb;
 
        /* wait a little more than one second before testing again */
@@ -111,9 +111,12 @@ int ionic_heartbeat_check(struct ionic *ionic)
        if (time_before(hb_time, (idev->last_hb_time + ionic->watchdog_period)))
                return 0;
 
-       /* firmware is useful only if fw_status is non-zero */
-       fw_status = ioread32(&idev->dev_info_regs->fw_status);
-       if (!fw_status)
+       /* firmware is useful only if the running bit is set and
+        * fw_status != 0xff (bad PCI read)
+        */
+       fw_status = ioread8(&idev->dev_info_regs->fw_status);
+       if (fw_status == 0xff ||
+           !(fw_status & IONIC_FW_STS_F_RUNNING))
                return -ENXIO;
 
        /* early FW has no heartbeat, else FW will return non-zero */
index ce07c29..54547d5 100644 (file)
@@ -2445,6 +2445,7 @@ union ionic_dev_info_regs {
                u8     version;
                u8     asic_type;
                u8     asic_rev;
+#define IONIC_FW_STS_F_RUNNING 0x1
                u8     fw_status;
                u32    fw_heartbeat;
                char   fw_version[IONIC_DEVINFO_FWVERS_BUFLEN];
index e8a1b27..234c6f3 100644 (file)
@@ -163,6 +163,8 @@ struct qede_rdma_dev {
        struct list_head entry;
        struct list_head rdma_event_list;
        struct workqueue_struct *rdma_wq;
+       struct kref refcnt;
+       struct completion event_comp;
        bool exp_recovery;
 };
 
index ffabc2d..2d873ae 100644 (file)
@@ -59,6 +59,9 @@ static void _qede_rdma_dev_add(struct qede_dev *edev)
 static int qede_rdma_create_wq(struct qede_dev *edev)
 {
        INIT_LIST_HEAD(&edev->rdma_info.rdma_event_list);
+       kref_init(&edev->rdma_info.refcnt);
+       init_completion(&edev->rdma_info.event_comp);
+
        edev->rdma_info.rdma_wq = create_singlethread_workqueue("rdma_wq");
        if (!edev->rdma_info.rdma_wq) {
                DP_NOTICE(edev, "qedr: Could not create workqueue\n");
@@ -83,8 +86,23 @@ static void qede_rdma_cleanup_event(struct qede_dev *edev)
        }
 }
 
+static void qede_rdma_complete_event(struct kref *ref)
+{
+       struct qede_rdma_dev *rdma_dev =
+               container_of(ref, struct qede_rdma_dev, refcnt);
+
+       /* no more events will be added after this */
+       complete(&rdma_dev->event_comp);
+}
+
 static void qede_rdma_destroy_wq(struct qede_dev *edev)
 {
+       /* Avoid race with add_event flow, make sure it finishes before
+        * we start accessing the list and cleaning up the work
+        */
+       kref_put(&edev->rdma_info.refcnt, qede_rdma_complete_event);
+       wait_for_completion(&edev->rdma_info.event_comp);
+
        qede_rdma_cleanup_event(edev);
        destroy_workqueue(edev->rdma_info.rdma_wq);
 }
@@ -310,15 +328,24 @@ static void qede_rdma_add_event(struct qede_dev *edev,
        if (!edev->rdma_info.qedr_dev)
                return;
 
+       /* We don't want the cleanup flow to start while we're allocating and
+        * scheduling the work
+        */
+       if (!kref_get_unless_zero(&edev->rdma_info.refcnt))
+               return; /* already being destroyed */
+
        event_node = qede_rdma_get_free_event_node(edev);
        if (!event_node)
-               return;
+               goto out;
 
        event_node->event = event;
        event_node->ptr = edev;
 
        INIT_WORK(&event_node->work, qede_rdma_handle_event);
        queue_work(edev->rdma_info.rdma_wq, &event_node->work);
+
+out:
+       kref_put(&edev->rdma_info.refcnt, qede_rdma_complete_event);
 }
 
 void qede_rdma_dev_event_open(struct qede_dev *edev)
index 7d68b28..a62229a 100644 (file)
@@ -410,7 +410,7 @@ static int bcm5481_config_aneg(struct phy_device *phydev)
        struct device_node *np = phydev->mdio.dev.of_node;
        int ret;
 
-       /* Aneg firsly. */
+       /* Aneg firstly. */
        ret = genphy_config_aneg(phydev);
 
        /* Then we can set up the delay. */
@@ -463,7 +463,7 @@ static int bcm54616s_config_aneg(struct phy_device *phydev)
 {
        int ret;
 
-       /* Aneg firsly. */
+       /* Aneg firstly. */
        if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX)
                ret = genphy_c37_config_aneg(phydev);
        else
index 7e9975d..f1ded03 100644 (file)
@@ -178,6 +178,23 @@ static int iproc_mdio_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+int iproc_mdio_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct iproc_mdio_priv *priv = platform_get_drvdata(pdev);
+
+       /* restore the mii clock configuration */
+       iproc_mdio_config_clk(priv->base);
+
+       return 0;
+}
+
+static const struct dev_pm_ops iproc_mdio_pm_ops = {
+       .resume = iproc_mdio_resume
+};
+#endif /* CONFIG_PM_SLEEP */
+
 static const struct of_device_id iproc_mdio_of_match[] = {
        { .compatible = "brcm,iproc-mdio", },
        { /* sentinel */ },
@@ -188,6 +205,9 @@ static struct platform_driver iproc_mdio_driver = {
        .driver = {
                .name = "iproc-mdio",
                .of_match_table = iproc_mdio_of_match,
+#ifdef CONFIG_PM_SLEEP
+               .pm = &iproc_mdio_pm_ops,
+#endif
        },
        .probe = iproc_mdio_probe,
        .remove = iproc_mdio_remove,
index 43db442..cdc9696 100644 (file)
@@ -258,6 +258,8 @@ static void wg_setup(struct net_device *dev)
        enum { WG_NETDEV_FEATURES = NETIF_F_HW_CSUM | NETIF_F_RXCSUM |
                                    NETIF_F_SG | NETIF_F_GSO |
                                    NETIF_F_GSO_SOFTWARE | NETIF_F_HIGHDMA };
+       const int overhead = MESSAGE_MINIMUM_LENGTH + sizeof(struct udphdr) +
+                            max(sizeof(struct ipv6hdr), sizeof(struct iphdr));
 
        dev->netdev_ops = &netdev_ops;
        dev->hard_header_len = 0;
@@ -271,9 +273,8 @@ static void wg_setup(struct net_device *dev)
        dev->features |= WG_NETDEV_FEATURES;
        dev->hw_features |= WG_NETDEV_FEATURES;
        dev->hw_enc_features |= WG_NETDEV_FEATURES;
-       dev->mtu = ETH_DATA_LEN - MESSAGE_MINIMUM_LENGTH -
-                  sizeof(struct udphdr) -
-                  max(sizeof(struct ipv6hdr), sizeof(struct iphdr));
+       dev->mtu = ETH_DATA_LEN - overhead;
+       dev->max_mtu = round_down(INT_MAX, MESSAGE_PADDING_MULTIPLE) - overhead;
 
        SET_NETDEV_DEVTYPE(dev, &device_type);
 
index 9c6bab9..4a15389 100644 (file)
@@ -118,10 +118,13 @@ static void wg_receive_handshake_packet(struct wg_device *wg,
 
        under_load = skb_queue_len(&wg->incoming_handshakes) >=
                     MAX_QUEUED_INCOMING_HANDSHAKES / 8;
-       if (under_load)
+       if (under_load) {
                last_under_load = ktime_get_coarse_boottime_ns();
-       else if (last_under_load)
+       } else if (last_under_load) {
                under_load = !wg_birthdate_has_expired(last_under_load, 1);
+               if (!under_load)
+                       last_under_load = 0;
+       }
        mac_state = wg_cookie_validate_packet(&wg->cookie_checker, skb,
                                              under_load);
        if ((under_load && mac_state == VALID_MAC_WITH_COOKIE) ||
index c132605..7348c10 100644 (file)
@@ -143,16 +143,22 @@ static void keep_key_fresh(struct wg_peer *peer)
 
 static unsigned int calculate_skb_padding(struct sk_buff *skb)
 {
+       unsigned int padded_size, last_unit = skb->len;
+
+       if (unlikely(!PACKET_CB(skb)->mtu))
+               return ALIGN(last_unit, MESSAGE_PADDING_MULTIPLE) - last_unit;
+
        /* We do this modulo business with the MTU, just in case the networking
         * layer gives us a packet that's bigger than the MTU. In that case, we
         * wouldn't want the final subtraction to overflow in the case of the
-        * padded_size being clamped.
+        * padded_size being clamped. Fortunately, that's very rarely the case,
+        * so we optimize for that not happening.
         */
-       unsigned int last_unit = skb->len % PACKET_CB(skb)->mtu;
-       unsigned int padded_size = ALIGN(last_unit, MESSAGE_PADDING_MULTIPLE);
+       if (unlikely(last_unit > PACKET_CB(skb)->mtu))
+               last_unit %= PACKET_CB(skb)->mtu;
 
-       if (padded_size > PACKET_CB(skb)->mtu)
-               padded_size = PACKET_CB(skb)->mtu;
+       padded_size = min(PACKET_CB(skb)->mtu,
+                         ALIGN(last_unit, MESSAGE_PADDING_MULTIPLE));
        return padded_size - last_unit;
 }
 
index 262f3b5..b0d6541 100644 (file)
@@ -432,7 +432,6 @@ void wg_socket_reinit(struct wg_device *wg, struct sock *new4,
                wg->incoming_port = ntohs(inet_sk(new4)->inet_sport);
        mutex_unlock(&wg->socket_update_lock);
        synchronize_rcu();
-       synchronize_net();
        sock_free(old4);
        sock_free(old6);
 }
index 720c89d..4ac8cb2 100644 (file)
@@ -225,6 +225,7 @@ static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy)
 
 out:
        gpiod_set_value_cansleep(phy->gpiod_en, !phy->en_polarity);
+       usleep_range(10000, 15000);
 }
 
 static void pn544_hci_i2c_enable_mode(struct pn544_i2c_phy *phy, int run_mode)
index 2b83156..b788870 100644 (file)
@@ -682,7 +682,7 @@ static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb)
 static int pn544_hci_check_presence(struct nfc_hci_dev *hdev,
                                   struct nfc_target *target)
 {
-       pr_debug("supported protocol %d\b", target->supported_protocols);
+       pr_debug("supported protocol %d\n", target->supported_protocols);
        if (target->supported_protocols & (NFC_PROTO_ISO14443_MASK |
                                        NFC_PROTO_ISO14443_B_MASK)) {
                return nfc_hci_send_cmd(hdev, target->hci_reader_gate,
index ada59df..a4d8c90 100644 (file)
@@ -1165,8 +1165,8 @@ static int nvme_identify_ns(struct nvme_ctrl *ctrl,
 static int nvme_features(struct nvme_ctrl *dev, u8 op, unsigned int fid,
                unsigned int dword11, void *buffer, size_t buflen, u32 *result)
 {
+       union nvme_result res = { 0 };
        struct nvme_command c;
-       union nvme_result res;
        int ret;
 
        memset(&c, 0, sizeof(c));
index 797c183..a11900c 100644 (file)
@@ -715,6 +715,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
        }
 
        INIT_WORK(&ctrl->ana_work, nvme_ana_work);
+       kfree(ctrl->ana_log_buf);
        ctrl->ana_log_buf = kmalloc(ctrl->ana_log_size, GFP_KERNEL);
        if (!ctrl->ana_log_buf) {
                error = -ENOMEM;
index 9c80f9f..ace4dd9 100644 (file)
@@ -2747,6 +2747,18 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev)
                    (dmi_match(DMI_BOARD_NAME, "PRIME B350M-A") ||
                     dmi_match(DMI_BOARD_NAME, "PRIME Z370-A")))
                        return NVME_QUIRK_NO_APST;
+       } else if ((pdev->vendor == 0x144d && (pdev->device == 0xa801 ||
+                   pdev->device == 0xa808 || pdev->device == 0xa809)) ||
+                  (pdev->vendor == 0x1e0f && pdev->device == 0x0001)) {
+               /*
+                * Forcing to use host managed nvme power settings for
+                * lowest idle power with quick resume latency on
+                * Samsung and Toshiba SSDs based on suspend behavior
+                * on Coffee Lake board for LENOVO C640
+                */
+               if ((dmi_match(DMI_BOARD_VENDOR, "LENOVO")) &&
+                    dmi_match(DMI_BOARD_NAME, "LNVNB161216"))
+                       return NVME_QUIRK_SIMPLE_SUSPEND;
        }
 
        return 0;
@@ -3109,7 +3121,8 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
                                NVME_QUIRK_IGNORE_DEV_SUBNQN, },
        { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
-       { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) },
+       { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001),
+               .driver_data = NVME_QUIRK_SINGLE_VECTOR },
        { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) },
        { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2005),
                .driver_data = NVME_QUIRK_SINGLE_VECTOR |
index da642e8..4dd2eb6 100644 (file)
@@ -303,8 +303,10 @@ static void *
 cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset)
 {
        struct ccwdev_iter *iter;
+       loff_t p = *offset;
 
-       if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
+       (*offset)++;
+       if (p >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
                return NULL;
        iter = it;
        if (iter->devno == __MAX_SUBCHANNEL) {
@@ -314,7 +316,6 @@ cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset)
                        return NULL;
        } else
                iter->devno++;
-       (*offset)++;
        return iter;
 }
 
index 51038ec..dfcbe54 100644 (file)
@@ -135,7 +135,7 @@ static ssize_t chp_measurement_chars_read(struct file *filp,
        struct channel_path *chp;
        struct device *device;
 
-       device = container_of(kobj, struct device, kobj);
+       device = kobj_to_dev(kobj);
        chp = to_channelpath(device);
        if (chp->cmg == -1)
                return 0;
@@ -184,7 +184,7 @@ static ssize_t chp_measurement_read(struct file *filp, struct kobject *kobj,
        struct device *device;
        unsigned int size;
 
-       device = container_of(kobj, struct device, kobj);
+       device = kobj_to_dev(kobj);
        chp = to_channelpath(device);
        css = to_css(chp->dev.parent);
 
index 3ab8e80..e115623 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/io.h>
 #include <asm/qdio.h>
 
 #include "cio.h"
@@ -205,7 +206,7 @@ static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr,
 
        /* fill in sl */
        for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
-               q->sl->element[j].sbal = (unsigned long)q->sbal[j];
+               q->sl->element[j].sbal = virt_to_phys(q->sbal[j]);
 }
 
 static void setup_queues(struct qdio_irq *irq_ptr,
index d4caf46..2afe215 100644 (file)
@@ -887,7 +887,7 @@ static int ep11_unwrapkey(u16 card, u16 domain,
        /* empty pin tag */
        *p++ = 0x04;
        *p++ = 0;
-       /* encrytped key value tag and bytes */
+       /* encrypted key value tag and bytes */
        p += asn1tag_write(p, 0x04, enckey, enckeysize);
 
        /* reply cprb and payload */
@@ -1095,7 +1095,7 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
 
        /* Step 1: generate AES 256 bit random kek key */
        rc = ep11_genaeskey(card, domain, 256,
-                           0x00006c00, /* EN/DECRYTP, WRAP/UNWRAP */
+                           0x00006c00, /* EN/DECRYPT, WRAP/UNWRAP */
                            kek, &keklen);
        if (rc) {
                DEBUG_ERR(
index 9639938..8ca85c8 100644 (file)
@@ -1128,9 +1128,10 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
        qeth_tx_complete_buf(buf, error, budget);
 
        for (i = 0; i < queue->max_elements; ++i) {
-               if (buf->buffer->element[i].addr && buf->is_header[i])
-                       kmem_cache_free(qeth_core_header_cache,
-                               buf->buffer->element[i].addr);
+               void *data = phys_to_virt(buf->buffer->element[i].addr);
+
+               if (data && buf->is_header[i])
+                       kmem_cache_free(qeth_core_header_cache, data);
                buf->is_header[i] = 0;
        }
 
@@ -2641,7 +2642,8 @@ static int qeth_init_input_buffer(struct qeth_card *card,
        buf->pool_entry = pool_entry;
        for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
                buf->buffer->element[i].length = PAGE_SIZE;
-               buf->buffer->element[i].addr =  pool_entry->elements[i];
+               buf->buffer->element[i].addr =
+                       virt_to_phys(pool_entry->elements[i]);
                if (i == QETH_MAX_BUFFER_ELEMENTS(card) - 1)
                        buf->buffer->element[i].eflags = SBAL_EFLAGS_LAST_ENTRY;
                else
@@ -3459,9 +3461,8 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, unsigned int qdio_err,
 
                while ((e < QDIO_MAX_ELEMENTS_PER_BUFFER) &&
                       buffer->element[e].addr) {
-                       unsigned long phys_aob_addr;
+                       unsigned long phys_aob_addr = buffer->element[e].addr;
 
-                       phys_aob_addr = (unsigned long) buffer->element[e].addr;
                        qeth_qdio_handle_aob(card, phys_aob_addr);
                        ++e;
                }
@@ -3750,7 +3751,7 @@ static unsigned int __qeth_fill_buffer(struct sk_buff *skb,
                elem_length = min_t(unsigned int, length,
                                    PAGE_SIZE - offset_in_page(data));
 
-               buffer->element[element].addr = data;
+               buffer->element[element].addr = virt_to_phys(data);
                buffer->element[element].length = elem_length;
                length -= elem_length;
                if (is_first_elem) {
@@ -3780,7 +3781,7 @@ static unsigned int __qeth_fill_buffer(struct sk_buff *skb,
                        elem_length = min_t(unsigned int, length,
                                            PAGE_SIZE - offset_in_page(data));
 
-                       buffer->element[element].addr = data;
+                       buffer->element[element].addr = virt_to_phys(data);
                        buffer->element[element].length = elem_length;
                        buffer->element[element].eflags =
                                SBAL_EFLAGS_MIDDLE_FRAG;
@@ -3820,7 +3821,7 @@ static unsigned int qeth_fill_buffer(struct qeth_qdio_out_buffer *buf,
                int element = buf->next_element_to_fill;
                is_first_elem = false;
 
-               buffer->element[element].addr = hdr;
+               buffer->element[element].addr = virt_to_phys(hdr);
                buffer->element[element].length = hd_len;
                buffer->element[element].eflags = SBAL_EFLAGS_FIRST_FRAG;
                /* remember to free cache-allocated qeth_hdr: */
@@ -4746,10 +4747,10 @@ static void qeth_qdio_establish_cq(struct qeth_card *card,
        if (card->options.cq == QETH_CQ_ENABLED) {
                int offset = QDIO_MAX_BUFFERS_PER_Q *
                             (card->qdio.no_in_queues - 1);
-               for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
-                       in_sbal_ptrs[offset + i] = (struct qdio_buffer *)
-                               virt_to_phys(card->qdio.c_q->bufs[i].buffer);
-               }
+
+               for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++)
+                       in_sbal_ptrs[offset + i] =
+                               card->qdio.c_q->bufs[i].buffer;
 
                queue_start_poll[card->qdio.no_in_queues - 1] = NULL;
        }
@@ -4783,10 +4784,9 @@ static int qeth_qdio_establish(struct qeth_card *card)
                rc = -ENOMEM;
                goto out_free_qib_param;
        }
-       for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
-               in_sbal_ptrs[i] = (struct qdio_buffer *)
-                       virt_to_phys(card->qdio.in_q->bufs[i].buffer);
-       }
+
+       for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++)
+               in_sbal_ptrs[i] = card->qdio.in_q->bufs[i].buffer;
 
        queue_start_poll = kcalloc(card->qdio.no_in_queues, sizeof(void *),
                                   GFP_KERNEL);
@@ -4807,11 +4807,11 @@ static int qeth_qdio_establish(struct qeth_card *card)
                rc = -ENOMEM;
                goto out_free_queue_start_poll;
        }
+
        for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
-               for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) {
-                       out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys(
-                               card->qdio.out_qs[i]->bufs[j]->buffer);
-               }
+               for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++, k++)
+                       out_sbal_ptrs[k] =
+                               card->qdio.out_qs[i]->bufs[j]->buffer;
 
        memset(&init_data, 0, sizeof(struct qdio_initialize));
        init_data.cdev                   = CARD_DDEV(card);
@@ -5289,7 +5289,7 @@ next_packet:
                offset = 0;
        }
 
-       hdr = element->addr + offset;
+       hdr = phys_to_virt(element->addr) + offset;
        offset += sizeof(*hdr);
        skb = NULL;
 
@@ -5344,7 +5344,7 @@ next_packet:
        }
 
        use_rx_sg = (card->options.cq == QETH_CQ_ENABLED) ||
-                   ((skb_len >= card->options.rx_sg_cb) &&
+                   (skb_len > card->options.rx_sg_cb &&
                     !atomic_read(&card->force_alloc_skb) &&
                     !IS_OSN(card));
 
@@ -5388,7 +5388,7 @@ use_skb:
 walk_packet:
        while (skb_len) {
                int data_len = min(skb_len, (int)(element->length - offset));
-               char *data = element->addr + offset;
+               char *data = phys_to_virt(element->addr) + offset;
 
                skb_len -= data_len;
                offset += data_len;
@@ -5447,7 +5447,6 @@ static int qeth_extract_skbs(struct qeth_card *card, int budget,
 {
        int work_done = 0;
 
-       WARN_ON_ONCE(!budget);
        *done = false;
 
        while (budget) {
index 692bd26..9972d96 100644 (file)
@@ -1707,15 +1707,14 @@ int qeth_l2_vnicc_set_state(struct qeth_card *card, u32 vnicc, bool state)
 
        QETH_CARD_TEXT(card, 2, "vniccsch");
 
-       /* do not change anything if BridgePort is enabled */
-       if (qeth_bridgeport_is_in_use(card))
-               return -EBUSY;
-
        /* check if characteristic and enable/disable are supported */
        if (!(card->options.vnicc.sup_chars & vnicc) ||
            !(card->options.vnicc.set_char_sup & vnicc))
                return -EOPNOTSUPP;
 
+       if (qeth_bridgeport_is_in_use(card))
+               return -EBUSY;
+
        /* set enable/disable command and store wanted characteristic */
        if (state) {
                cmd = IPA_VNICC_ENABLE;
@@ -1761,14 +1760,13 @@ int qeth_l2_vnicc_get_state(struct qeth_card *card, u32 vnicc, bool *state)
 
        QETH_CARD_TEXT(card, 2, "vniccgch");
 
-       /* do not get anything if BridgePort is enabled */
-       if (qeth_bridgeport_is_in_use(card))
-               return -EBUSY;
-
        /* check if characteristic is supported */
        if (!(card->options.vnicc.sup_chars & vnicc))
                return -EOPNOTSUPP;
 
+       if (qeth_bridgeport_is_in_use(card))
+               return -EBUSY;
+
        /* if card is ready, query current VNICC state */
        if (qeth_card_hw_is_reachable(card))
                rc = qeth_l2_vnicc_query_chars(card);
@@ -1786,15 +1784,14 @@ int qeth_l2_vnicc_set_timeout(struct qeth_card *card, u32 timeout)
 
        QETH_CARD_TEXT(card, 2, "vniccsto");
 
-       /* do not change anything if BridgePort is enabled */
-       if (qeth_bridgeport_is_in_use(card))
-               return -EBUSY;
-
        /* check if characteristic and set_timeout are supported */
        if (!(card->options.vnicc.sup_chars & QETH_VNICC_LEARNING) ||
            !(card->options.vnicc.getset_timeout_sup & QETH_VNICC_LEARNING))
                return -EOPNOTSUPP;
 
+       if (qeth_bridgeport_is_in_use(card))
+               return -EBUSY;
+
        /* do we need to do anything? */
        if (card->options.vnicc.learning_timeout == timeout)
                return rc;
@@ -1823,14 +1820,14 @@ int qeth_l2_vnicc_get_timeout(struct qeth_card *card, u32 *timeout)
 
        QETH_CARD_TEXT(card, 2, "vniccgto");
 
-       /* do not get anything if BridgePort is enabled */
-       if (qeth_bridgeport_is_in_use(card))
-               return -EBUSY;
-
        /* check if characteristic and get_timeout are supported */
        if (!(card->options.vnicc.sup_chars & QETH_VNICC_LEARNING) ||
            !(card->options.vnicc.getset_timeout_sup & QETH_VNICC_LEARNING))
                return -EOPNOTSUPP;
+
+       if (qeth_bridgeport_is_in_use(card))
+               return -EBUSY;
+
        /* if card is ready, get timeout. Otherwise, just return stored value */
        *timeout = card->options.vnicc.learning_timeout;
        if (qeth_card_hw_is_reachable(card))
index 223a805..cae9b7f 100644 (file)
@@ -2510,7 +2510,7 @@ void zfcp_fsf_reqid_check(struct zfcp_qdio *qdio, int sbal_idx)
        for (idx = 0; idx < QDIO_MAX_ELEMENTS_PER_BUFFER; idx++) {
 
                sbale = &sbal->element[idx];
-               req_id = (unsigned long) sbale->addr;
+               req_id = sbale->addr;
                fsf_req = zfcp_reqlist_find_rm(adapter->req_list, req_id);
 
                if (!fsf_req) {
index 661436a..f0d6296 100644 (file)
@@ -98,7 +98,7 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
                        memset(pl, 0,
                               ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
                        sbale = qdio->res_q[idx]->element;
-                       req_id = (u64) sbale->addr;
+                       req_id = sbale->addr;
                        scount = min(sbale->scount + 1,
                                     ZFCP_QDIO_MAX_SBALS_PER_REQ + 1);
                                     /* incl. signaling SBAL */
@@ -199,7 +199,7 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
                                             q_req->sbal_number);
                        return -EINVAL;
                }
-               sbale->addr = sg_virt(sg);
+               sbale->addr = sg_phys(sg);
                sbale->length = sg->length;
        }
        return 0;
@@ -418,7 +418,7 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
                sbale->length = 0;
                sbale->eflags = SBAL_EFLAGS_LAST_ENTRY;
                sbale->sflags = 0;
-               sbale->addr = NULL;
+               sbale->addr = 0;
        }
 
        if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q))
index 2a816a3..6b43d6b 100644 (file)
@@ -122,14 +122,14 @@ void zfcp_qdio_req_init(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
                                        % QDIO_MAX_BUFFERS_PER_Q;
 
        sbale = zfcp_qdio_sbale_req(qdio, q_req);
-       sbale->addr = (void *) req_id;
+       sbale->addr = req_id;
        sbale->eflags = 0;
        sbale->sflags = SBAL_SFLAGS0_COMMAND | sbtype;
 
        if (unlikely(!data))
                return;
        sbale++;
-       sbale->addr = data;
+       sbale->addr = virt_to_phys(data);
        sbale->length = len;
 }
 
@@ -152,7 +152,7 @@ void zfcp_qdio_fill_next(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req,
        BUG_ON(q_req->sbale_curr == qdio->max_sbale_per_sbal - 1);
        q_req->sbale_curr++;
        sbale = zfcp_qdio_sbale_curr(qdio, q_req);
-       sbale->addr = data;
+       sbale->addr = virt_to_phys(data);
        sbale->length = len;
 }
 
index f3b36fd..b2ad965 100644 (file)
@@ -623,7 +623,8 @@ retry_alloc:
 
        fusion->io_request_frames =
                        dma_pool_alloc(fusion->io_request_frames_pool,
-                               GFP_KERNEL, &fusion->io_request_frames_phys);
+                               GFP_KERNEL | __GFP_NOWARN,
+                               &fusion->io_request_frames_phys);
        if (!fusion->io_request_frames) {
                if (instance->max_fw_cmds >= (MEGASAS_REDUCE_QD_COUNT * 2)) {
                        instance->max_fw_cmds -= MEGASAS_REDUCE_QD_COUNT;
@@ -661,7 +662,7 @@ retry_alloc:
 
                fusion->io_request_frames =
                        dma_pool_alloc(fusion->io_request_frames_pool,
-                                      GFP_KERNEL,
+                                      GFP_KERNEL | __GFP_NOWARN,
                                       &fusion->io_request_frames_phys);
 
                if (!fusion->io_request_frames) {
index d6d605d..8d8fd5c 100644 (file)
@@ -14,14 +14,6 @@ config ASHMEM
          It is, in theory, a good memory allocator for low-memory devices,
          because it can discard shared memory units when under memory pressure.
 
-config ANDROID_VSOC
-       tristate "Android Virtual SoC support"
-       depends on PCI_MSI
-       help
-         This option adds support for the Virtual SoC driver needed to boot
-         a 'cuttlefish' Android image inside QEmu. The driver interacts with
-         a QEmu ivshmem device. If built as a module, it will be called vsoc.
-
 source "drivers/staging/android/ion/Kconfig"
 
 endif # if ANDROID
index 14bd9c6..3b66cd0 100644 (file)
@@ -4,4 +4,3 @@ ccflags-y += -I$(src)                   # needed for trace events
 obj-y                                  += ion/
 
 obj-$(CONFIG_ASHMEM)                   += ashmem.o
-obj-$(CONFIG_ANDROID_VSOC)             += vsoc.o
index 767dd98..80eccfa 100644 (file)
@@ -9,14 +9,5 @@ ion/
  - Split /dev/ion up into multiple nodes (e.g. /dev/ion/heap0)
  - Better test framework (integration with VGEM was suggested)
 
-vsoc.c, uapi/vsoc_shm.h
- - The current driver uses the same wait queue for all of the futexes in a
-   region. This will cause false wakeups in regions with a large number of
-   waiting threads. We should eventually use multiple queues and select the
-   queue based on the region.
- - Add debugfs support for examining the permissions of regions.
- - Remove VSOC_WAIT_FOR_INCOMING_INTERRUPT ioctl. This functionality has been
-   superseded by the futex and is there for legacy reasons.
-
 Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc:
 Arve Hjønnevåg <arve@android.com> and Riley Andrews <riandrews@android.com>
index 5891d07..8044510 100644 (file)
@@ -351,8 +351,23 @@ static inline vm_flags_t calc_vm_may_flags(unsigned long prot)
               _calc_vm_trans(prot, PROT_EXEC,  VM_MAYEXEC);
 }
 
+static int ashmem_vmfile_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       /* do not allow to mmap ashmem backing shmem file directly */
+       return -EPERM;
+}
+
+static unsigned long
+ashmem_vmfile_get_unmapped_area(struct file *file, unsigned long addr,
+                               unsigned long len, unsigned long pgoff,
+                               unsigned long flags)
+{
+       return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
+}
+
 static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
 {
+       static struct file_operations vmfile_fops;
        struct ashmem_area *asma = file->private_data;
        int ret = 0;
 
@@ -393,6 +408,19 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
                }
                vmfile->f_mode |= FMODE_LSEEK;
                asma->file = vmfile;
+               /*
+                * override mmap operation of the vmfile so that it can't be
+                * remapped which would lead to creation of a new vma with no
+                * asma permission checks. Have to override get_unmapped_area
+                * as well to prevent VM_BUG_ON check for f_ops modification.
+                */
+               if (!vmfile_fops.mmap) {
+                       vmfile_fops = *vmfile->f_op;
+                       vmfile_fops.mmap = ashmem_vmfile_mmap;
+                       vmfile_fops.get_unmapped_area =
+                                       ashmem_vmfile_get_unmapped_area;
+               }
+               vmfile->f_op = &vmfile_fops;
        }
        get_file(asma->file);
 
diff --git a/drivers/staging/android/uapi/vsoc_shm.h b/drivers/staging/android/uapi/vsoc_shm.h
deleted file mode 100644 (file)
index 6291fb2..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2017 Google, Inc.
- *
- */
-
-#ifndef _UAPI_LINUX_VSOC_SHM_H
-#define _UAPI_LINUX_VSOC_SHM_H
-
-#include <linux/types.h>
-
-/**
- * A permission is a token that permits a receiver to read and/or write an area
- * of memory within a Vsoc region.
- *
- * An fd_scoped permission grants both read and write access, and can be
- * attached to a file description (see open(2)).
- * Ownership of the area can then be shared by passing a file descriptor
- * among processes.
- *
- * begin_offset and end_offset define the area of memory that is controlled by
- * the permission. owner_offset points to a word, also in shared memory, that
- * controls ownership of the area.
- *
- * ownership of the region expires when the associated file description is
- * released.
- *
- * At most one permission can be attached to each file description.
- *
- * This is useful when implementing HALs like gralloc that scope and pass
- * ownership of shared resources via file descriptors.
- *
- * The caller is responsibe for doing any fencing.
- *
- * The calling process will normally identify a currently free area of
- * memory. It will construct a proposed fd_scoped_permission_arg structure:
- *
- *   begin_offset and end_offset describe the area being claimed
- *
- *   owner_offset points to the location in shared memory that indicates the
- *   owner of the area.
- *
- *   owned_value is the value that will be stored in owner_offset iff the
- *   permission can be granted. It must be different than VSOC_REGION_FREE.
- *
- * Two fd_scoped_permission structures are compatible if they vary only by
- * their owned_value fields.
- *
- * The driver ensures that, for any group of simultaneous callers proposing
- * compatible fd_scoped_permissions, it will accept exactly one of the
- * propopsals. The other callers will get a failure with errno of EAGAIN.
- *
- * A process receiving a file descriptor can identify the region being
- * granted using the VSOC_GET_FD_SCOPED_PERMISSION ioctl.
- */
-struct fd_scoped_permission {
-       __u32 begin_offset;
-       __u32 end_offset;
-       __u32 owner_offset;
-       __u32 owned_value;
-};
-
-/*
- * This value represents a free area of memory. The driver expects to see this
- * value at owner_offset when creating a permission otherwise it will not do it,
- * and will write this value back once the permission is no longer needed.
- */
-#define VSOC_REGION_FREE ((__u32)0)
-
-/**
- * ioctl argument for VSOC_CREATE_FD_SCOPE_PERMISSION
- */
-struct fd_scoped_permission_arg {
-       struct fd_scoped_permission perm;
-       __s32 managed_region_fd;
-};
-
-#define VSOC_NODE_FREE ((__u32)0)
-
-/*
- * Describes a signal table in shared memory. Each non-zero entry in the
- * table indicates that the receiver should signal the futex at the given
- * offset. Offsets are relative to the region, not the shared memory window.
- *
- * interrupt_signalled_offset is used to reliably signal interrupts across the
- * vmm boundary. There are two roles: transmitter and receiver. For example,
- * in the host_to_guest_signal_table the host is the transmitter and the
- * guest is the receiver. The protocol is as follows:
- *
- * 1. The transmitter should convert the offset of the futex to an offset
- *    in the signal table [0, (1 << num_nodes_lg2))
- *    The transmitter can choose any appropriate hashing algorithm, including
- *    hash = futex_offset & ((1 << num_nodes_lg2) - 1)
- *
- * 3. The transmitter should atomically compare and swap futex_offset with 0
- *    at hash. There are 3 possible outcomes
- *      a. The swap fails because the futex_offset is already in the table.
- *         The transmitter should stop.
- *      b. Some other offset is in the table. This is a hash collision. The
- *         transmitter should move to another table slot and try again. One
- *         possible algorithm:
- *         hash = (hash + 1) & ((1 << num_nodes_lg2) - 1)
- *      c. The swap worked. Continue below.
- *
- * 3. The transmitter atomically swaps 1 with the value at the
- *    interrupt_signalled_offset. There are two outcomes:
- *      a. The prior value was 1. In this case an interrupt has already been
- *         posted. The transmitter is done.
- *      b. The prior value was 0, indicating that the receiver may be sleeping.
- *         The transmitter will issue an interrupt.
- *
- * 4. On waking the receiver immediately exchanges a 0 with the
- *    interrupt_signalled_offset. If it receives a 0 then this a spurious
- *    interrupt. That may occasionally happen in the current protocol, but
- *    should be rare.
- *
- * 5. The receiver scans the signal table by atomicaly exchanging 0 at each
- *    location. If a non-zero offset is returned from the exchange the
- *    receiver wakes all sleepers at the given offset:
- *      futex((int*)(region_base + old_value), FUTEX_WAKE, MAX_INT);
- *
- * 6. The receiver thread then does a conditional wait, waking immediately
- *    if the value at interrupt_signalled_offset is non-zero. This catches cases
- *    here additional  signals were posted while the table was being scanned.
- *    On the guest the wait is handled via the VSOC_WAIT_FOR_INCOMING_INTERRUPT
- *    ioctl.
- */
-struct vsoc_signal_table_layout {
-       /* log_2(Number of signal table entries) */
-       __u32 num_nodes_lg2;
-       /*
-        * Offset to the first signal table entry relative to the start of the
-        * region
-        */
-       __u32 futex_uaddr_table_offset;
-       /*
-        * Offset to an atomic_t / atomic uint32_t. A non-zero value indicates
-        * that one or more offsets are currently posted in the table.
-        * semi-unique access to an entry in the table
-        */
-       __u32 interrupt_signalled_offset;
-};
-
-#define VSOC_REGION_WHOLE ((__s32)0)
-#define VSOC_DEVICE_NAME_SZ 16
-
-/**
- * Each HAL would (usually) talk to a single device region
- * Mulitple entities care about these regions:
- * - The ivshmem_server will populate the regions in shared memory
- * - The guest kernel will read the region, create minor device nodes, and
- *   allow interested parties to register for FUTEX_WAKE events in the region
- * - HALs will access via the minor device nodes published by the guest kernel
- * - Host side processes will access the region via the ivshmem_server:
- *   1. Pass name to ivshmem_server at a UNIX socket
- *   2. ivshmemserver will reply with 2 fds:
- *     - host->guest doorbell fd
- *     - guest->host doorbell fd
- *     - fd for the shared memory region
- *     - region offset
- *   3. Start a futex receiver thread on the doorbell fd pointed at the
- *      signal_nodes
- */
-struct vsoc_device_region {
-       __u16 current_version;
-       __u16 min_compatible_version;
-       __u32 region_begin_offset;
-       __u32 region_end_offset;
-       __u32 offset_of_region_data;
-       struct vsoc_signal_table_layout guest_to_host_signal_table;
-       struct vsoc_signal_table_layout host_to_guest_signal_table;
-       /* Name of the device. Must always be terminated with a '\0', so
-        * the longest supported device name is 15 characters.
-        */
-       char device_name[VSOC_DEVICE_NAME_SZ];
-       /* There are two ways that permissions to access regions are handled:
-        *   - When subdivided_by is VSOC_REGION_WHOLE, any process that can
-        *     open the device node for the region gains complete access to it.
-        *   - When subdivided is set processes that open the region cannot
-        *     access it. Access to a sub-region must be established by invoking
-        *     the VSOC_CREATE_FD_SCOPE_PERMISSION ioctl on the region
-        *     referenced in subdivided_by, providing a fileinstance
-        *     (represented by a fd) opened on this region.
-        */
-       __u32 managed_by;
-};
-
-/*
- * The vsoc layout descriptor.
- * The first 4K should be reserved for the shm header and region descriptors.
- * The regions should be page aligned.
- */
-
-struct vsoc_shm_layout_descriptor {
-       __u16 major_version;
-       __u16 minor_version;
-
-       /* size of the shm. This may be redundant but nice to have */
-       __u32 size;
-
-       /* number of shared memory regions */
-       __u32 region_count;
-
-       /* The offset to the start of region descriptors */
-       __u32 vsoc_region_desc_offset;
-};
-
-/*
- * This specifies the current version that should be stored in
- * vsoc_shm_layout_descriptor.major_version and
- * vsoc_shm_layout_descriptor.minor_version.
- * It should be updated only if the vsoc_device_region and
- * vsoc_shm_layout_descriptor structures have changed.
- * Versioning within each region is transferred
- * via the min_compatible_version and current_version fields in
- * vsoc_device_region. The driver does not consult these fields: they are left
- * for the HALs and host processes and will change independently of the layout
- * version.
- */
-#define CURRENT_VSOC_LAYOUT_MAJOR_VERSION 2
-#define CURRENT_VSOC_LAYOUT_MINOR_VERSION 0
-
-#define VSOC_CREATE_FD_SCOPED_PERMISSION \
-       _IOW(0xF5, 0, struct fd_scoped_permission)
-#define VSOC_GET_FD_SCOPED_PERMISSION _IOR(0xF5, 1, struct fd_scoped_permission)
-
-/*
- * This is used to signal the host to scan the guest_to_host_signal_table
- * for new futexes to wake. This sends an interrupt if one is not already
- * in flight.
- */
-#define VSOC_MAYBE_SEND_INTERRUPT_TO_HOST _IO(0xF5, 2)
-
-/*
- * When this returns the guest will scan host_to_guest_signal_table to
- * check for new futexes to wake.
- */
-/* TODO(ghartman): Consider moving this to the bottom half */
-#define VSOC_WAIT_FOR_INCOMING_INTERRUPT _IO(0xF5, 3)
-
-/*
- * Guest HALs will use this to retrieve the region description after
- * opening their device node.
- */
-#define VSOC_DESCRIBE_REGION _IOR(0xF5, 4, struct vsoc_device_region)
-
-/*
- * Wake any threads that may be waiting for a host interrupt on this region.
- * This is mostly used during shutdown.
- */
-#define VSOC_SELF_INTERRUPT _IO(0xF5, 5)
-
-/*
- * This is used to signal the host to scan the guest_to_host_signal_table
- * for new futexes to wake. This sends an interrupt unconditionally.
- */
-#define VSOC_SEND_INTERRUPT_TO_HOST _IO(0xF5, 6)
-
-enum wait_types {
-       VSOC_WAIT_UNDEFINED = 0,
-       VSOC_WAIT_IF_EQUAL = 1,
-       VSOC_WAIT_IF_EQUAL_TIMEOUT = 2
-};
-
-/*
- * Wait for a condition to be true
- *
- * Note, this is sized and aligned so the 32 bit and 64 bit layouts are
- * identical.
- */
-struct vsoc_cond_wait {
-       /* Input: Offset of the 32 bit word to check */
-       __u32 offset;
-       /* Input: Value that will be compared with the offset */
-       __u32 value;
-       /* Monotonic time to wake at in seconds */
-       __u64 wake_time_sec;
-       /* Input: Monotonic time to wait in nanoseconds */
-       __u32 wake_time_nsec;
-       /* Input: Type of wait */
-       __u32 wait_type;
-       /* Output: Number of times the thread woke before returning. */
-       __u32 wakes;
-       /* Ensure that we're 8-byte aligned and 8 byte length for 32/64 bit
-        * compatibility.
-        */
-       __u32 reserved_1;
-};
-
-#define VSOC_COND_WAIT _IOWR(0xF5, 7, struct vsoc_cond_wait)
-
-/* Wake any local threads waiting at the offset given in arg */
-#define VSOC_COND_WAKE _IO(0xF5, 8)
-
-#endif /* _UAPI_LINUX_VSOC_SHM_H */
diff --git a/drivers/staging/android/vsoc.c b/drivers/staging/android/vsoc.c
deleted file mode 100644 (file)
index 1240bb0..0000000
+++ /dev/null
@@ -1,1149 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * drivers/android/staging/vsoc.c
- *
- * Android Virtual System on a Chip (VSoC) driver
- *
- * Copyright (C) 2017 Google, Inc.
- *
- * Author: ghartman@google.com
- *
- * Based on drivers/char/kvm_ivshmem.c - driver for KVM Inter-VM shared memory
- *         Copyright 2009 Cam Macdonell <cam@cs.ualberta.ca>
- *
- * Based on cirrusfb.c and 8139cp.c:
- *   Copyright 1999-2001 Jeff Garzik
- *   Copyright 2001-2004 Jeff Garzik
- */
-
-#include <linux/dma-mapping.h>
-#include <linux/freezer.h>
-#include <linux/futex.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include <linux/sched.h>
-#include <linux/syscalls.h>
-#include <linux/uaccess.h>
-#include <linux/interrupt.h>
-#include <linux/cdev.h>
-#include <linux/file.h>
-#include "uapi/vsoc_shm.h"
-
-#define VSOC_DEV_NAME "vsoc"
-
-/*
- * Description of the ivshmem-doorbell PCI device used by QEmu. These
- * constants follow docs/specs/ivshmem-spec.txt, which can be found in
- * the QEmu repository. This was last reconciled with the version that
- * came out with 2.8
- */
-
-/*
- * These constants are determined KVM Inter-VM shared memory device
- * register offsets
- */
-enum {
-       INTR_MASK = 0x00,       /* Interrupt Mask */
-       INTR_STATUS = 0x04,     /* Interrupt Status */
-       IV_POSITION = 0x08,     /* VM ID */
-       DOORBELL = 0x0c,        /* Doorbell */
-};
-
-static const int REGISTER_BAR;  /* Equal to 0 */
-static const int MAX_REGISTER_BAR_LEN = 0x100;
-/*
- * The MSI-x BAR is not used directly.
- *
- * static const int MSI_X_BAR = 1;
- */
-static const int SHARED_MEMORY_BAR = 2;
-
-struct vsoc_region_data {
-       char name[VSOC_DEVICE_NAME_SZ + 1];
-       wait_queue_head_t interrupt_wait_queue;
-       /* TODO(b/73664181): Use multiple futex wait queues */
-       wait_queue_head_t futex_wait_queue;
-       /* Flag indicating that an interrupt has been signalled by the host. */
-       atomic_t *incoming_signalled;
-       /* Flag indicating the guest has signalled the host. */
-       atomic_t *outgoing_signalled;
-       bool irq_requested;
-       bool device_created;
-};
-
-struct vsoc_device {
-       /* Kernel virtual address of REGISTER_BAR. */
-       void __iomem *regs;
-       /* Physical address of SHARED_MEMORY_BAR. */
-       phys_addr_t shm_phys_start;
-       /* Kernel virtual address of SHARED_MEMORY_BAR. */
-       void __iomem *kernel_mapped_shm;
-       /* Size of the entire shared memory window in bytes. */
-       size_t shm_size;
-       /*
-        * Pointer to the virtual address of the shared memory layout structure.
-        * This is probably identical to kernel_mapped_shm, but saving this
-        * here saves a lot of annoying casts.
-        */
-       struct vsoc_shm_layout_descriptor *layout;
-       /*
-        * Points to a table of region descriptors in the kernel's virtual
-        * address space. Calculated from
-        * vsoc_shm_layout_descriptor.vsoc_region_desc_offset
-        */
-       struct vsoc_device_region *regions;
-       /* Head of a list of permissions that have been granted. */
-       struct list_head permissions;
-       struct pci_dev *dev;
-       /* Per-region (and therefore per-interrupt) information. */
-       struct vsoc_region_data *regions_data;
-       /*
-        * Table of msi-x entries. This has to be separated from struct
-        * vsoc_region_data because the kernel deals with them as an array.
-        */
-       struct msix_entry *msix_entries;
-       /* Mutex that protectes the permission list */
-       struct mutex mtx;
-       /* Major number assigned by the kernel */
-       int major;
-       /* Character device assigned by the kernel */
-       struct cdev cdev;
-       /* Device class assigned by the kernel */
-       struct class *class;
-       /*
-        * Flags that indicate what we've initialized. These are used to do an
-        * orderly cleanup of the device.
-        */
-       bool enabled_device;
-       bool requested_regions;
-       bool cdev_added;
-       bool class_added;
-       bool msix_enabled;
-};
-
-static struct vsoc_device vsoc_dev;
-
-/*
- * TODO(ghartman): Add a /sys filesystem entry that summarizes the permissions.
- */
-
-struct fd_scoped_permission_node {
-       struct fd_scoped_permission permission;
-       struct list_head list;
-};
-
-struct vsoc_private_data {
-       struct fd_scoped_permission_node *fd_scoped_permission_node;
-};
-
-static long vsoc_ioctl(struct file *, unsigned int, unsigned long);
-static int vsoc_mmap(struct file *, struct vm_area_struct *);
-static int vsoc_open(struct inode *, struct file *);
-static int vsoc_release(struct inode *, struct file *);
-static ssize_t vsoc_read(struct file *, char __user *, size_t, loff_t *);
-static ssize_t vsoc_write(struct file *, const char __user *, size_t, loff_t *);
-static loff_t vsoc_lseek(struct file *filp, loff_t offset, int origin);
-static int
-do_create_fd_scoped_permission(struct vsoc_device_region *region_p,
-                              struct fd_scoped_permission_node *np,
-                              struct fd_scoped_permission_arg __user *arg);
-static void
-do_destroy_fd_scoped_permission(struct vsoc_device_region *owner_region_p,
-                               struct fd_scoped_permission *perm);
-static long do_vsoc_describe_region(struct file *,
-                                   struct vsoc_device_region __user *);
-static ssize_t vsoc_get_area(struct file *filp, __u32 *perm_off);
-
-/**
- * Validate arguments on entry points to the driver.
- */
-inline int vsoc_validate_inode(struct inode *inode)
-{
-       if (iminor(inode) >= vsoc_dev.layout->region_count) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "describe_region: invalid region %d\n", iminor(inode));
-               return -ENODEV;
-       }
-       return 0;
-}
-
-inline int vsoc_validate_filep(struct file *filp)
-{
-       int ret = vsoc_validate_inode(file_inode(filp));
-
-       if (ret)
-               return ret;
-       if (!filp->private_data) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "No private data on fd, region %d\n",
-                       iminor(file_inode(filp)));
-               return -EBADFD;
-       }
-       return 0;
-}
-
-/* Converts from shared memory offset to virtual address */
-static inline void *shm_off_to_virtual_addr(__u32 offset)
-{
-       return (void __force *)vsoc_dev.kernel_mapped_shm + offset;
-}
-
-/* Converts from shared memory offset to physical address */
-static inline phys_addr_t shm_off_to_phys_addr(__u32 offset)
-{
-       return vsoc_dev.shm_phys_start + offset;
-}
-
-/**
- * Convenience functions to obtain the region from the inode or file.
- * Dangerous to call before validating the inode/file.
- */
-static
-inline struct vsoc_device_region *vsoc_region_from_inode(struct inode *inode)
-{
-       return &vsoc_dev.regions[iminor(inode)];
-}
-
-static
-inline struct vsoc_device_region *vsoc_region_from_filep(struct file *inode)
-{
-       return vsoc_region_from_inode(file_inode(inode));
-}
-
-static inline uint32_t vsoc_device_region_size(struct vsoc_device_region *r)
-{
-       return r->region_end_offset - r->region_begin_offset;
-}
-
-static const struct file_operations vsoc_ops = {
-       .owner = THIS_MODULE,
-       .open = vsoc_open,
-       .mmap = vsoc_mmap,
-       .read = vsoc_read,
-       .unlocked_ioctl = vsoc_ioctl,
-       .compat_ioctl = vsoc_ioctl,
-       .write = vsoc_write,
-       .llseek = vsoc_lseek,
-       .release = vsoc_release,
-};
-
-static struct pci_device_id vsoc_id_table[] = {
-       {0x1af4, 0x1110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       {0},
-};
-
-MODULE_DEVICE_TABLE(pci, vsoc_id_table);
-
-static void vsoc_remove_device(struct pci_dev *pdev);
-static int vsoc_probe_device(struct pci_dev *pdev,
-                            const struct pci_device_id *ent);
-
-static struct pci_driver vsoc_pci_driver = {
-       .name = "vsoc",
-       .id_table = vsoc_id_table,
-       .probe = vsoc_probe_device,
-       .remove = vsoc_remove_device,
-};
-
-static int
-do_create_fd_scoped_permission(struct vsoc_device_region *region_p,
-                              struct fd_scoped_permission_node *np,
-                              struct fd_scoped_permission_arg __user *arg)
-{
-       struct file *managed_filp;
-       s32 managed_fd;
-       atomic_t *owner_ptr = NULL;
-       struct vsoc_device_region *managed_region_p;
-
-       if (copy_from_user(&np->permission,
-                          &arg->perm, sizeof(np->permission)) ||
-           copy_from_user(&managed_fd,
-                          &arg->managed_region_fd, sizeof(managed_fd))) {
-               return -EFAULT;
-       }
-       managed_filp = fdget(managed_fd).file;
-       /* Check that it's a valid fd, */
-       if (!managed_filp || vsoc_validate_filep(managed_filp))
-               return -EPERM;
-       /* EEXIST if the given fd already has a permission. */
-       if (((struct vsoc_private_data *)managed_filp->private_data)->
-           fd_scoped_permission_node)
-               return -EEXIST;
-       managed_region_p = vsoc_region_from_filep(managed_filp);
-       /* Check that the provided region is managed by this one */
-       if (&vsoc_dev.regions[managed_region_p->managed_by] != region_p)
-               return -EPERM;
-       /* The area must be well formed and have non-zero size */
-       if (np->permission.begin_offset >= np->permission.end_offset)
-               return -EINVAL;
-       /* The area must fit in the memory window */
-       if (np->permission.end_offset >
-           vsoc_device_region_size(managed_region_p))
-               return -ERANGE;
-       /* The area must be in the region data section */
-       if (np->permission.begin_offset <
-           managed_region_p->offset_of_region_data)
-               return -ERANGE;
-       /* The area must be page aligned */
-       if (!PAGE_ALIGNED(np->permission.begin_offset) ||
-           !PAGE_ALIGNED(np->permission.end_offset))
-               return -EINVAL;
-       /* Owner offset must be naturally aligned in the window */
-       if (np->permission.owner_offset &
-           (sizeof(np->permission.owner_offset) - 1))
-               return -EINVAL;
-       /* The owner flag must reside in the owner memory */
-       if (np->permission.owner_offset + sizeof(np->permission.owner_offset) >
-           vsoc_device_region_size(region_p))
-               return -ERANGE;
-       /* The owner flag must reside in the data section */
-       if (np->permission.owner_offset < region_p->offset_of_region_data)
-               return -EINVAL;
-       /* The owner value must change to claim the memory */
-       if (np->permission.owned_value == VSOC_REGION_FREE)
-               return -EINVAL;
-       owner_ptr =
-           (atomic_t *)shm_off_to_virtual_addr(region_p->region_begin_offset +
-                                               np->permission.owner_offset);
-       /* We've already verified that this is in the shared memory window, so
-        * it should be safe to write to this address.
-        */
-       if (atomic_cmpxchg(owner_ptr,
-                          VSOC_REGION_FREE,
-                          np->permission.owned_value) != VSOC_REGION_FREE) {
-               return -EBUSY;
-       }
-       ((struct vsoc_private_data *)managed_filp->private_data)->
-           fd_scoped_permission_node = np;
-       /* The file offset needs to be adjusted if the calling
-        * process did any read/write operations on the fd
-        * before creating the permission.
-        */
-       if (managed_filp->f_pos) {
-               if (managed_filp->f_pos > np->permission.end_offset) {
-                       /* If the offset is beyond the permission end, set it
-                        * to the end.
-                        */
-                       managed_filp->f_pos = np->permission.end_offset;
-               } else {
-                       /* If the offset is within the permission interval
-                        * keep it there otherwise reset it to zero.
-                        */
-                       if (managed_filp->f_pos < np->permission.begin_offset) {
-                               managed_filp->f_pos = 0;
-                       } else {
-                               managed_filp->f_pos -=
-                                   np->permission.begin_offset;
-                       }
-               }
-       }
-       return 0;
-}
-
-static void
-do_destroy_fd_scoped_permission_node(struct vsoc_device_region *owner_region_p,
-                                    struct fd_scoped_permission_node *node)
-{
-       if (node) {
-               do_destroy_fd_scoped_permission(owner_region_p,
-                                               &node->permission);
-               mutex_lock(&vsoc_dev.mtx);
-               list_del(&node->list);
-               mutex_unlock(&vsoc_dev.mtx);
-               kfree(node);
-       }
-}
-
-static void
-do_destroy_fd_scoped_permission(struct vsoc_device_region *owner_region_p,
-                               struct fd_scoped_permission *perm)
-{
-       atomic_t *owner_ptr = NULL;
-       int prev = 0;
-
-       if (!perm)
-               return;
-       owner_ptr = (atomic_t *)shm_off_to_virtual_addr
-               (owner_region_p->region_begin_offset + perm->owner_offset);
-       prev = atomic_xchg(owner_ptr, VSOC_REGION_FREE);
-       if (prev != perm->owned_value)
-               dev_err(&vsoc_dev.dev->dev,
-                       "%x-%x: owner (%s) %x: expected to be %x was %x",
-                       perm->begin_offset, perm->end_offset,
-                       owner_region_p->device_name, perm->owner_offset,
-                       perm->owned_value, prev);
-}
-
-static long do_vsoc_describe_region(struct file *filp,
-                                   struct vsoc_device_region __user *dest)
-{
-       struct vsoc_device_region *region_p;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       region_p = vsoc_region_from_filep(filp);
-       if (copy_to_user(dest, region_p, sizeof(*region_p)))
-               return -EFAULT;
-       return 0;
-}
-
-/**
- * Implements the inner logic of cond_wait. Copies to and from userspace are
- * done in the helper function below.
- */
-static int handle_vsoc_cond_wait(struct file *filp, struct vsoc_cond_wait *arg)
-{
-       DEFINE_WAIT(wait);
-       u32 region_number = iminor(file_inode(filp));
-       struct vsoc_region_data *data = vsoc_dev.regions_data + region_number;
-       struct hrtimer_sleeper timeout, *to = NULL;
-       int ret = 0;
-       struct vsoc_device_region *region_p = vsoc_region_from_filep(filp);
-       atomic_t *address = NULL;
-       ktime_t wake_time;
-
-       /* Ensure that the offset is aligned */
-       if (arg->offset & (sizeof(uint32_t) - 1))
-               return -EADDRNOTAVAIL;
-       /* Ensure that the offset is within shared memory */
-       if (((uint64_t)arg->offset) + region_p->region_begin_offset +
-           sizeof(uint32_t) > region_p->region_end_offset)
-               return -E2BIG;
-       address = shm_off_to_virtual_addr(region_p->region_begin_offset +
-                                         arg->offset);
-
-       /* Ensure that the type of wait is valid */
-       switch (arg->wait_type) {
-       case VSOC_WAIT_IF_EQUAL:
-               break;
-       case VSOC_WAIT_IF_EQUAL_TIMEOUT:
-               to = &timeout;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (to) {
-               /* Copy the user-supplied timesec into the kernel structure.
-                * We do things this way to flatten differences between 32 bit
-                * and 64 bit timespecs.
-                */
-               if (arg->wake_time_nsec >= NSEC_PER_SEC)
-                       return -EINVAL;
-               wake_time = ktime_set(arg->wake_time_sec, arg->wake_time_nsec);
-
-               hrtimer_init_sleeper_on_stack(to, CLOCK_MONOTONIC,
-                                             HRTIMER_MODE_ABS);
-               hrtimer_set_expires_range_ns(&to->timer, wake_time,
-                                            current->timer_slack_ns);
-       }
-
-       while (1) {
-               prepare_to_wait(&data->futex_wait_queue, &wait,
-                               TASK_INTERRUPTIBLE);
-               /*
-                * Check the sentinel value after prepare_to_wait. If the value
-                * changes after this check the writer will call signal,
-                * changing the task state from INTERRUPTIBLE to RUNNING. That
-                * will ensure that schedule() will eventually schedule this
-                * task.
-                */
-               if (atomic_read(address) != arg->value) {
-                       ret = 0;
-                       break;
-               }
-               if (to) {
-                       hrtimer_sleeper_start_expires(to, HRTIMER_MODE_ABS);
-                       if (likely(to->task))
-                               freezable_schedule();
-                       hrtimer_cancel(&to->timer);
-                       if (!to->task) {
-                               ret = -ETIMEDOUT;
-                               break;
-                       }
-               } else {
-                       freezable_schedule();
-               }
-               /* Count the number of times that we woke up. This is useful
-                * for unit testing.
-                */
-               ++arg->wakes;
-               if (signal_pending(current)) {
-                       ret = -EINTR;
-                       break;
-               }
-       }
-       finish_wait(&data->futex_wait_queue, &wait);
-       if (to)
-               destroy_hrtimer_on_stack(&to->timer);
-       return ret;
-}
-
-/**
- * Handles the details of copying from/to userspace to ensure that the copies
- * happen on all of the return paths of cond_wait.
- */
-static int do_vsoc_cond_wait(struct file *filp,
-                            struct vsoc_cond_wait __user *untrusted_in)
-{
-       struct vsoc_cond_wait arg;
-       int rval = 0;
-
-       if (copy_from_user(&arg, untrusted_in, sizeof(arg)))
-               return -EFAULT;
-       /* wakes is an out parameter. Initialize it to something sensible. */
-       arg.wakes = 0;
-       rval = handle_vsoc_cond_wait(filp, &arg);
-       if (copy_to_user(untrusted_in, &arg, sizeof(arg)))
-               return -EFAULT;
-       return rval;
-}
-
-static int do_vsoc_cond_wake(struct file *filp, uint32_t offset)
-{
-       struct vsoc_device_region *region_p = vsoc_region_from_filep(filp);
-       u32 region_number = iminor(file_inode(filp));
-       struct vsoc_region_data *data = vsoc_dev.regions_data + region_number;
-       /* Ensure that the offset is aligned */
-       if (offset & (sizeof(uint32_t) - 1))
-               return -EADDRNOTAVAIL;
-       /* Ensure that the offset is within shared memory */
-       if (((uint64_t)offset) + region_p->region_begin_offset +
-           sizeof(uint32_t) > region_p->region_end_offset)
-               return -E2BIG;
-       /*
-        * TODO(b/73664181): Use multiple futex wait queues.
-        * We need to wake every sleeper when the condition changes. Typically
-        * only a single thread will be waiting on the condition, but there
-        * are exceptions. The worst case is about 10 threads.
-        */
-       wake_up_interruptible_all(&data->futex_wait_queue);
-       return 0;
-}
-
-static long vsoc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-       int rv = 0;
-       struct vsoc_device_region *region_p;
-       u32 reg_num;
-       struct vsoc_region_data *reg_data;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       region_p = vsoc_region_from_filep(filp);
-       reg_num = iminor(file_inode(filp));
-       reg_data = vsoc_dev.regions_data + reg_num;
-       switch (cmd) {
-       case VSOC_CREATE_FD_SCOPED_PERMISSION:
-               {
-                       struct fd_scoped_permission_node *node = NULL;
-
-                       node = kzalloc(sizeof(*node), GFP_KERNEL);
-                       /* We can't allocate memory for the permission */
-                       if (!node)
-                               return -ENOMEM;
-                       INIT_LIST_HEAD(&node->list);
-                       rv = do_create_fd_scoped_permission
-                               (region_p,
-                                node,
-                                (struct fd_scoped_permission_arg __user *)arg);
-                       if (!rv) {
-                               mutex_lock(&vsoc_dev.mtx);
-                               list_add(&node->list, &vsoc_dev.permissions);
-                               mutex_unlock(&vsoc_dev.mtx);
-                       } else {
-                               kfree(node);
-                               return rv;
-                       }
-               }
-               break;
-
-       case VSOC_GET_FD_SCOPED_PERMISSION:
-               {
-                       struct fd_scoped_permission_node *node =
-                           ((struct vsoc_private_data *)filp->private_data)->
-                           fd_scoped_permission_node;
-                       if (!node)
-                               return -ENOENT;
-                       if (copy_to_user
-                           ((struct fd_scoped_permission __user *)arg,
-                            &node->permission, sizeof(node->permission)))
-                               return -EFAULT;
-               }
-               break;
-
-       case VSOC_MAYBE_SEND_INTERRUPT_TO_HOST:
-               if (!atomic_xchg(reg_data->outgoing_signalled, 1)) {
-                       writel(reg_num, vsoc_dev.regs + DOORBELL);
-                       return 0;
-               } else {
-                       return -EBUSY;
-               }
-               break;
-
-       case VSOC_SEND_INTERRUPT_TO_HOST:
-               writel(reg_num, vsoc_dev.regs + DOORBELL);
-               return 0;
-       case VSOC_WAIT_FOR_INCOMING_INTERRUPT:
-               wait_event_interruptible
-                       (reg_data->interrupt_wait_queue,
-                        (atomic_read(reg_data->incoming_signalled) != 0));
-               break;
-
-       case VSOC_DESCRIBE_REGION:
-               return do_vsoc_describe_region
-                       (filp,
-                        (struct vsoc_device_region __user *)arg);
-
-       case VSOC_SELF_INTERRUPT:
-               atomic_set(reg_data->incoming_signalled, 1);
-               wake_up_interruptible(&reg_data->interrupt_wait_queue);
-               break;
-
-       case VSOC_COND_WAIT:
-               return do_vsoc_cond_wait(filp,
-                                        (struct vsoc_cond_wait __user *)arg);
-       case VSOC_COND_WAKE:
-               return do_vsoc_cond_wake(filp, arg);
-
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static ssize_t vsoc_read(struct file *filp, char __user *buffer, size_t len,
-                        loff_t *poffset)
-{
-       __u32 area_off;
-       const void *area_p;
-       ssize_t area_len;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       area_len = vsoc_get_area(filp, &area_off);
-       area_p = shm_off_to_virtual_addr(area_off);
-       area_p += *poffset;
-       area_len -= *poffset;
-       if (area_len <= 0)
-               return 0;
-       if (area_len < len)
-               len = area_len;
-       if (copy_to_user(buffer, area_p, len))
-               return -EFAULT;
-       *poffset += len;
-       return len;
-}
-
-static loff_t vsoc_lseek(struct file *filp, loff_t offset, int origin)
-{
-       ssize_t area_len = 0;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       area_len = vsoc_get_area(filp, NULL);
-       switch (origin) {
-       case SEEK_SET:
-               break;
-
-       case SEEK_CUR:
-               if (offset > 0 && offset + filp->f_pos < 0)
-                       return -EOVERFLOW;
-               offset += filp->f_pos;
-               break;
-
-       case SEEK_END:
-               if (offset > 0 && offset + area_len < 0)
-                       return -EOVERFLOW;
-               offset += area_len;
-               break;
-
-       case SEEK_DATA:
-               if (offset >= area_len)
-                       return -EINVAL;
-               if (offset < 0)
-                       offset = 0;
-               break;
-
-       case SEEK_HOLE:
-               /* Next hole is always the end of the region, unless offset is
-                * beyond that
-                */
-               if (offset < area_len)
-                       offset = area_len;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       if (offset < 0 || offset > area_len)
-               return -EINVAL;
-       filp->f_pos = offset;
-
-       return offset;
-}
-
-static ssize_t vsoc_write(struct file *filp, const char __user *buffer,
-                         size_t len, loff_t *poffset)
-{
-       __u32 area_off;
-       void *area_p;
-       ssize_t area_len;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       area_len = vsoc_get_area(filp, &area_off);
-       area_p = shm_off_to_virtual_addr(area_off);
-       area_p += *poffset;
-       area_len -= *poffset;
-       if (area_len <= 0)
-               return 0;
-       if (area_len < len)
-               len = area_len;
-       if (copy_from_user(area_p, buffer, len))
-               return -EFAULT;
-       *poffset += len;
-       return len;
-}
-
-static irqreturn_t vsoc_interrupt(int irq, void *region_data_v)
-{
-       struct vsoc_region_data *region_data =
-           (struct vsoc_region_data *)region_data_v;
-       int reg_num = region_data - vsoc_dev.regions_data;
-
-       if (unlikely(!region_data))
-               return IRQ_NONE;
-
-       if (unlikely(reg_num < 0 ||
-                    reg_num >= vsoc_dev.layout->region_count)) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "invalid irq @%p reg_num=0x%04x\n",
-                       region_data, reg_num);
-               return IRQ_NONE;
-       }
-       if (unlikely(vsoc_dev.regions_data + reg_num != region_data)) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "irq not aligned @%p reg_num=0x%04x\n",
-                       region_data, reg_num);
-               return IRQ_NONE;
-       }
-       wake_up_interruptible(&region_data->interrupt_wait_queue);
-       return IRQ_HANDLED;
-}
-
-static int vsoc_probe_device(struct pci_dev *pdev,
-                            const struct pci_device_id *ent)
-{
-       int result;
-       int i;
-       resource_size_t reg_size;
-       dev_t devt;
-
-       vsoc_dev.dev = pdev;
-       result = pci_enable_device(pdev);
-       if (result) {
-               dev_err(&pdev->dev,
-                       "pci_enable_device failed %s: error %d\n",
-                       pci_name(pdev), result);
-               return result;
-       }
-       vsoc_dev.enabled_device = true;
-       result = pci_request_regions(pdev, "vsoc");
-       if (result < 0) {
-               dev_err(&pdev->dev, "pci_request_regions failed\n");
-               vsoc_remove_device(pdev);
-               return -EBUSY;
-       }
-       vsoc_dev.requested_regions = true;
-       /* Set up the control registers in BAR 0 */
-       reg_size = pci_resource_len(pdev, REGISTER_BAR);
-       if (reg_size > MAX_REGISTER_BAR_LEN)
-               vsoc_dev.regs =
-                   pci_iomap(pdev, REGISTER_BAR, MAX_REGISTER_BAR_LEN);
-       else
-               vsoc_dev.regs = pci_iomap(pdev, REGISTER_BAR, reg_size);
-
-       if (!vsoc_dev.regs) {
-               dev_err(&pdev->dev,
-                       "cannot map registers of size %zu\n",
-                      (size_t)reg_size);
-               vsoc_remove_device(pdev);
-               return -EBUSY;
-       }
-
-       /* Map the shared memory in BAR 2 */
-       vsoc_dev.shm_phys_start = pci_resource_start(pdev, SHARED_MEMORY_BAR);
-       vsoc_dev.shm_size = pci_resource_len(pdev, SHARED_MEMORY_BAR);
-
-       dev_info(&pdev->dev, "shared memory @ DMA %pa size=0x%zx\n",
-                &vsoc_dev.shm_phys_start, vsoc_dev.shm_size);
-       vsoc_dev.kernel_mapped_shm = pci_iomap_wc(pdev, SHARED_MEMORY_BAR, 0);
-       if (!vsoc_dev.kernel_mapped_shm) {
-               dev_err(&vsoc_dev.dev->dev, "cannot iomap region\n");
-               vsoc_remove_device(pdev);
-               return -EBUSY;
-       }
-
-       vsoc_dev.layout = (struct vsoc_shm_layout_descriptor __force *)
-                               vsoc_dev.kernel_mapped_shm;
-       dev_info(&pdev->dev, "major_version: %d\n",
-                vsoc_dev.layout->major_version);
-       dev_info(&pdev->dev, "minor_version: %d\n",
-                vsoc_dev.layout->minor_version);
-       dev_info(&pdev->dev, "size: 0x%x\n", vsoc_dev.layout->size);
-       dev_info(&pdev->dev, "regions: %d\n", vsoc_dev.layout->region_count);
-       if (vsoc_dev.layout->major_version !=
-           CURRENT_VSOC_LAYOUT_MAJOR_VERSION) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "driver supports only major_version %d\n",
-                       CURRENT_VSOC_LAYOUT_MAJOR_VERSION);
-               vsoc_remove_device(pdev);
-               return -EBUSY;
-       }
-       result = alloc_chrdev_region(&devt, 0, vsoc_dev.layout->region_count,
-                                    VSOC_DEV_NAME);
-       if (result) {
-               dev_err(&vsoc_dev.dev->dev, "alloc_chrdev_region failed\n");
-               vsoc_remove_device(pdev);
-               return -EBUSY;
-       }
-       vsoc_dev.major = MAJOR(devt);
-       cdev_init(&vsoc_dev.cdev, &vsoc_ops);
-       vsoc_dev.cdev.owner = THIS_MODULE;
-       result = cdev_add(&vsoc_dev.cdev, devt, vsoc_dev.layout->region_count);
-       if (result) {
-               dev_err(&vsoc_dev.dev->dev, "cdev_add error\n");
-               vsoc_remove_device(pdev);
-               return -EBUSY;
-       }
-       vsoc_dev.cdev_added = true;
-       vsoc_dev.class = class_create(THIS_MODULE, VSOC_DEV_NAME);
-       if (IS_ERR(vsoc_dev.class)) {
-               dev_err(&vsoc_dev.dev->dev, "class_create failed\n");
-               vsoc_remove_device(pdev);
-               return PTR_ERR(vsoc_dev.class);
-       }
-       vsoc_dev.class_added = true;
-       vsoc_dev.regions = (struct vsoc_device_region __force *)
-               ((void *)vsoc_dev.layout +
-                vsoc_dev.layout->vsoc_region_desc_offset);
-       vsoc_dev.msix_entries =
-               kcalloc(vsoc_dev.layout->region_count,
-                       sizeof(vsoc_dev.msix_entries[0]), GFP_KERNEL);
-       if (!vsoc_dev.msix_entries) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "unable to allocate msix_entries\n");
-               vsoc_remove_device(pdev);
-               return -ENOSPC;
-       }
-       vsoc_dev.regions_data =
-               kcalloc(vsoc_dev.layout->region_count,
-                       sizeof(vsoc_dev.regions_data[0]), GFP_KERNEL);
-       if (!vsoc_dev.regions_data) {
-               dev_err(&vsoc_dev.dev->dev,
-                       "unable to allocate regions' data\n");
-               vsoc_remove_device(pdev);
-               return -ENOSPC;
-       }
-       for (i = 0; i < vsoc_dev.layout->region_count; ++i)
-               vsoc_dev.msix_entries[i].entry = i;
-
-       result = pci_enable_msix_exact(vsoc_dev.dev, vsoc_dev.msix_entries,
-                                      vsoc_dev.layout->region_count);
-       if (result) {
-               dev_info(&pdev->dev, "pci_enable_msix failed: %d\n", result);
-               vsoc_remove_device(pdev);
-               return -ENOSPC;
-       }
-       /* Check that all regions are well formed */
-       for (i = 0; i < vsoc_dev.layout->region_count; ++i) {
-               const struct vsoc_device_region *region = vsoc_dev.regions + i;
-
-               if (!PAGE_ALIGNED(region->region_begin_offset) ||
-                   !PAGE_ALIGNED(region->region_end_offset)) {
-                       dev_err(&vsoc_dev.dev->dev,
-                               "region %d not aligned (%x:%x)", i,
-                               region->region_begin_offset,
-                               region->region_end_offset);
-                       vsoc_remove_device(pdev);
-                       return -EFAULT;
-               }
-               if (region->region_begin_offset >= region->region_end_offset ||
-                   region->region_end_offset > vsoc_dev.shm_size) {
-                       dev_err(&vsoc_dev.dev->dev,
-                               "region %d offsets are wrong: %x %x %zx",
-                               i, region->region_begin_offset,
-                               region->region_end_offset, vsoc_dev.shm_size);
-                       vsoc_remove_device(pdev);
-                       return -EFAULT;
-               }
-               if (region->managed_by >= vsoc_dev.layout->region_count) {
-                       dev_err(&vsoc_dev.dev->dev,
-                               "region %d has invalid owner: %u",
-                               i, region->managed_by);
-                       vsoc_remove_device(pdev);
-                       return -EFAULT;
-               }
-       }
-       vsoc_dev.msix_enabled = true;
-       for (i = 0; i < vsoc_dev.layout->region_count; ++i) {
-               const struct vsoc_device_region *region = vsoc_dev.regions + i;
-               size_t name_sz = sizeof(vsoc_dev.regions_data[i].name) - 1;
-               const struct vsoc_signal_table_layout *h_to_g_signal_table =
-                       &region->host_to_guest_signal_table;
-               const struct vsoc_signal_table_layout *g_to_h_signal_table =
-                       &region->guest_to_host_signal_table;
-
-               vsoc_dev.regions_data[i].name[name_sz] = '\0';
-               memcpy(vsoc_dev.regions_data[i].name, region->device_name,
-                      name_sz);
-               dev_info(&pdev->dev, "region %d name=%s\n",
-                        i, vsoc_dev.regions_data[i].name);
-               init_waitqueue_head
-                       (&vsoc_dev.regions_data[i].interrupt_wait_queue);
-               init_waitqueue_head(&vsoc_dev.regions_data[i].futex_wait_queue);
-               vsoc_dev.regions_data[i].incoming_signalled =
-                       shm_off_to_virtual_addr(region->region_begin_offset) +
-                       h_to_g_signal_table->interrupt_signalled_offset;
-               vsoc_dev.regions_data[i].outgoing_signalled =
-                       shm_off_to_virtual_addr(region->region_begin_offset) +
-                       g_to_h_signal_table->interrupt_signalled_offset;
-               result = request_irq(vsoc_dev.msix_entries[i].vector,
-                                    vsoc_interrupt, 0,
-                                    vsoc_dev.regions_data[i].name,
-                                    vsoc_dev.regions_data + i);
-               if (result) {
-                       dev_info(&pdev->dev,
-                                "request_irq failed irq=%d vector=%d\n",
-                               i, vsoc_dev.msix_entries[i].vector);
-                       vsoc_remove_device(pdev);
-                       return -ENOSPC;
-               }
-               vsoc_dev.regions_data[i].irq_requested = true;
-               if (!device_create(vsoc_dev.class, NULL,
-                                  MKDEV(vsoc_dev.major, i),
-                                  NULL, vsoc_dev.regions_data[i].name)) {
-                       dev_err(&vsoc_dev.dev->dev, "device_create failed\n");
-                       vsoc_remove_device(pdev);
-                       return -EBUSY;
-               }
-               vsoc_dev.regions_data[i].device_created = true;
-       }
-       return 0;
-}
-
-/*
- * This should undo all of the allocations in the probe function in reverse
- * order.
- *
- * Notes:
- *
- *   The device may have been partially initialized, so double check
- *   that the allocations happened.
- *
- *   This function may be called multiple times, so mark resources as freed
- *   as they are deallocated.
- */
-static void vsoc_remove_device(struct pci_dev *pdev)
-{
-       int i;
-       /*
-        * pdev is the first thing to be set on probe and the last thing
-        * to be cleared here. If it's NULL then there is no cleanup.
-        */
-       if (!pdev || !vsoc_dev.dev)
-               return;
-       dev_info(&pdev->dev, "remove_device\n");
-       if (vsoc_dev.regions_data) {
-               for (i = 0; i < vsoc_dev.layout->region_count; ++i) {
-                       if (vsoc_dev.regions_data[i].device_created) {
-                               device_destroy(vsoc_dev.class,
-                                              MKDEV(vsoc_dev.major, i));
-                               vsoc_dev.regions_data[i].device_created = false;
-                       }
-                       if (vsoc_dev.regions_data[i].irq_requested)
-                               free_irq(vsoc_dev.msix_entries[i].vector, NULL);
-                       vsoc_dev.regions_data[i].irq_requested = false;
-               }
-               kfree(vsoc_dev.regions_data);
-               vsoc_dev.regions_data = NULL;
-       }
-       if (vsoc_dev.msix_enabled) {
-               pci_disable_msix(pdev);
-               vsoc_dev.msix_enabled = false;
-       }
-       kfree(vsoc_dev.msix_entries);
-       vsoc_dev.msix_entries = NULL;
-       vsoc_dev.regions = NULL;
-       if (vsoc_dev.class_added) {
-               class_destroy(vsoc_dev.class);
-               vsoc_dev.class_added = false;
-       }
-       if (vsoc_dev.cdev_added) {
-               cdev_del(&vsoc_dev.cdev);
-               vsoc_dev.cdev_added = false;
-       }
-       if (vsoc_dev.major && vsoc_dev.layout) {
-               unregister_chrdev_region(MKDEV(vsoc_dev.major, 0),
-                                        vsoc_dev.layout->region_count);
-               vsoc_dev.major = 0;
-       }
-       vsoc_dev.layout = NULL;
-       if (vsoc_dev.kernel_mapped_shm) {
-               pci_iounmap(pdev, vsoc_dev.kernel_mapped_shm);
-               vsoc_dev.kernel_mapped_shm = NULL;
-       }
-       if (vsoc_dev.regs) {
-               pci_iounmap(pdev, vsoc_dev.regs);
-               vsoc_dev.regs = NULL;
-       }
-       if (vsoc_dev.requested_regions) {
-               pci_release_regions(pdev);
-               vsoc_dev.requested_regions = false;
-       }
-       if (vsoc_dev.enabled_device) {
-               pci_disable_device(pdev);
-               vsoc_dev.enabled_device = false;
-       }
-       /* Do this last: it indicates that the device is not initialized. */
-       vsoc_dev.dev = NULL;
-}
-
-static void __exit vsoc_cleanup_module(void)
-{
-       vsoc_remove_device(vsoc_dev.dev);
-       pci_unregister_driver(&vsoc_pci_driver);
-}
-
-static int __init vsoc_init_module(void)
-{
-       int err = -ENOMEM;
-
-       INIT_LIST_HEAD(&vsoc_dev.permissions);
-       mutex_init(&vsoc_dev.mtx);
-
-       err = pci_register_driver(&vsoc_pci_driver);
-       if (err < 0)
-               return err;
-       return 0;
-}
-
-static int vsoc_open(struct inode *inode, struct file *filp)
-{
-       /* Can't use vsoc_validate_filep because filp is still incomplete */
-       int ret = vsoc_validate_inode(inode);
-
-       if (ret)
-               return ret;
-       filp->private_data =
-               kzalloc(sizeof(struct vsoc_private_data), GFP_KERNEL);
-       if (!filp->private_data)
-               return -ENOMEM;
-       return 0;
-}
-
-static int vsoc_release(struct inode *inode, struct file *filp)
-{
-       struct vsoc_private_data *private_data = NULL;
-       struct fd_scoped_permission_node *node = NULL;
-       struct vsoc_device_region *owner_region_p = NULL;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       private_data = (struct vsoc_private_data *)filp->private_data;
-       if (!private_data)
-               return 0;
-
-       node = private_data->fd_scoped_permission_node;
-       if (node) {
-               owner_region_p = vsoc_region_from_inode(inode);
-               if (owner_region_p->managed_by != VSOC_REGION_WHOLE) {
-                       owner_region_p =
-                           &vsoc_dev.regions[owner_region_p->managed_by];
-               }
-               do_destroy_fd_scoped_permission_node(owner_region_p, node);
-               private_data->fd_scoped_permission_node = NULL;
-       }
-       kfree(private_data);
-       filp->private_data = NULL;
-
-       return 0;
-}
-
-/*
- * Returns the device relative offset and length of the area specified by the
- * fd scoped permission. If there is no fd scoped permission set, a default
- * permission covering the entire region is assumed, unless the region is owned
- * by another one, in which case the default is a permission with zero size.
- */
-static ssize_t vsoc_get_area(struct file *filp, __u32 *area_offset)
-{
-       __u32 off = 0;
-       ssize_t length = 0;
-       struct vsoc_device_region *region_p;
-       struct fd_scoped_permission *perm;
-
-       region_p = vsoc_region_from_filep(filp);
-       off = region_p->region_begin_offset;
-       perm = &((struct vsoc_private_data *)filp->private_data)->
-               fd_scoped_permission_node->permission;
-       if (perm) {
-               off += perm->begin_offset;
-               length = perm->end_offset - perm->begin_offset;
-       } else if (region_p->managed_by == VSOC_REGION_WHOLE) {
-               /* No permission set and the regions is not owned by another,
-                * default to full region access.
-                */
-               length = vsoc_device_region_size(region_p);
-       } else {
-               /* return zero length, access is denied. */
-               length = 0;
-       }
-       if (area_offset)
-               *area_offset = off;
-       return length;
-}
-
-static int vsoc_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-       unsigned long len = vma->vm_end - vma->vm_start;
-       __u32 area_off;
-       phys_addr_t mem_off;
-       ssize_t area_len;
-       int retval = vsoc_validate_filep(filp);
-
-       if (retval)
-               return retval;
-       area_len = vsoc_get_area(filp, &area_off);
-       /* Add the requested offset */
-       area_off += (vma->vm_pgoff << PAGE_SHIFT);
-       area_len -= (vma->vm_pgoff << PAGE_SHIFT);
-       if (area_len < len)
-               return -EINVAL;
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-       mem_off = shm_off_to_phys_addr(area_off);
-       if (io_remap_pfn_range(vma, vma->vm_start, mem_off >> PAGE_SHIFT,
-                              len, vma->vm_page_prot))
-               return -EAGAIN;
-       return 0;
-}
-
-module_init(vsoc_init_module);
-module_exit(vsoc_cleanup_module);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Greg Hartman <ghartman@google.com>");
-MODULE_DESCRIPTION("VSoC interpretation of QEmu's ivshmem device");
-MODULE_VERSION("1.0");
index 9b19ea9..9a3f7c0 100644 (file)
@@ -92,8 +92,8 @@ void gb_audio_manager_remove_all(void)
 
        list_for_each_entry_safe(module, next, &modules_list, list) {
                list_del(&module->list);
-               kobject_put(&module->kobj);
                ida_simple_remove(&module_id, module->id);
+               kobject_put(&module->kobj);
        }
 
        is_empty = list_empty(&modules_list);
index 9b6ea86..ba53959 100644 (file)
@@ -2009,21 +2009,16 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
        struct ieee_param *param;
        uint ret = 0;
 
-       if (p->length < sizeof(struct ieee_param) || !p->pointer) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!p->pointer || p->length != sizeof(struct ieee_param))
+               return -EINVAL;
 
        param = (struct ieee_param *)rtw_malloc(p->length);
-       if (!param) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!param)
+               return -ENOMEM;
 
        if (copy_from_user(param, p->pointer, p->length)) {
                kfree(param);
-               ret = -EFAULT;
-               goto out;
+               return -EFAULT;
        }
 
        switch (param->cmd) {
@@ -2054,9 +2049,6 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
                ret = -EFAULT;
 
        kfree(param);
-
-out:
-
        return ret;
 }
 
@@ -2791,26 +2783,19 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
        * so, we just check hw_init_completed
        */
 
-       if (!padapter->hw_init_completed) {
-               ret = -EPERM;
-               goto out;
-       }
+       if (!padapter->hw_init_completed)
+               return -EPERM;
 
-       if (!p->pointer) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!p->pointer || p->length != sizeof(struct ieee_param))
+               return -EINVAL;
 
        param = (struct ieee_param *)rtw_malloc(p->length);
-       if (!param) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (!param)
+               return -ENOMEM;
 
        if (copy_from_user(param, p->pointer, p->length)) {
                kfree(param);
-               ret = -EFAULT;
-               goto out;
+               return -EFAULT;
        }
 
        switch (param->cmd) {
@@ -2865,7 +2850,6 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
        if (ret == 0 && copy_to_user(p->pointer, param, p->length))
                ret = -EFAULT;
        kfree(param);
-out:
        return ret;
 }
 #endif
index b44e902..b6d56cf 100644 (file)
@@ -476,14 +476,13 @@ int rtl8723bs_xmit_thread(void *context)
        s32 ret;
        struct adapter *padapter;
        struct xmit_priv *pxmitpriv;
-       u8 thread_name[20] = "RTWHALXT";
-
+       u8 thread_name[20];
 
        ret = _SUCCESS;
        padapter = context;
        pxmitpriv = &padapter->xmitpriv;
 
-       rtw_sprintf(thread_name, 20, "%s-"ADPT_FMT, thread_name, ADPT_ARG(padapter));
+       rtw_sprintf(thread_name, 20, "RTWHALXT-" ADPT_FMT, ADPT_ARG(padapter));
        thread_enter(thread_name);
 
        DBG_871X("start "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
index db6528a..9b9038e 100644 (file)
@@ -3373,21 +3373,16 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
 
        /* down(&ieee->wx_sem); */
 
-       if (p->length < sizeof(struct ieee_param) || !p->pointer) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!p->pointer || p->length != sizeof(struct ieee_param))
+               return -EINVAL;
 
        param = rtw_malloc(p->length);
-       if (param == NULL) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (param == NULL)
+               return -ENOMEM;
 
        if (copy_from_user(param, p->pointer, p->length)) {
                kfree(param);
-               ret = -EFAULT;
-               goto out;
+               return -EFAULT;
        }
 
        switch (param->cmd) {
@@ -3421,12 +3416,8 @@ static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
 
        kfree(param);
 
-out:
-
        /* up(&ieee->wx_sem); */
-
        return ret;
-
 }
 
 static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param, u32 param_len)
@@ -4200,28 +4191,19 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
        * so, we just check hw_init_completed
        */
 
-       if (!padapter->hw_init_completed) {
-               ret = -EPERM;
-               goto out;
-       }
-
+       if (!padapter->hw_init_completed)
+               return -EPERM;
 
-       /* if (p->length < sizeof(struct ieee_param) || !p->pointer) { */
-       if (!p->pointer) {
-               ret = -EINVAL;
-               goto out;
-       }
+       if (!p->pointer || p->length != sizeof(*param))
+               return -EINVAL;
 
        param = rtw_malloc(p->length);
-       if (param == NULL) {
-               ret = -ENOMEM;
-               goto out;
-       }
+       if (param == NULL)
+               return -ENOMEM;
 
        if (copy_from_user(param, p->pointer, p->length)) {
                kfree(param);
-               ret = -EFAULT;
-               goto out;
+               return -EFAULT;
        }
 
        /* DBG_871X("%s, cmd =%d\n", __func__, param->cmd); */
@@ -4321,13 +4303,8 @@ static int rtw_hostapd_ioctl(struct net_device *dev, struct iw_point *p)
        if (ret == 0 && copy_to_user(p->pointer, param, p->length))
                ret = -EFAULT;
 
-
        kfree(param);
-
-out:
-
        return ret;
-
 }
 
 static int rtw_wx_set_priv(struct net_device *dev,
index 821aae8..a0b60e7 100644 (file)
@@ -98,7 +98,7 @@ int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb,
 
        vnt_rf_rssi_to_dbm(priv, tail->rssi, &rx_dbm);
 
-       priv->bb_pre_ed_rssi = (u8)rx_dbm + 1;
+       priv->bb_pre_ed_rssi = (u8)-rx_dbm + 1;
        priv->current_rssi = priv->bb_pre_ed_rssi;
 
        skb_pull(skb, sizeof(*head));
index b94ed4e..09e55ea 100644 (file)
@@ -1165,9 +1165,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length,
                conn->cid);
 
-       if (target_get_sess_cmd(&cmd->se_cmd, true) < 0)
-               return iscsit_add_reject_cmd(cmd,
-                               ISCSI_REASON_WAITING_FOR_LOGOUT, buf);
+       target_get_sess_cmd(&cmd->se_cmd, true);
 
        cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd,
                                                     scsilun_to_int(&hdr->lun));
@@ -2004,9 +2002,7 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                              conn->sess->se_sess, 0, DMA_NONE,
                              TCM_SIMPLE_TAG, cmd->sense_buffer + 2);
 
-       if (target_get_sess_cmd(&cmd->se_cmd, true) < 0)
-               return iscsit_add_reject_cmd(cmd,
-                               ISCSI_REASON_WAITING_FOR_LOGOUT, buf);
+       target_get_sess_cmd(&cmd->se_cmd, true);
 
        /*
         * TASK_REASSIGN for ERL=2 / connection stays inside of
@@ -4149,6 +4145,9 @@ int iscsit_close_connection(
        iscsit_stop_nopin_response_timer(conn);
        iscsit_stop_nopin_timer(conn);
 
+       if (conn->conn_transport->iscsit_wait_conn)
+               conn->conn_transport->iscsit_wait_conn(conn);
+
        /*
         * During Connection recovery drop unacknowledged out of order
         * commands for this connection, and prepare the other commands
@@ -4231,11 +4230,6 @@ int iscsit_close_connection(
         * must wait until they have completed.
         */
        iscsit_check_conn_usage_count(conn);
-       target_sess_cmd_list_set_waiting(sess->se_sess);
-       target_wait_for_sess_cmds(sess->se_sess);
-
-       if (conn->conn_transport->iscsit_wait_conn)
-               conn->conn_transport->iscsit_wait_conn(conn);
 
        ahash_request_free(conn->conn_tx_hash);
        if (conn->conn_rx_hash) {
index ea482d4..0ae9e60 100644 (file)
@@ -666,6 +666,11 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
 
        target_remove_from_state_list(cmd);
 
+       /*
+        * Clear struct se_cmd->se_lun before the handoff to FE.
+        */
+       cmd->se_lun = NULL;
+
        spin_lock_irqsave(&cmd->t_state_lock, flags);
        /*
         * Determine if frontend context caller is requesting the stopping of
@@ -693,6 +698,17 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
        return cmd->se_tfo->check_stop_free(cmd);
 }
 
+static void transport_lun_remove_cmd(struct se_cmd *cmd)
+{
+       struct se_lun *lun = cmd->se_lun;
+
+       if (!lun)
+               return;
+
+       if (cmpxchg(&cmd->lun_ref_active, true, false))
+               percpu_ref_put(&lun->lun_ref);
+}
+
 static void target_complete_failure_work(struct work_struct *work)
 {
        struct se_cmd *cmd = container_of(work, struct se_cmd, work);
@@ -783,6 +799,8 @@ static void target_handle_abort(struct se_cmd *cmd)
 
        WARN_ON_ONCE(kref_read(&cmd->cmd_kref) == 0);
 
+       transport_lun_remove_cmd(cmd);
+
        transport_cmd_check_stop_to_fabric(cmd);
 }
 
@@ -1708,6 +1726,7 @@ static void target_complete_tmr_failure(struct work_struct *work)
        se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
        se_cmd->se_tfo->queue_tm_rsp(se_cmd);
 
+       transport_lun_remove_cmd(se_cmd);
        transport_cmd_check_stop_to_fabric(se_cmd);
 }
 
@@ -1898,6 +1917,7 @@ void transport_generic_request_failure(struct se_cmd *cmd,
                goto queue_full;
 
 check_stop:
+       transport_lun_remove_cmd(cmd);
        transport_cmd_check_stop_to_fabric(cmd);
        return;
 
@@ -2195,6 +2215,7 @@ queue_status:
                transport_handle_queue_full(cmd, cmd->se_dev, ret, false);
                return;
        }
+       transport_lun_remove_cmd(cmd);
        transport_cmd_check_stop_to_fabric(cmd);
 }
 
@@ -2289,6 +2310,7 @@ static void target_complete_ok_work(struct work_struct *work)
                if (ret)
                        goto queue_full;
 
+               transport_lun_remove_cmd(cmd);
                transport_cmd_check_stop_to_fabric(cmd);
                return;
        }
@@ -2314,6 +2336,7 @@ static void target_complete_ok_work(struct work_struct *work)
                        if (ret)
                                goto queue_full;
 
+                       transport_lun_remove_cmd(cmd);
                        transport_cmd_check_stop_to_fabric(cmd);
                        return;
                }
@@ -2349,6 +2372,7 @@ queue_rsp:
                        if (ret)
                                goto queue_full;
 
+                       transport_lun_remove_cmd(cmd);
                        transport_cmd_check_stop_to_fabric(cmd);
                        return;
                }
@@ -2384,6 +2408,7 @@ queue_status:
                break;
        }
 
+       transport_lun_remove_cmd(cmd);
        transport_cmd_check_stop_to_fabric(cmd);
        return;
 
@@ -2710,6 +2735,9 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
                 */
                if (cmd->state_active)
                        target_remove_from_state_list(cmd);
+
+               if (cmd->se_lun)
+                       transport_lun_remove_cmd(cmd);
        }
        if (aborted)
                cmd->free_compl = &compl;
@@ -2781,9 +2809,6 @@ static void target_release_cmd_kref(struct kref *kref)
        struct completion *abrt_compl = se_cmd->abrt_compl;
        unsigned long flags;
 
-       if (se_cmd->lun_ref_active)
-               percpu_ref_put(&se_cmd->se_lun->lun_ref);
-
        if (se_sess) {
                spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
                list_del_init(&se_cmd->se_cmd_list);
index ad5479f..7d6ecc3 100644 (file)
@@ -348,6 +348,12 @@ out:
        return ret;
 }
 
+static int tb_switch_nvm_no_read(void *priv, unsigned int offset, void *val,
+                                size_t bytes)
+{
+       return -EPERM;
+}
+
 static int tb_switch_nvm_write(void *priv, unsigned int offset, void *val,
                               size_t bytes)
 {
@@ -393,6 +399,7 @@ static struct nvmem_device *register_nvmem(struct tb_switch *sw, int id,
                config.read_only = true;
        } else {
                config.name = "nvm_non_active";
+               config.reg_read = tb_switch_nvm_no_read;
                config.reg_write = tb_switch_nvm_write;
                config.root_only = true;
        }
index d1cdd2a..d367803 100644 (file)
@@ -265,7 +265,6 @@ struct device *serdev_tty_port_register(struct tty_port *port,
                                        struct device *parent,
                                        struct tty_driver *drv, int idx)
 {
-       const struct tty_port_client_operations *old_ops;
        struct serdev_controller *ctrl;
        struct serport *serport;
        int ret;
@@ -284,7 +283,6 @@ struct device *serdev_tty_port_register(struct tty_port *port,
 
        ctrl->ops = &ctrl_ops;
 
-       old_ops = port->client_ops;
        port->client_ops = &client_ops;
        port->client_data = ctrl;
 
@@ -297,7 +295,7 @@ struct device *serdev_tty_port_register(struct tty_port *port,
 
 err_reset_data:
        port->client_data = NULL;
-       port->client_ops = old_ops;
+       port->client_ops = &tty_port_default_client_ops;
        serdev_controller_put(ctrl);
 
        return ERR_PTR(ret);
@@ -312,8 +310,8 @@ int serdev_tty_port_unregister(struct tty_port *port)
                return -ENODEV;
 
        serdev_controller_remove(ctrl);
-       port->client_ops = NULL;
        port->client_data = NULL;
+       port->client_ops = &tty_port_default_client_ops;
        serdev_controller_put(ctrl);
 
        return 0;
index d657aa1..c33e02c 100644 (file)
@@ -446,7 +446,6 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
                port.port.line = rc;
 
        port.port.irq = irq_of_parse_and_map(np, 0);
-       port.port.irqflags = IRQF_SHARED;
        port.port.handle_irq = aspeed_vuart_handle_irq;
        port.port.iotype = UPIO_MEM;
        port.port.type = PORT_16550A;
index 0894a22..f2a33c9 100644 (file)
@@ -174,7 +174,7 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
        struct hlist_head *h;
        struct hlist_node *n;
        struct irq_info *i;
-       int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
+       int ret;
 
        mutex_lock(&hash_mutex);
 
@@ -209,9 +209,8 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
                INIT_LIST_HEAD(&up->list);
                i->head = &up->list;
                spin_unlock_irq(&i->lock);
-               irq_flags |= up->port.irqflags;
                ret = request_irq(up->port.irq, serial8250_interrupt,
-                                 irq_flags, up->port.name, i);
+                                 up->port.irqflags, up->port.name, i);
                if (ret < 0)
                        serial_do_unlink(i, up);
        }
index 531ad67..f668775 100644 (file)
@@ -202,7 +202,6 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
 
        port->type = type;
        port->uartclk = clk;
-       port->irqflags |= IRQF_SHARED;
 
        if (of_property_read_bool(np, "no-loopback-test"))
                port->flags |= UPF_SKIP_TEST;
index 430e346..0325f2e 100644 (file)
@@ -2177,6 +2177,10 @@ int serial8250_do_startup(struct uart_port *port)
                }
        }
 
+       /* Check if we need to have shared IRQs */
+       if (port->irq && (up->port.flags & UPF_SHARE_IRQ))
+               up->port.irqflags |= IRQF_SHARED;
+
        if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) {
                unsigned char iir1;
                /*
index 3bdd56a..ea12f10 100644 (file)
@@ -286,6 +286,10 @@ static void ar933x_uart_set_termios(struct uart_port *port,
        ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
                            AR933X_UART_CS_HOST_INT_EN);
 
+       /* enable RX and TX ready overide */
+       ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
+               AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE);
+
        /* reenable the UART */
        ar933x_uart_rmw(up, AR933X_UART_CS_REG,
                        AR933X_UART_CS_IF_MODE_M << AR933X_UART_CS_IF_MODE_S,
@@ -418,6 +422,10 @@ static int ar933x_uart_startup(struct uart_port *port)
        ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
                            AR933X_UART_CS_HOST_INT_EN);
 
+       /* enable RX and TX ready overide */
+       ar933x_uart_rmw_set(up, AR933X_UART_CS_REG,
+               AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE);
+
        /* Enable RX interrupts */
        up->ier = AR933X_UART_INT_RX_VALID;
        ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);
index c15c398..a39c87a 100644 (file)
@@ -570,7 +570,8 @@ static void atmel_stop_tx(struct uart_port *port)
        atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
 
        if (atmel_uart_is_half_duplex(port))
-               atmel_start_rx(port);
+               if (!atomic_read(&atmel_port->tasklet_shutdown))
+                       atmel_start_rx(port);
 
 }
 
index 19d5a4c..d4b81b0 100644 (file)
@@ -1373,6 +1373,7 @@ static struct console cpm_scc_uart_console = {
 
 static int __init cpm_uart_console_init(void)
 {
+       cpm_muram_init();
        register_console(&cpm_scc_uart_console);
        return 0;
 }
index 0c6c631..d337782 100644 (file)
@@ -599,7 +599,7 @@ static void imx_uart_dma_tx(struct imx_port *sport)
 
        sport->tx_bytes = uart_circ_chars_pending(xmit);
 
-       if (xmit->tail < xmit->head) {
+       if (xmit->tail < xmit->head || xmit->head == 0) {
                sport->dma_tx_nents = 1;
                sg_init_one(sgl, xmit->buf + xmit->tail, sport->tx_bytes);
        } else {
index 191abb1..0bd1684 100644 (file)
@@ -129,6 +129,7 @@ static int handle_rx_console(struct uart_port *uport, u32 bytes, bool drop);
 static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop);
 static unsigned int qcom_geni_serial_tx_empty(struct uart_port *port);
 static void qcom_geni_serial_stop_rx(struct uart_port *uport);
+static void qcom_geni_serial_handle_rx(struct uart_port *uport, bool drop);
 
 static const unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200,
                                        32000000, 48000000, 64000000, 80000000,
@@ -599,7 +600,7 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport)
        u32 irq_en;
        u32 status;
        struct qcom_geni_serial_port *port = to_dev_port(uport, uport);
-       u32 irq_clear = S_CMD_DONE_EN;
+       u32 s_irq_status;
 
        irq_en = readl(uport->membase + SE_GENI_S_IRQ_EN);
        irq_en &= ~(S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN);
@@ -615,10 +616,19 @@ static void qcom_geni_serial_stop_rx(struct uart_port *uport)
                return;
 
        geni_se_cancel_s_cmd(&port->se);
-       qcom_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG,
-                                       S_GENI_CMD_CANCEL, false);
+       qcom_geni_serial_poll_bit(uport, SE_GENI_S_IRQ_STATUS,
+                                       S_CMD_CANCEL_EN, true);
+       /*
+        * If timeout occurs secondary engine remains active
+        * and Abort sequence is executed.
+        */
+       s_irq_status = readl(uport->membase + SE_GENI_S_IRQ_STATUS);
+       /* Flush the Rx buffer */
+       if (s_irq_status & S_RX_FIFO_LAST_EN)
+               qcom_geni_serial_handle_rx(uport, true);
+       writel(s_irq_status, uport->membase + SE_GENI_S_IRQ_CLEAR);
+
        status = readl(uport->membase + SE_GENI_STATUS);
-       writel(irq_clear, uport->membase + SE_GENI_S_IRQ_CLEAR);
        if (status & S_GENI_CMD_ACTIVE)
                qcom_geni_serial_abort_rx(uport);
 }
index 33034b8..8de8bac 100644 (file)
@@ -692,11 +692,22 @@ static void tegra_uart_copy_rx_to_tty(struct tegra_uart_port *tup,
                                   count, DMA_TO_DEVICE);
 }
 
+static void do_handle_rx_pio(struct tegra_uart_port *tup)
+{
+       struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
+       struct tty_port *port = &tup->uport.state->port;
+
+       tegra_uart_handle_rx_pio(tup, port);
+       if (tty) {
+               tty_flip_buffer_push(port);
+               tty_kref_put(tty);
+       }
+}
+
 static void tegra_uart_rx_buffer_push(struct tegra_uart_port *tup,
                                      unsigned int residue)
 {
        struct tty_port *port = &tup->uport.state->port;
-       struct tty_struct *tty = tty_port_tty_get(port);
        unsigned int count;
 
        async_tx_ack(tup->rx_dma_desc);
@@ -705,11 +716,7 @@ static void tegra_uart_rx_buffer_push(struct tegra_uart_port *tup,
        /* If we are here, DMA is stopped */
        tegra_uart_copy_rx_to_tty(tup, port, count);
 
-       tegra_uart_handle_rx_pio(tup, port);
-       if (tty) {
-               tty_flip_buffer_push(port);
-               tty_kref_put(tty);
-       }
+       do_handle_rx_pio(tup);
 }
 
 static void tegra_uart_rx_dma_complete(void *args)
@@ -749,8 +756,10 @@ static void tegra_uart_terminate_rx_dma(struct tegra_uart_port *tup)
 {
        struct dma_tx_state state;
 
-       if (!tup->rx_dma_active)
+       if (!tup->rx_dma_active) {
+               do_handle_rx_pio(tup);
                return;
+       }
 
        dmaengine_terminate_all(tup->rx_dma_chan);
        dmaengine_tx_status(tup->rx_dma_chan, tup->rx_cookie, &state);
@@ -816,18 +825,6 @@ static void tegra_uart_handle_modem_signal_change(struct uart_port *u)
                uart_handle_cts_change(&tup->uport, msr & UART_MSR_CTS);
 }
 
-static void do_handle_rx_pio(struct tegra_uart_port *tup)
-{
-       struct tty_struct *tty = tty_port_tty_get(&tup->uport.state->port);
-       struct tty_port *port = &tup->uport.state->port;
-
-       tegra_uart_handle_rx_pio(tup, port);
-       if (tty) {
-               tty_flip_buffer_push(port);
-               tty_kref_put(tty);
-       }
-}
-
 static irqreturn_t tegra_uart_isr(int irq, void *data)
 {
        struct tegra_uart_port *tup = data;
index 044c3cb..ea80bf8 100644 (file)
@@ -52,10 +52,11 @@ static void tty_port_default_wakeup(struct tty_port *port)
        }
 }
 
-static const struct tty_port_client_operations default_client_ops = {
+const struct tty_port_client_operations tty_port_default_client_ops = {
        .receive_buf = tty_port_default_receive_buf,
        .write_wakeup = tty_port_default_wakeup,
 };
+EXPORT_SYMBOL_GPL(tty_port_default_client_ops);
 
 void tty_port_init(struct tty_port *port)
 {
@@ -68,7 +69,7 @@ void tty_port_init(struct tty_port *port)
        spin_lock_init(&port->lock);
        port->close_delay = (50 * HZ) / 100;
        port->closing_wait = (3000 * HZ) / 100;
-       port->client_ops = &default_client_ops;
+       port->client_ops = &tty_port_default_client_ops;
        kref_init(&port->kref);
 }
 EXPORT_SYMBOL(tty_port_init);
index 78732fe..0c50d74 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/tty.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 
@@ -29,6 +30,8 @@
 #include <linux/console.h>
 #include <linux/tty_flip.h>
 
+#include <linux/sched/signal.h>
+
 /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
 #define isspace(c)     ((c) == ' ')
 
@@ -43,6 +46,7 @@ static volatile int sel_start = -1;   /* cleared by clear_selection */
 static int sel_end;
 static int sel_buffer_lth;
 static char *sel_buffer;
+static DEFINE_MUTEX(sel_lock);
 
 /* clear_selection, highlight and highlight_pointer can be called
    from interrupt (via scrollback/front) */
@@ -184,7 +188,7 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
        char *bp, *obp;
        int i, ps, pe, multiplier;
        u32 c;
-       int mode;
+       int mode, ret = 0;
 
        poke_blanked_console();
 
@@ -210,6 +214,7 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
        if (ps > pe)    /* make sel_start <= sel_end */
                swap(ps, pe);
 
+       mutex_lock(&sel_lock);
        if (sel_cons != vc_cons[fg_console].d) {
                clear_selection();
                sel_cons = vc_cons[fg_console].d;
@@ -255,9 +260,10 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
                        break;
                case TIOCL_SELPOINTER:
                        highlight_pointer(pe);
-                       return 0;
+                       goto unlock;
                default:
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto unlock;
        }
 
        /* remove the pointer */
@@ -279,7 +285,7 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
        else if (new_sel_start == sel_start)
        {
                if (new_sel_end == sel_end)     /* no action required */
-                       return 0;
+                       goto unlock;
                else if (new_sel_end > sel_end) /* extend to right */
                        highlight(sel_end + 2, new_sel_end);
                else                            /* contract from right */
@@ -307,7 +313,8 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
        if (!bp) {
                printk(KERN_WARNING "selection: kmalloc() failed\n");
                clear_selection();
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto unlock;
        }
        kfree(sel_buffer);
        sel_buffer = bp;
@@ -332,7 +339,9 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
                }
        }
        sel_buffer_lth = bp - sel_buffer;
-       return 0;
+unlock:
+       mutex_unlock(&sel_lock);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(set_selection_kernel);
 
@@ -350,6 +359,7 @@ int paste_selection(struct tty_struct *tty)
        unsigned int count;
        struct  tty_ldisc *ld;
        DECLARE_WAITQUEUE(wait, current);
+       int ret = 0;
 
        console_lock();
        poke_blanked_console();
@@ -361,10 +371,17 @@ int paste_selection(struct tty_struct *tty)
        tty_buffer_lock_exclusive(&vc->port);
 
        add_wait_queue(&vc->paste_wait, &wait);
+       mutex_lock(&sel_lock);
        while (sel_buffer && sel_buffer_lth > pasted) {
                set_current_state(TASK_INTERRUPTIBLE);
+               if (signal_pending(current)) {
+                       ret = -EINTR;
+                       break;
+               }
                if (tty_throttled(tty)) {
+                       mutex_unlock(&sel_lock);
                        schedule();
+                       mutex_lock(&sel_lock);
                        continue;
                }
                __set_current_state(TASK_RUNNING);
@@ -373,11 +390,12 @@ int paste_selection(struct tty_struct *tty)
                                              count);
                pasted += count;
        }
+       mutex_unlock(&sel_lock);
        remove_wait_queue(&vc->paste_wait, &wait);
        __set_current_state(TASK_RUNNING);
 
        tty_buffer_unlock_exclusive(&vc->port);
        tty_ldisc_deref(ld);
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(paste_selection);
index 35d21cd..0cfbb71 100644 (file)
@@ -936,10 +936,21 @@ static void flush_scrollback(struct vc_data *vc)
        WARN_CONSOLE_UNLOCKED();
 
        set_origin(vc);
-       if (vc->vc_sw->con_flush_scrollback)
+       if (vc->vc_sw->con_flush_scrollback) {
                vc->vc_sw->con_flush_scrollback(vc);
-       else
+       } else if (con_is_visible(vc)) {
+               /*
+                * When no con_flush_scrollback method is provided then the
+                * legacy way for flushing the scrollback buffer is to use
+                * a side effect of the con_switch method. We do it only on
+                * the foreground console as background consoles have no
+                * scrollback buffers in that case and we obviously don't
+                * want to switch to them.
+                */
+               hide_cursor(vc);
                vc->vc_sw->con_switch(vc);
+               set_cursor(vc);
+       }
 }
 
 /*
index 8b0ed13..ee6c91e 100644 (file)
@@ -876,15 +876,20 @@ int vt_ioctl(struct tty_struct *tty,
                        return -EINVAL;
 
                for (i = 0; i < MAX_NR_CONSOLES; i++) {
+                       struct vc_data *vcp;
+
                        if (!vc_cons[i].d)
                                continue;
                        console_lock();
-                       if (v.v_vlin)
-                               vc_cons[i].d->vc_scan_lines = v.v_vlin;
-                       if (v.v_clin)
-                               vc_cons[i].d->vc_font.height = v.v_clin;
-                       vc_cons[i].d->vc_resize_user = 1;
-                       vc_resize(vc_cons[i].d, v.v_cols, v.v_rows);
+                       vcp = vc_cons[i].d;
+                       if (vcp) {
+                               if (v.v_vlin)
+                                       vcp->vc_scan_lines = v.v_vlin;
+                               if (v.v_clin)
+                                       vcp->vc_font.height = v.v_clin;
+                               vcp->vc_resize_user = 1;
+                               vc_resize(vcp, v.v_cols, v.v_rows);
+                       }
                        console_unlock();
                }
                break;
index 26bc05e..b7918f6 100644 (file)
@@ -256,6 +256,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
                struct usb_host_interface *ifp, int num_ep,
                unsigned char *buffer, int size)
 {
+       struct usb_device *udev = to_usb_device(ddev);
        unsigned char *buffer0 = buffer;
        struct usb_endpoint_descriptor *d;
        struct usb_host_endpoint *endpoint;
@@ -297,6 +298,16 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
                goto skip_to_next_endpoint_or_interface_descriptor;
        }
 
+       /* Ignore blacklisted endpoints */
+       if (udev->quirks & USB_QUIRK_ENDPOINT_BLACKLIST) {
+               if (usb_endpoint_is_blacklisted(udev, ifp, d)) {
+                       dev_warn(ddev, "config %d interface %d altsetting %d has a blacklisted endpoint with address 0x%X, skipping\n",
+                                       cfgno, inum, asnum,
+                                       d->bEndpointAddress);
+                       goto skip_to_next_endpoint_or_interface_descriptor;
+               }
+       }
+
        endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
        ++ifp->desc.bNumEndpoints;
 
@@ -311,7 +322,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
        j = 255;
        if (usb_endpoint_xfer_int(d)) {
                i = 1;
-               switch (to_usb_device(ddev)->speed) {
+               switch (udev->speed) {
                case USB_SPEED_SUPER_PLUS:
                case USB_SPEED_SUPER:
                case USB_SPEED_HIGH:
@@ -332,8 +343,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
                        /*
                         * This quirk fixes bIntervals reported in ms.
                         */
-                       if (to_usb_device(ddev)->quirks &
-                               USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL) {
+                       if (udev->quirks & USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL) {
                                n = clamp(fls(d->bInterval) + 3, i, j);
                                i = j = n;
                        }
@@ -341,8 +351,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
                         * This quirk fixes bIntervals reported in
                         * linear microframes.
                         */
-                       if (to_usb_device(ddev)->quirks &
-                               USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL) {
+                       if (udev->quirks & USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL) {
                                n = clamp(fls(d->bInterval), i, j);
                                i = j = n;
                        }
@@ -359,7 +368,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
        } else if (usb_endpoint_xfer_isoc(d)) {
                i = 1;
                j = 16;
-               switch (to_usb_device(ddev)->speed) {
+               switch (udev->speed) {
                case USB_SPEED_HIGH:
                        n = 7;          /* 8 ms = 2^(7-1) uframes */
                        break;
@@ -381,8 +390,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
         * explicitly forbidden by the USB spec.  In an attempt to make
         * them usable, we will try treating them as Interrupt endpoints.
         */
-       if (to_usb_device(ddev)->speed == USB_SPEED_LOW &&
-                       usb_endpoint_xfer_bulk(d)) {
+       if (udev->speed == USB_SPEED_LOW && usb_endpoint_xfer_bulk(d)) {
                dev_warn(ddev, "config %d interface %d altsetting %d "
                    "endpoint 0x%X is Bulk; changing to Interrupt\n",
                    cfgno, inum, asnum, d->bEndpointAddress);
@@ -406,7 +414,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
 
        /* Find the highest legal maxpacket size for this endpoint */
        i = 0;          /* additional transactions per microframe */
-       switch (to_usb_device(ddev)->speed) {
+       switch (udev->speed) {
        case USB_SPEED_LOW:
                maxpacket_maxes = low_speed_maxpacket_maxes;
                break;
@@ -442,8 +450,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
         * maxpacket sizes other than 512.  High speed HCDs may not
         * be able to handle that particular bug, so let's warn...
         */
-       if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
-                       && usb_endpoint_xfer_bulk(d)) {
+       if (udev->speed == USB_SPEED_HIGH && usb_endpoint_xfer_bulk(d)) {
                if (maxp != 512)
                        dev_warn(ddev, "config %d interface %d altsetting %d "
                                "bulk endpoint 0x%X has invalid maxpacket %d\n",
@@ -452,7 +459,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
        }
 
        /* Parse a possible SuperSpeed endpoint companion descriptor */
-       if (to_usb_device(ddev)->speed >= USB_SPEED_SUPER)
+       if (udev->speed >= USB_SPEED_SUPER)
                usb_parse_ss_endpoint_companion(ddev, cfgno,
                                inum, asnum, endpoint, buffer, size);
 
index 3405b14..1d212f8 100644 (file)
@@ -38,7 +38,9 @@
 #include "otg_whitelist.h"
 
 #define USB_VENDOR_GENESYS_LOGIC               0x05e3
+#define USB_VENDOR_SMSC                                0x0424
 #define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND       0x01
+#define HUB_QUIRK_DISABLE_AUTOSUSPEND          0x02
 
 #define USB_TP_TRANSMISSION_DELAY      40      /* ns */
 #define USB_TP_TRANSMISSION_DELAY_MAX  65535   /* ns */
@@ -1217,11 +1219,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 #ifdef CONFIG_PM
                        udev->reset_resume = 1;
 #endif
-                       /* Don't set the change_bits when the device
-                        * was powered off.
-                        */
-                       if (test_bit(port1, hub->power_bits))
-                               set_bit(port1, hub->change_bits);
 
                } else {
                        /* The power session is gone; tell hub_wq */
@@ -1731,6 +1728,10 @@ static void hub_disconnect(struct usb_interface *intf)
        kfree(hub->buffer);
 
        pm_suspend_ignore_children(&intf->dev, false);
+
+       if (hub->quirk_disable_autosuspend)
+               usb_autopm_put_interface(intf);
+
        kref_put(&hub->kref, hub_release);
 }
 
@@ -1863,6 +1864,11 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
        if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND)
                hub->quirk_check_port_auto_suspend = 1;
 
+       if (id->driver_info & HUB_QUIRK_DISABLE_AUTOSUSPEND) {
+               hub->quirk_disable_autosuspend = 1;
+               usb_autopm_get_interface(intf);
+       }
+
        if (hub_configure(hub, &desc->endpoint[0].desc) >= 0)
                return 0;
 
@@ -5599,6 +5605,10 @@ out_hdev_lock:
 }
 
 static const struct usb_device_id hub_id_table[] = {
+    { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_CLASS,
+      .idVendor = USB_VENDOR_SMSC,
+      .bInterfaceClass = USB_CLASS_HUB,
+      .driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND},
     { .match_flags = USB_DEVICE_ID_MATCH_VENDOR
                        | USB_DEVICE_ID_MATCH_INT_CLASS,
       .idVendor = USB_VENDOR_GENESYS_LOGIC,
index a9e24e4..a97dd1b 100644 (file)
@@ -61,6 +61,7 @@ struct usb_hub {
        unsigned                quiescing:1;
        unsigned                disconnected:1;
        unsigned                in_reset:1;
+       unsigned                quirk_disable_autosuspend:1;
 
        unsigned                quirk_check_port_auto_suspend:1;
 
index 6b64130..2b24336 100644 (file)
@@ -354,6 +354,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x0904, 0x6103), .driver_info =
                        USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },
 
+       /* Sound Devices USBPre2 */
+       { USB_DEVICE(0x0926, 0x0202), .driver_info =
+                       USB_QUIRK_ENDPOINT_BLACKLIST },
+
        /* Keytouch QWERTY Panel keyboard */
        { USB_DEVICE(0x0926, 0x3333), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
@@ -445,6 +449,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* INTEL VALUE SSD */
        { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* novation SoundControl XL */
+       { USB_DEVICE(0x1235, 0x0061), .driver_info = USB_QUIRK_RESET_RESUME },
+
        { }  /* terminating entry must be last */
 };
 
@@ -472,6 +479,39 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = {
        { }  /* terminating entry must be last */
 };
 
+/*
+ * Entries for blacklisted endpoints that should be ignored when parsing
+ * configuration descriptors.
+ *
+ * Matched for devices with USB_QUIRK_ENDPOINT_BLACKLIST.
+ */
+static const struct usb_device_id usb_endpoint_blacklist[] = {
+       { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 },
+       { }
+};
+
+bool usb_endpoint_is_blacklisted(struct usb_device *udev,
+               struct usb_host_interface *intf,
+               struct usb_endpoint_descriptor *epd)
+{
+       const struct usb_device_id *id;
+       unsigned int address;
+
+       for (id = usb_endpoint_blacklist; id->match_flags; ++id) {
+               if (!usb_match_device(udev, id))
+                       continue;
+
+               if (!usb_match_one_id_intf(udev, intf, id))
+                       continue;
+
+               address = id->driver_info;
+               if (address == epd->bEndpointAddress)
+                       return true;
+       }
+
+       return false;
+}
+
 static bool usb_match_any_interface(struct usb_device *udev,
                                    const struct usb_device_id *id)
 {
index cf4783c..3ad0ee5 100644 (file)
@@ -37,6 +37,9 @@ extern void usb_authorize_interface(struct usb_interface *);
 extern void usb_detect_quirks(struct usb_device *udev);
 extern void usb_detect_interface_quirks(struct usb_device *udev);
 extern void usb_release_quirk_list(void);
+extern bool usb_endpoint_is_blacklisted(struct usb_device *udev,
+               struct usb_host_interface *intf,
+               struct usb_endpoint_descriptor *epd);
 extern int usb_remove_device(struct usb_device *udev);
 
 extern int usb_get_device_descriptor(struct usb_device *dev,
index 88f7d6d..92ed32e 100644 (file)
@@ -1083,11 +1083,6 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
        else
                packets = 1;    /* send one packet if length is zero. */
 
-       if (hs_ep->isochronous && length > (hs_ep->mc * hs_ep->ep.maxpacket)) {
-               dev_err(hsotg->dev, "req length > maxpacket*mc\n");
-               return;
-       }
-
        if (dir_in && index != 0)
                if (hs_ep->isochronous)
                        epsize = DXEPTSIZ_MC(packets);
@@ -1391,6 +1386,13 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
        req->actual = 0;
        req->status = -EINPROGRESS;
 
+       /* Don't queue ISOC request if length greater than mps*mc */
+       if (hs_ep->isochronous &&
+           req->length > (hs_ep->mc * hs_ep->ep.maxpacket)) {
+               dev_err(hs->dev, "req length > maxpacket*mc\n");
+               return -EINVAL;
+       }
+
        /* In DDMA mode for ISOC's don't queue request if length greater
         * than descriptor limits.
         */
@@ -1632,6 +1634,7 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
        struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
        struct dwc2_hsotg_ep *ep;
        __le16 reply;
+       u16 status;
        int ret;
 
        dev_dbg(hsotg->dev, "%s: USB_REQ_GET_STATUS\n", __func__);
@@ -1643,11 +1646,10 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
 
        switch (ctrl->bRequestType & USB_RECIP_MASK) {
        case USB_RECIP_DEVICE:
-               /*
-                * bit 0 => self powered
-                * bit 1 => remote wakeup
-                */
-               reply = cpu_to_le16(0);
+               status = 1 << USB_DEVICE_SELF_POWERED;
+               status |= hsotg->remote_wakeup_allowed <<
+                         USB_DEVICE_REMOTE_WAKEUP;
+               reply = cpu_to_le16(status);
                break;
 
        case USB_RECIP_INTERFACE:
@@ -1758,7 +1760,10 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
        case USB_RECIP_DEVICE:
                switch (wValue) {
                case USB_DEVICE_REMOTE_WAKEUP:
-                       hsotg->remote_wakeup_allowed = 1;
+                       if (set)
+                               hsotg->remote_wakeup_allowed = 1;
+                       else
+                               hsotg->remote_wakeup_allowed = 0;
                        break;
 
                case USB_DEVICE_TEST_MODE:
@@ -1768,16 +1773,17 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
                                return -EINVAL;
 
                        hsotg->test_mode = wIndex >> 8;
-                       ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
-                       if (ret) {
-                               dev_err(hsotg->dev,
-                                       "%s: failed to send reply\n", __func__);
-                               return ret;
-                       }
                        break;
                default:
                        return -ENOENT;
                }
+
+               ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
+               if (ret) {
+                       dev_err(hsotg->dev,
+                               "%s: failed to send reply\n", __func__);
+                       return ret;
+               }
                break;
 
        case USB_RECIP_ENDPOINT:
index e56beb9..4a13cea 100644 (file)
@@ -256,86 +256,77 @@ static inline const char *dwc3_ep_event_string(char *str, size_t size,
        u8 epnum = event->endpoint_number;
        size_t len;
        int status;
-       int ret;
 
-       ret = snprintf(str, size, "ep%d%s: ", epnum >> 1,
+       len = scnprintf(str, size, "ep%d%s: ", epnum >> 1,
                        (epnum & 1) ? "in" : "out");
-       if (ret < 0)
-               return "UNKNOWN";
 
        status = event->status;
 
        switch (event->endpoint_event) {
        case DWC3_DEPEVT_XFERCOMPLETE:
-               len = strlen(str);
-               snprintf(str + len, size - len, "Transfer Complete (%c%c%c)",
+               len += scnprintf(str + len, size - len,
+                               "Transfer Complete (%c%c%c)",
                                status & DEPEVT_STATUS_SHORT ? 'S' : 's',
                                status & DEPEVT_STATUS_IOC ? 'I' : 'i',
                                status & DEPEVT_STATUS_LST ? 'L' : 'l');
 
-               len = strlen(str);
-
                if (epnum <= 1)
-                       snprintf(str + len, size - len, " [%s]",
+                       scnprintf(str + len, size - len, " [%s]",
                                        dwc3_ep0_state_string(ep0state));
                break;
        case DWC3_DEPEVT_XFERINPROGRESS:
-               len = strlen(str);
-
-               snprintf(str + len, size - len, "Transfer In Progress [%d] (%c%c%c)",
+               scnprintf(str + len, size - len,
+                               "Transfer In Progress [%d] (%c%c%c)",
                                event->parameters,
                                status & DEPEVT_STATUS_SHORT ? 'S' : 's',
                                status & DEPEVT_STATUS_IOC ? 'I' : 'i',
                                status & DEPEVT_STATUS_LST ? 'M' : 'm');
                break;
        case DWC3_DEPEVT_XFERNOTREADY:
-               len = strlen(str);
-
-               snprintf(str + len, size - len, "Transfer Not Ready [%d]%s",
+               len += scnprintf(str + len, size - len,
+                               "Transfer Not Ready [%d]%s",
                                event->parameters,
                                status & DEPEVT_STATUS_TRANSFER_ACTIVE ?
                                " (Active)" : " (Not Active)");
 
-               len = strlen(str);
-
                /* Control Endpoints */
                if (epnum <= 1) {
                        int phase = DEPEVT_STATUS_CONTROL_PHASE(event->status);
 
                        switch (phase) {
                        case DEPEVT_STATUS_CONTROL_DATA:
-                               snprintf(str + ret, size - ret,
+                               scnprintf(str + len, size - len,
                                                " [Data Phase]");
                                break;
                        case DEPEVT_STATUS_CONTROL_STATUS:
-                               snprintf(str + ret, size - ret,
+                               scnprintf(str + len, size - len,
                                                " [Status Phase]");
                        }
                }
                break;
        case DWC3_DEPEVT_RXTXFIFOEVT:
-               snprintf(str + ret, size - ret, "FIFO");
+               scnprintf(str + len, size - len, "FIFO");
                break;
        case DWC3_DEPEVT_STREAMEVT:
                status = event->status;
 
                switch (status) {
                case DEPEVT_STREAMEVT_FOUND:
-                       snprintf(str + ret, size - ret, " Stream %d Found",
+                       scnprintf(str + len, size - len, " Stream %d Found",
                                        event->parameters);
                        break;
                case DEPEVT_STREAMEVT_NOTFOUND:
                default:
-                       snprintf(str + ret, size - ret, " Stream Not Found");
+                       scnprintf(str + len, size - len, " Stream Not Found");
                        break;
                }
 
                break;
        case DWC3_DEPEVT_EPCMDCMPLT:
-               snprintf(str + ret, size - ret, "Endpoint Command Complete");
+               scnprintf(str + len, size - len, "Endpoint Command Complete");
                break;
        default:
-               snprintf(str, size, "UNKNOWN");
+               scnprintf(str + len, size - len, "UNKNOWN");
        }
 
        return str;
index 1b8014a..1b7d2f9 100644 (file)
@@ -2429,7 +2429,8 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
        if (event->status & DEPEVT_STATUS_SHORT && !chain)
                return 1;
 
-       if (event->status & DEPEVT_STATUS_IOC)
+       if ((trb->ctrl & DWC3_TRB_CTRL_IOC) ||
+           (trb->ctrl & DWC3_TRB_CTRL_LST))
                return 1;
 
        return 0;
index 3b4f670..223f72d 100644 (file)
@@ -437,12 +437,14 @@ static u8 encode_bMaxPower(enum usb_device_speed speed,
                val = CONFIG_USB_GADGET_VBUS_DRAW;
        if (!val)
                return 0;
-       switch (speed) {
-       case USB_SPEED_SUPER:
-               return DIV_ROUND_UP(val, 8);
-       default:
-               return DIV_ROUND_UP(val, 2);
-       }
+       if (speed < USB_SPEED_SUPER)
+               return min(val, 500U) / 2;
+       else
+               /*
+                * USB 3.x supports up to 900mA, but since 900 isn't divisible
+                * by 8 the integral division will effectively cap to 896mA.
+                */
+               return min(val, 900U) / 8;
 }
 
 static int config_buf(struct usb_configuration *config,
@@ -854,6 +856,10 @@ static int set_config(struct usb_composite_dev *cdev,
 
        /* when we return, be sure our power usage is valid */
        power = c->MaxPower ? c->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW;
+       if (gadget->speed < USB_SPEED_SUPER)
+               power = min(power, 500U);
+       else
+               power = min(power, 900U);
 done:
        usb_gadget_vbus_draw(gadget, power);
        if (result >= 0 && cdev->delayed_status)
@@ -2280,7 +2286,7 @@ void composite_resume(struct usb_gadget *gadget)
 {
        struct usb_composite_dev        *cdev = get_gadget_data(gadget);
        struct usb_function             *f;
-       u16                             maxpower;
+       unsigned                        maxpower;
 
        /* REVISIT:  should we have config level
         * suspend/resume callbacks?
@@ -2294,10 +2300,14 @@ void composite_resume(struct usb_gadget *gadget)
                                f->resume(f);
                }
 
-               maxpower = cdev->config->MaxPower;
+               maxpower = cdev->config->MaxPower ?
+                       cdev->config->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW;
+               if (gadget->speed < USB_SPEED_SUPER)
+                       maxpower = min(maxpower, 500U);
+               else
+                       maxpower = min(maxpower, 900U);
 
-               usb_gadget_vbus_draw(gadget, maxpower ?
-                       maxpower : CONFIG_USB_GADGET_VBUS_DRAW);
+               usb_gadget_vbus_draw(gadget, maxpower);
        }
 
        cdev->suspended = 0;
index 6171d28..5719176 100644 (file)
@@ -1162,18 +1162,19 @@ static int ffs_aio_cancel(struct kiocb *kiocb)
 {
        struct ffs_io_data *io_data = kiocb->private;
        struct ffs_epfile *epfile = kiocb->ki_filp->private_data;
+       unsigned long flags;
        int value;
 
        ENTER();
 
-       spin_lock_irq(&epfile->ffs->eps_lock);
+       spin_lock_irqsave(&epfile->ffs->eps_lock, flags);
 
        if (likely(io_data && io_data->ep && io_data->req))
                value = usb_ep_dequeue(io_data->ep, io_data->req);
        else
                value = -EINVAL;
 
-       spin_unlock_irq(&epfile->ffs->eps_lock);
+       spin_unlock_irqrestore(&epfile->ffs->eps_lock, flags);
 
        return value;
 }
index 6d956f1..e6d32c5 100644 (file)
@@ -361,7 +361,7 @@ int u_audio_start_capture(struct g_audio *audio_dev)
        ep = audio_dev->out_ep;
        prm = &uac->c_prm;
        config_ep_by_speed(gadget, &audio_dev->func, ep);
-       req_len = prm->max_psize;
+       req_len = ep->maxpacket;
 
        prm->ep_enabled = true;
        usb_ep_enable(ep);
@@ -379,7 +379,7 @@ int u_audio_start_capture(struct g_audio *audio_dev)
                        req->context = &prm->ureq[i];
                        req->length = req_len;
                        req->complete = u_audio_iso_complete;
-                       req->buf = prm->rbuf + i * prm->max_psize;
+                       req->buf = prm->rbuf + i * ep->maxpacket;
                }
 
                if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
@@ -430,9 +430,9 @@ int u_audio_start_playback(struct g_audio *audio_dev)
        uac->p_pktsize = min_t(unsigned int,
                                uac->p_framesize *
                                        (params->p_srate / uac->p_interval),
-                               prm->max_psize);
+                               ep->maxpacket);
 
-       if (uac->p_pktsize < prm->max_psize)
+       if (uac->p_pktsize < ep->maxpacket)
                uac->p_pktsize_residue = uac->p_framesize *
                        (params->p_srate % uac->p_interval);
        else
@@ -457,7 +457,7 @@ int u_audio_start_playback(struct g_audio *audio_dev)
                        req->context = &prm->ureq[i];
                        req->length = req_len;
                        req->complete = u_audio_iso_complete;
-                       req->buf = prm->rbuf + i * prm->max_psize;
+                       req->buf = prm->rbuf + i * ep->maxpacket;
                }
 
                if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
index f986e5c..8167d37 100644 (file)
@@ -561,8 +561,10 @@ static int gs_start_io(struct gs_port *port)
        port->n_read = 0;
        started = gs_start_rx(port);
 
-       /* unblock any pending writes into our circular buffer */
        if (started) {
+               gs_start_tx(port);
+               /* Unblock any pending writes into our circular buffer, in case
+                * we didn't in gs_start_tx() */
                tty_wakeup(port->port.tty);
        } else {
                gs_free_requests(ep, head, &port->read_allocated);
index 29d8e5f..b1cfc82 100644 (file)
@@ -1399,7 +1399,6 @@ err:
 /**
  * xudc_stop - stops the device.
  * @gadget: pointer to the usb gadget structure
- * @driver: pointer to usb gadget driver structure
  *
  * Return: zero always
  */
index 7a3a29e..af92b25 100644 (file)
@@ -55,6 +55,7 @@ static u8 usb_bos_descriptor [] = {
 static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
                                     u16 wLength)
 {
+       struct xhci_port_cap *port_cap = NULL;
        int i, ssa_count;
        u32 temp;
        u16 desc_size, ssp_cap_size, ssa_size = 0;
@@ -64,16 +65,24 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
        ssp_cap_size = sizeof(usb_bos_descriptor) - desc_size;
 
        /* does xhci support USB 3.1 Enhanced SuperSpeed */
-       if (xhci->usb3_rhub.min_rev >= 0x01) {
+       for (i = 0; i < xhci->num_port_caps; i++) {
+               if (xhci->port_caps[i].maj_rev == 0x03 &&
+                   xhci->port_caps[i].min_rev >= 0x01) {
+                       usb3_1 = true;
+                       port_cap = &xhci->port_caps[i];
+                       break;
+               }
+       }
+
+       if (usb3_1) {
                /* does xhci provide a PSI table for SSA speed attributes? */
-               if (xhci->usb3_rhub.psi_count) {
+               if (port_cap->psi_count) {
                        /* two SSA entries for each unique PSI ID, RX and TX */
-                       ssa_count = xhci->usb3_rhub.psi_uid_count * 2;
+                       ssa_count = port_cap->psi_uid_count * 2;
                        ssa_size = ssa_count * sizeof(u32);
                        ssp_cap_size -= 16; /* skip copying the default SSA */
                }
                desc_size += ssp_cap_size;
-               usb3_1 = true;
        }
        memcpy(buf, &usb_bos_descriptor, min(desc_size, wLength));
 
@@ -99,7 +108,7 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
        }
 
        /* If PSI table exists, add the custom speed attributes from it */
-       if (usb3_1 && xhci->usb3_rhub.psi_count) {
+       if (usb3_1 && port_cap->psi_count) {
                u32 ssp_cap_base, bm_attrib, psi, psi_mant, psi_exp;
                int offset;
 
@@ -111,7 +120,7 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
 
                /* attribute count SSAC bits 4:0 and ID count SSIC bits 8:5 */
                bm_attrib = (ssa_count - 1) & 0x1f;
-               bm_attrib |= (xhci->usb3_rhub.psi_uid_count - 1) << 5;
+               bm_attrib |= (port_cap->psi_uid_count - 1) << 5;
                put_unaligned_le32(bm_attrib, &buf[ssp_cap_base + 4]);
 
                if (wLength < desc_size + ssa_size)
@@ -124,8 +133,8 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
                 * USB 3.1 requires two SSA entries (RX and TX) for every link
                 */
                offset = desc_size;
-               for (i = 0; i < xhci->usb3_rhub.psi_count; i++) {
-                       psi = xhci->usb3_rhub.psi[i];
+               for (i = 0; i < port_cap->psi_count; i++) {
+                       psi = port_cap->psi[i];
                        psi &= ~USB_SSP_SUBLINK_SPEED_RSVD;
                        psi_exp = XHCI_EXT_PORT_PSIE(psi);
                        psi_mant = XHCI_EXT_PORT_PSIM(psi);
index 3b1388f..884c601 100644 (file)
@@ -1475,9 +1475,15 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
        /* Allow 3 retries for everything but isoc, set CErr = 3 */
        if (!usb_endpoint_xfer_isoc(&ep->desc))
                err_count = 3;
-       /* Some devices get this wrong */
-       if (usb_endpoint_xfer_bulk(&ep->desc) && udev->speed == USB_SPEED_HIGH)
-               max_packet = 512;
+       /* HS bulk max packet should be 512, FS bulk supports 8, 16, 32 or 64 */
+       if (usb_endpoint_xfer_bulk(&ep->desc)) {
+               if (udev->speed == USB_SPEED_HIGH)
+                       max_packet = 512;
+               if (udev->speed == USB_SPEED_FULL) {
+                       max_packet = rounddown_pow_of_two(max_packet);
+                       max_packet = clamp_val(max_packet, 8, 64);
+               }
+       }
        /* xHCI 1.0 and 1.1 indicates that ctrl ep avg TRB Length should be 8 */
        if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
                avg_trb_len = 8;
@@ -1909,17 +1915,17 @@ no_bw:
        xhci->usb3_rhub.num_ports = 0;
        xhci->num_active_eps = 0;
        kfree(xhci->usb2_rhub.ports);
-       kfree(xhci->usb2_rhub.psi);
        kfree(xhci->usb3_rhub.ports);
-       kfree(xhci->usb3_rhub.psi);
        kfree(xhci->hw_ports);
        kfree(xhci->rh_bw);
        kfree(xhci->ext_caps);
+       for (i = 0; i < xhci->num_port_caps; i++)
+               kfree(xhci->port_caps[i].psi);
+       kfree(xhci->port_caps);
+       xhci->num_port_caps = 0;
 
        xhci->usb2_rhub.ports = NULL;
-       xhci->usb2_rhub.psi = NULL;
        xhci->usb3_rhub.ports = NULL;
-       xhci->usb3_rhub.psi = NULL;
        xhci->hw_ports = NULL;
        xhci->rh_bw = NULL;
        xhci->ext_caps = NULL;
@@ -2120,6 +2126,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
        u8 major_revision, minor_revision;
        struct xhci_hub *rhub;
        struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
+       struct xhci_port_cap *port_cap;
 
        temp = readl(addr);
        major_revision = XHCI_EXT_PORT_MAJOR(temp);
@@ -2154,31 +2161,39 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
                /* WTF? "Valid values are ‘1’ to MaxPorts" */
                return;
 
-       rhub->psi_count = XHCI_EXT_PORT_PSIC(temp);
-       if (rhub->psi_count) {
-               rhub->psi = kcalloc_node(rhub->psi_count, sizeof(*rhub->psi),
-                                   GFP_KERNEL, dev_to_node(dev));
-               if (!rhub->psi)
-                       rhub->psi_count = 0;
+       port_cap = &xhci->port_caps[xhci->num_port_caps++];
+       if (xhci->num_port_caps > max_caps)
+               return;
+
+       port_cap->maj_rev = major_revision;
+       port_cap->min_rev = minor_revision;
+       port_cap->psi_count = XHCI_EXT_PORT_PSIC(temp);
 
-               rhub->psi_uid_count++;
-               for (i = 0; i < rhub->psi_count; i++) {
-                       rhub->psi[i] = readl(addr + 4 + i);
+       if (port_cap->psi_count) {
+               port_cap->psi = kcalloc_node(port_cap->psi_count,
+                                            sizeof(*port_cap->psi),
+                                            GFP_KERNEL, dev_to_node(dev));
+               if (!port_cap->psi)
+                       port_cap->psi_count = 0;
+
+               port_cap->psi_uid_count++;
+               for (i = 0; i < port_cap->psi_count; i++) {
+                       port_cap->psi[i] = readl(addr + 4 + i);
 
                        /* count unique ID values, two consecutive entries can
                         * have the same ID if link is assymetric
                         */
-                       if (i && (XHCI_EXT_PORT_PSIV(rhub->psi[i]) !=
-                                 XHCI_EXT_PORT_PSIV(rhub->psi[i - 1])))
-                               rhub->psi_uid_count++;
+                       if (i && (XHCI_EXT_PORT_PSIV(port_cap->psi[i]) !=
+                                 XHCI_EXT_PORT_PSIV(port_cap->psi[i - 1])))
+                               port_cap->psi_uid_count++;
 
                        xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n",
-                                 XHCI_EXT_PORT_PSIV(rhub->psi[i]),
-                                 XHCI_EXT_PORT_PSIE(rhub->psi[i]),
-                                 XHCI_EXT_PORT_PLT(rhub->psi[i]),
-                                 XHCI_EXT_PORT_PFD(rhub->psi[i]),
-                                 XHCI_EXT_PORT_LP(rhub->psi[i]),
-                                 XHCI_EXT_PORT_PSIM(rhub->psi[i]));
+                                 XHCI_EXT_PORT_PSIV(port_cap->psi[i]),
+                                 XHCI_EXT_PORT_PSIE(port_cap->psi[i]),
+                                 XHCI_EXT_PORT_PLT(port_cap->psi[i]),
+                                 XHCI_EXT_PORT_PFD(port_cap->psi[i]),
+                                 XHCI_EXT_PORT_LP(port_cap->psi[i]),
+                                 XHCI_EXT_PORT_PSIM(port_cap->psi[i]));
                }
        }
        /* cache usb2 port capabilities */
@@ -2213,6 +2228,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
                        continue;
                }
                hw_port->rhub = rhub;
+               hw_port->port_cap = port_cap;
                rhub->num_ports++;
        }
        /* FIXME: Should we disable ports not in the Extended Capabilities? */
@@ -2303,6 +2319,11 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
        if (!xhci->ext_caps)
                return -ENOMEM;
 
+       xhci->port_caps = kcalloc_node(cap_count, sizeof(*xhci->port_caps),
+                               flags, dev_to_node(dev));
+       if (!xhci->port_caps)
+               return -ENOMEM;
+
        offset = cap_start;
 
        while (offset) {
index 4917c5b..5e9b537 100644 (file)
@@ -49,6 +49,7 @@
 #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_XHCI                0x15ec
 #define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI                0x15f0
 #define PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI              0x8a13
+#define PCI_DEVICE_ID_INTEL_CML_XHCI                   0xa3af
 
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_4                        0x43b9
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_3                        0x43ba
@@ -187,7 +188,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                 pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI ||
                 pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI ||
                 pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI ||
-                pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) {
+                pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI ||
+                pdev->device == PCI_DEVICE_ID_INTEL_CML_XHCI)) {
                xhci->quirks |= XHCI_PME_STUCK_QUIRK;
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
@@ -302,6 +304,9 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
        if (!usb_hcd_is_primary_hcd(hcd))
                return 0;
 
+       if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
+               xhci_pme_acpi_rtd3_enable(pdev);
+
        xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn);
 
        /* Find any debug ports */
@@ -359,9 +364,6 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
                        HCC_MAX_PSA(xhci->hcc_params) >= 4)
                xhci->shared_hcd->can_do_streams = 1;
 
-       if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
-               xhci_pme_acpi_rtd3_enable(dev);
-
        /* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
        pm_runtime_put_noidle(&dev->dev);
 
index 13d8838..3ecee10 100644 (file)
@@ -1702,12 +1702,20 @@ struct xhci_bus_state {
  * Intel Lynx Point LP xHCI host.
  */
 #define        XHCI_MAX_REXIT_TIMEOUT_MS       20
+struct xhci_port_cap {
+       u32                     *psi;   /* array of protocol speed ID entries */
+       u8                      psi_count;
+       u8                      psi_uid_count;
+       u8                      maj_rev;
+       u8                      min_rev;
+};
 
 struct xhci_port {
        __le32 __iomem          *addr;
        int                     hw_portnum;
        int                     hcd_portnum;
        struct xhci_hub         *rhub;
+       struct xhci_port_cap    *port_cap;
 };
 
 struct xhci_hub {
@@ -1719,9 +1727,6 @@ struct xhci_hub {
        /* supported prococol extended capabiliy values */
        u8                      maj_rev;
        u8                      min_rev;
-       u32                     *psi;   /* array of protocol speed ID entries */
-       u8                      psi_count;
-       u8                      psi_uid_count;
 };
 
 /* There is one xhci_hcd structure per controller */
@@ -1880,6 +1885,9 @@ struct xhci_hcd {
        /* cached usb2 extened protocol capabilites */
        u32                     *ext_caps;
        unsigned int            num_ext_caps;
+       /* cached extended protocol port capabilities */
+       struct xhci_port_cap    *port_caps;
+       unsigned int            num_port_caps;
        /* Compliance Mode Recovery Data */
        struct timer_list       comp_mode_recovery_timer;
        u32                     port_status_u0;
index dce44fb..dce2030 100644 (file)
 #define USB_DEVICE_ID_CODEMERCS_IOWPV2 0x1512
 /* full speed iowarrior */
 #define USB_DEVICE_ID_CODEMERCS_IOW56  0x1503
+/* fuller speed iowarrior */
+#define USB_DEVICE_ID_CODEMERCS_IOW28  0x1504
+#define USB_DEVICE_ID_CODEMERCS_IOW28L 0x1505
+#define USB_DEVICE_ID_CODEMERCS_IOW100 0x1506
+
+/* OEMed devices */
+#define USB_DEVICE_ID_CODEMERCS_IOW24SAG       0x158a
+#define USB_DEVICE_ID_CODEMERCS_IOW56AM                0x158b
 
 /* Get a minor range for your devices from the usb maintainer */
 #ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -133,6 +141,11 @@ static const struct usb_device_id iowarrior_ids[] = {
        {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV1)},
        {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV2)},
        {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24SAG)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56AM)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28L)},
+       {USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW100)},
        {}                      /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, iowarrior_ids);
@@ -357,6 +370,7 @@ static ssize_t iowarrior_write(struct file *file,
        }
        switch (dev->product_id) {
        case USB_DEVICE_ID_CODEMERCS_IOW24:
+       case USB_DEVICE_ID_CODEMERCS_IOW24SAG:
        case USB_DEVICE_ID_CODEMERCS_IOWPV1:
        case USB_DEVICE_ID_CODEMERCS_IOWPV2:
        case USB_DEVICE_ID_CODEMERCS_IOW40:
@@ -371,6 +385,10 @@ static ssize_t iowarrior_write(struct file *file,
                goto exit;
                break;
        case USB_DEVICE_ID_CODEMERCS_IOW56:
+       case USB_DEVICE_ID_CODEMERCS_IOW56AM:
+       case USB_DEVICE_ID_CODEMERCS_IOW28:
+       case USB_DEVICE_ID_CODEMERCS_IOW28L:
+       case USB_DEVICE_ID_CODEMERCS_IOW100:
                /* The IOW56 uses asynchronous IO and more urbs */
                if (atomic_read(&dev->write_busy) == MAX_WRITES_IN_FLIGHT) {
                        /* Wait until we are below the limit for submitted urbs */
@@ -493,6 +511,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd,
        switch (cmd) {
        case IOW_WRITE:
                if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW24 ||
+                   dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW24SAG ||
                    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV1 ||
                    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV2 ||
                    dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW40) {
@@ -767,7 +786,11 @@ static int iowarrior_probe(struct usb_interface *interface,
                goto error;
        }
 
-       if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) {
+       if ((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) ||
+           (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM) ||
+           (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28) ||
+           (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L) ||
+           (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW100)) {
                res = usb_find_last_int_out_endpoint(iface_desc,
                                &dev->int_out_endpoint);
                if (res) {
@@ -780,7 +803,11 @@ static int iowarrior_probe(struct usb_interface *interface,
        /* we have to check the report_size often, so remember it in the endianness suitable for our machine */
        dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint);
        if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) &&
-           (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56))
+           ((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) ||
+            (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM) ||
+            (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28) ||
+            (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L) ||
+            (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW100)))
                /* IOWarrior56 has wMaxPacketSize different from report size */
                dev->report_size = 7;
 
index 037e8ee..6153cc3 100644 (file)
@@ -969,6 +969,10 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
                return  -ENXIO;
        }
 
+       /*
+        * Note that UTMI pad registers are shared by all PHYs, therefore
+        * devm_platform_ioremap_resource() can't be used here.
+        */
        tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
                                           resource_size(res));
        if (!tegra_phy->pad_regs) {
@@ -1087,6 +1091,10 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
                return  -ENXIO;
        }
 
+       /*
+        * Note that PHY and USB controller are using shared registers,
+        * therefore devm_platform_ioremap_resource() can't be used here.
+        */
        tegra_phy->regs = devm_ioremap(&pdev->dev, res->start,
                                       resource_size(res));
        if (!tegra_phy->regs) {
index d3f420f..c5ecdcd 100644 (file)
@@ -205,6 +205,16 @@ static int ch341_get_divisor(speed_t speed)
                        16 * speed - 16 * CH341_CLKRATE / (clk_div * (div + 1)))
                div++;
 
+       /*
+        * Prefer lower base clock (fact = 0) if even divisor.
+        *
+        * Note that this makes the receiver more tolerant to errors.
+        */
+       if (fact == 1 && div % 2 == 0) {
+               div /= 2;
+               fact = 0;
+       }
+
        return (0x100 - div) << 8 | fact << 2 | ps;
 }
 
index 79d0586..172261a 100644 (file)
@@ -448,7 +448,7 @@ static void ir_set_termios(struct tty_struct *tty,
                        usb_sndbulkpipe(udev, port->bulk_out_endpointAddress),
                        transfer_buffer, 1, &actual_length, 5000);
        if (ret || actual_length != 1) {
-               if (actual_length != 1)
+               if (!ret)
                        ret = -EIO;
                dev_err(&port->dev, "failed to change line speed: %d\n", ret);
        }
index 95bba3b..3670fda 100644 (file)
@@ -45,6 +45,7 @@ struct uas_dev_info {
        struct scsi_cmnd *cmnd[MAX_CMNDS];
        spinlock_t lock;
        struct work_struct work;
+       struct work_struct scan_work;      /* for async scanning */
 };
 
 enum {
@@ -114,6 +115,17 @@ out:
        spin_unlock_irqrestore(&devinfo->lock, flags);
 }
 
+static void uas_scan_work(struct work_struct *work)
+{
+       struct uas_dev_info *devinfo =
+               container_of(work, struct uas_dev_info, scan_work);
+       struct Scsi_Host *shost = usb_get_intfdata(devinfo->intf);
+
+       dev_dbg(&devinfo->intf->dev, "starting scan\n");
+       scsi_scan_host(shost);
+       dev_dbg(&devinfo->intf->dev, "scan complete\n");
+}
+
 static void uas_add_work(struct uas_cmd_info *cmdinfo)
 {
        struct scsi_pointer *scp = (void *)cmdinfo;
@@ -982,6 +994,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
        init_usb_anchor(&devinfo->data_urbs);
        spin_lock_init(&devinfo->lock);
        INIT_WORK(&devinfo->work, uas_do_work);
+       INIT_WORK(&devinfo->scan_work, uas_scan_work);
 
        result = uas_configure_endpoints(devinfo);
        if (result)
@@ -998,7 +1011,9 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
        if (result)
                goto free_streams;
 
-       scsi_scan_host(shost);
+       /* Submit the delayed_work for SCSI-device scanning */
+       schedule_work(&devinfo->scan_work);
+
        return result;
 
 free_streams:
@@ -1166,6 +1181,12 @@ static void uas_disconnect(struct usb_interface *intf)
        usb_kill_anchored_urbs(&devinfo->data_urbs);
        uas_zap_pending(devinfo, DID_NO_CONNECT);
 
+       /*
+        * Prevent SCSI scanning (if it hasn't started yet)
+        * or wait for the SCSI-scanning routine to stop.
+        */
+       cancel_work_sync(&devinfo->scan_work);
+
        scsi_remove_host(shost);
        uas_free_streams(devinfo);
        scsi_host_put(shost);
index cec868f..9ea2b43 100644 (file)
@@ -207,6 +207,7 @@ config DA9063_WATCHDOG
 config DA9062_WATCHDOG
        tristate "Dialog DA9062/61 Watchdog"
        depends on MFD_DA9062 || COMPILE_TEST
+       depends on I2C
        select WATCHDOG_CORE
        help
          Support for the watchdog in the DA9062 and DA9061 PMICs.
@@ -841,6 +842,7 @@ config MEDIATEK_WATCHDOG
        tristate "Mediatek SoCs watchdog support"
        depends on ARCH_MEDIATEK || COMPILE_TEST
        select WATCHDOG_CORE
+       select RESET_CONTROLLER
        help
          Say Y here to include support for the watchdog timer
          in Mediatek SoCs.
index 47eefe0..0ad15d5 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/jiffies.h>
 #include <linux/mfd/da9062/registers.h>
 #include <linux/mfd/da9062/core.h>
+#include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/of.h>
 
@@ -31,6 +32,7 @@ static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };
 struct da9062_watchdog {
        struct da9062 *hw;
        struct watchdog_device wdtdev;
+       bool use_sw_pm;
 };
 
 static unsigned int da9062_wdt_timeout_to_sel(unsigned int secs)
@@ -95,13 +97,6 @@ static int da9062_wdt_stop(struct watchdog_device *wdd)
        struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
        int ret;
 
-       ret = da9062_reset_watchdog_timer(wdt);
-       if (ret) {
-               dev_err(wdt->hw->dev, "Failed to ping the watchdog (err = %d)\n",
-                       ret);
-               return ret;
-       }
-
        ret = regmap_update_bits(wdt->hw->regmap,
                                 DA9062AA_CONTROL_D,
                                 DA9062AA_TWDSCALE_MASK,
@@ -200,6 +195,8 @@ static int da9062_wdt_probe(struct platform_device *pdev)
        if (!wdt)
                return -ENOMEM;
 
+       wdt->use_sw_pm = device_property_present(dev, "dlg,use-sw-pm");
+
        wdt->hw = chip;
 
        wdt->wdtdev.info = &da9062_watchdog_info;
@@ -226,6 +223,10 @@ static int da9062_wdt_probe(struct platform_device *pdev)
 static int __maybe_unused da9062_wdt_suspend(struct device *dev)
 {
        struct watchdog_device *wdd = dev_get_drvdata(dev);
+       struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
+
+       if (!wdt->use_sw_pm)
+               return 0;
 
        if (watchdog_active(wdd))
                return da9062_wdt_stop(wdd);
@@ -236,6 +237,10 @@ static int __maybe_unused da9062_wdt_suspend(struct device *dev)
 static int __maybe_unused da9062_wdt_resume(struct device *dev)
 {
        struct watchdog_device *wdd = dev_get_drvdata(dev);
+       struct da9062_watchdog *wdt = watchdog_get_drvdata(wdd);
+
+       if (!wdt->use_sw_pm)
+               return 0;
 
        if (watchdog_active(wdd))
                return da9062_wdt_start(wdd);
index 70650b2..17240c5 100644 (file)
@@ -33,7 +33,9 @@ asmlinkage __visible void xen_maybe_preempt_hcall(void)
                 * cpu.
                 */
                __this_cpu_write(xen_in_preemptible_hcall, false);
-               _cond_resched();
+               local_irq_enable();
+               cond_resched();
+               local_irq_disable();
                __this_cpu_write(xen_in_preemptible_hcall, true);
        }
 }
index 7d26b4b..36deef6 100644 (file)
@@ -4142,7 +4142,6 @@ search_again:
                goto out;
        }
 
-       path->leave_spinning = 1;
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
        if (ret < 0)
                goto out;
@@ -4294,7 +4293,6 @@ delete:
                     root == fs_info->tree_root)) {
                        struct btrfs_ref ref = { 0 };
 
-                       btrfs_set_path_blocking(path);
                        bytes_deleted += extent_num_bytes;
 
                        btrfs_init_generic_ref(&ref, BTRFS_DROP_DELAYED_REF,
index db1ef14..2c449ae 100644 (file)
@@ -311,8 +311,10 @@ static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
        struct extent_crypt_result ecr;
        int rc = 0;
 
-       BUG_ON(!crypt_stat || !crypt_stat->tfm
-              || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED));
+       if (!crypt_stat || !crypt_stat->tfm
+              || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED))
+               return -EINVAL;
+
        if (unlikely(ecryptfs_verbosity > 0)) {
                ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n",
                                crypt_stat->key_size);
index 1c1a56b..e6ac78c 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright (C) 2004-2008 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  *              Trevor S. Highland <trevor.highland@gmail.com>
- *              Tyler Hicks <tyhicks@ou.edu>
+ *              Tyler Hicks <code@tyhicks.com>
  */
 
 #ifndef ECRYPTFS_KERNEL_H
index 7d326aa..af3eb02 100644 (file)
@@ -1304,7 +1304,7 @@ parse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,
                printk(KERN_WARNING "Tag 1 packet contains key larger "
                       "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES\n");
                rc = -EINVAL;
-               goto out;
+               goto out_free;
        }
        memcpy((*new_auth_tok)->session_key.encrypted_key,
               &data[(*packet_size)], (body_size - (ECRYPTFS_SIG_SIZE + 2)));
index b8a7ce3..e63259f 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 2004-2007 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
  *              Michael C. Thompson <mcthomps@us.ibm.com>
- *              Tyler Hicks <tyhicks@ou.edu>
+ *              Tyler Hicks <code@tyhicks.com>
  */
 
 #include <linux/dcache.h>
index d668e60..8646ba7 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Copyright (C) 2004-2008 International Business Machines Corp.
  *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
- *             Tyler Hicks <tyhicks@ou.edu>
+ *             Tyler Hicks <code@tyhicks.com>
  */
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -379,6 +379,7 @@ int __init ecryptfs_init_messaging(void)
                                        * ecryptfs_message_buf_len),
                                       GFP_KERNEL);
        if (!ecryptfs_msg_ctx_arr) {
+               kfree(ecryptfs_daemon_hash);
                rc = -ENOMEM;
                goto out;
        }
index 5a82601..de650df 100644 (file)
@@ -1260,6 +1260,9 @@ static void __io_req_aux_free(struct io_kiocb *req)
 {
        struct io_ring_ctx *ctx = req->ctx;
 
+       if (req->flags & REQ_F_NEED_CLEANUP)
+               io_cleanup_req(req);
+
        kfree(req->io);
        if (req->file) {
                if (req->flags & REQ_F_FIXED_FILE)
@@ -1275,9 +1278,6 @@ static void __io_free_req(struct io_kiocb *req)
 {
        __io_req_aux_free(req);
 
-       if (req->flags & REQ_F_NEED_CLEANUP)
-               io_cleanup_req(req);
-
        if (req->flags & REQ_F_INFLIGHT) {
                struct io_ring_ctx *ctx = req->ctx;
                unsigned long flags;
@@ -1672,11 +1672,17 @@ static void io_iopoll_reap_events(struct io_ring_ctx *ctx)
        mutex_unlock(&ctx->uring_lock);
 }
 
-static int __io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
-                           long min)
+static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
+                          long min)
 {
        int iters = 0, ret = 0;
 
+       /*
+        * We disallow the app entering submit/complete with polling, but we
+        * still need to lock the ring to prevent racing with polled issue
+        * that got punted to a workqueue.
+        */
+       mutex_lock(&ctx->uring_lock);
        do {
                int tmin = 0;
 
@@ -1712,21 +1718,6 @@ static int __io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
                ret = 0;
        } while (min && !*nr_events && !need_resched());
 
-       return ret;
-}
-
-static int io_iopoll_check(struct io_ring_ctx *ctx, unsigned *nr_events,
-                          long min)
-{
-       int ret;
-
-       /*
-        * We disallow the app entering submit/complete with polling, but we
-        * still need to lock the ring to prevent racing with polled issue
-        * that got punted to a workqueue.
-        */
-       mutex_lock(&ctx->uring_lock);
-       ret = __io_iopoll_check(ctx, nr_events, min);
        mutex_unlock(&ctx->uring_lock);
        return ret;
 }
@@ -2517,6 +2508,9 @@ static void io_fallocate_finish(struct io_wq_work **workptr)
        struct io_kiocb *nxt = NULL;
        int ret;
 
+       if (io_req_cancelled(req))
+               return;
+
        ret = vfs_fallocate(req->file, req->sync.mode, req->sync.off,
                                req->sync.len);
        if (ret < 0)
@@ -2904,6 +2898,7 @@ static void io_close_finish(struct io_wq_work **workptr)
        struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work);
        struct io_kiocb *nxt = NULL;
 
+       /* not cancellable, don't do io_req_cancelled() */
        __io_close_finish(req, &nxt);
        if (nxt)
                io_wq_assign_next(workptr, nxt);
@@ -3071,7 +3066,7 @@ static int io_sendmsg(struct io_kiocb *req, struct io_kiocb **nxt,
                        if (req->io)
                                return -EAGAIN;
                        if (io_alloc_async_ctx(req)) {
-                               if (kmsg && kmsg->iov != kmsg->fast_iov)
+                               if (kmsg->iov != kmsg->fast_iov)
                                        kfree(kmsg->iov);
                                return -ENOMEM;
                        }
@@ -3225,7 +3220,7 @@ static int io_recvmsg(struct io_kiocb *req, struct io_kiocb **nxt,
                        if (req->io)
                                return -EAGAIN;
                        if (io_alloc_async_ctx(req)) {
-                               if (kmsg && kmsg->iov != kmsg->fast_iov)
+                               if (kmsg->iov != kmsg->fast_iov)
                                        kfree(kmsg->iov);
                                return -ENOMEM;
                        }
@@ -5114,7 +5109,7 @@ static int io_sq_thread(void *data)
                                 */
                                mutex_lock(&ctx->uring_lock);
                                if (!list_empty(&ctx->poll_list))
-                                       __io_iopoll_check(ctx, &nr_events, 0);
+                                       io_iopoll_getevents(ctx, &nr_events, 0);
                                else
                                        inflight = 0;
                                mutex_unlock(&ctx->uring_lock);
@@ -5138,6 +5133,18 @@ static int io_sq_thread(void *data)
                 * to enter the kernel to reap and flush events.
                 */
                if (!to_submit || ret == -EBUSY) {
+                       /*
+                        * Drop cur_mm before scheduling, we can't hold it for
+                        * long periods (or over schedule()). Do this before
+                        * adding ourselves to the waitqueue, as the unuse/drop
+                        * may sleep.
+                        */
+                       if (cur_mm) {
+                               unuse_mm(cur_mm);
+                               mmput(cur_mm);
+                               cur_mm = NULL;
+                       }
+
                        /*
                         * We're polling. If we're within the defined idle
                         * period, then let us spin without work before going
@@ -5152,18 +5159,6 @@ static int io_sq_thread(void *data)
                                continue;
                        }
 
-                       /*
-                        * Drop cur_mm before scheduling, we can't hold it for
-                        * long periods (or over schedule()). Do this before
-                        * adding ourselves to the waitqueue, as the unuse/drop
-                        * may sleep.
-                        */
-                       if (cur_mm) {
-                               unuse_mm(cur_mm);
-                               mmput(cur_mm);
-                               cur_mm = NULL;
-                       }
-
                        prepare_to_wait(&ctx->sqo_wait, &wait,
                                                TASK_INTERRUPTIBLE);
 
index 5a34d6c..2144507 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -722,9 +722,10 @@ pipe_release(struct inode *inode, struct file *file)
        if (file->f_mode & FMODE_WRITE)
                pipe->writers--;
 
-       if (pipe->readers || pipe->writers) {
-               wake_up_interruptible_sync_poll(&pipe->rd_wait, EPOLLIN | EPOLLRDNORM | EPOLLERR | EPOLLHUP);
-               wake_up_interruptible_sync_poll(&pipe->wr_wait, EPOLLOUT | EPOLLWRNORM | EPOLLERR | EPOLLHUP);
+       /* Was that the last reader or writer, but not the other side? */
+       if (!pipe->readers != !pipe->writers) {
+               wake_up_interruptible_all(&pipe->rd_wait);
+               wake_up_interruptible_all(&pipe->wr_wait);
                kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
                kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
        }
@@ -1026,8 +1027,8 @@ static int wait_for_partner(struct pipe_inode_info *pipe, unsigned int *cnt)
 
 static void wake_up_partner(struct pipe_inode_info *pipe)
 {
-       wake_up_interruptible(&pipe->rd_wait);
-       wake_up_interruptible(&pipe->wr_wait);
+       wake_up_interruptible_all(&pipe->rd_wait);
+       wake_up_interruptible_all(&pipe->wr_wait);
 }
 
 static int fifo_open(struct inode *inode, struct file *filp)
@@ -1144,7 +1145,7 @@ err_rd:
 
 err_wr:
        if (!--pipe->writers)
-               wake_up_interruptible(&pipe->rd_wait);
+               wake_up_interruptible_all(&pipe->rd_wait);
        ret = -ERESTARTSYS;
        goto err;
 
@@ -1271,8 +1272,9 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
        pipe->max_usage = nr_slots;
        pipe->tail = tail;
        pipe->head = head;
-       wake_up_interruptible_all(&pipe->rd_wait);
-       wake_up_interruptible_all(&pipe->wr_wait);
+
+       /* This might have made more room for writers */
+       wake_up_interruptible(&pipe->wr_wait);
        return pipe->max_usage * PAGE_SIZE;
 
 out_revert_acct:
index 5867777..8e8be98 100644 (file)
@@ -753,6 +753,7 @@ ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_disable_all_gpes(void))
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_runtime_gpes(void))
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status acpi_enable_all_wakeup_gpes(void))
 ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_any_gpe_status_set(void))
+ACPI_HW_DEPENDENT_RETURN_UINT32(u32 acpi_any_fixed_event_status_set(void))
 
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                acpi_get_gpe_device(u32 gpe_index,
index 11083d8..df2475b 100644 (file)
@@ -248,15 +248,6 @@ typedef struct compat_siginfo {
        } _sifields;
 } compat_siginfo_t;
 
-/*
- * These functions operate on 32- or 64-bit specs depending on
- * COMPAT_USE_64BIT_TIME, hence the void user pointer arguments.
- */
-extern int compat_get_timespec(struct timespec *, const void __user *);
-extern int compat_put_timespec(const struct timespec *, void __user *);
-extern int compat_get_timeval(struct timeval *, const void __user *);
-extern int compat_put_timeval(const struct timeval *, void __user *);
-
 struct compat_iovec {
        compat_uptr_t   iov_base;
        compat_size_t   iov_len;
@@ -416,26 +407,6 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *to, const kernel_siginf
 int get_compat_sigevent(struct sigevent *event,
                const struct compat_sigevent __user *u_event);
 
-static inline int old_timeval32_compare(struct old_timeval32 *lhs,
-                                       struct old_timeval32 *rhs)
-{
-       if (lhs->tv_sec < rhs->tv_sec)
-               return -1;
-       if (lhs->tv_sec > rhs->tv_sec)
-               return 1;
-       return lhs->tv_usec - rhs->tv_usec;
-}
-
-static inline int old_timespec32_compare(struct old_timespec32 *lhs,
-                                       struct old_timespec32 *rhs)
-{
-       if (lhs->tv_sec < rhs->tv_sec)
-               return -1;
-       if (lhs->tv_sec > rhs->tv_sec)
-               return 1;
-       return lhs->tv_nsec - rhs->tv_nsec;
-}
-
 extern int get_compat_sigset(sigset_t *set, const compat_sigset_t __user *compat);
 
 /*
index 94f047a..d7c403d 100644 (file)
@@ -122,7 +122,7 @@ static inline int intel_svm_unbind_mm(struct device *dev, int pasid)
        BUG();
 }
 
-static int intel_svm_is_pasid_valid(struct device *dev, int pasid)
+static inline int intel_svm_is_pasid_valid(struct device *dev, int pasid)
 {
        return -EINVAL;
 }
index b2d4757..8d062e8 100644 (file)
@@ -192,7 +192,7 @@ enum {
        IRQ_DOMAIN_FLAG_HIERARCHY       = (1 << 0),
 
        /* Irq domain name was allocated in __irq_domain_add() */
-       IRQ_DOMAIN_NAME_ALLOCATED       = (1 << 6),
+       IRQ_DOMAIN_NAME_ALLOCATED       = (1 << 1),
 
        /* Irq domain is an IPI domain with virq per cpu */
        IRQ_DOMAIN_FLAG_IPI_PER_CPU     = (1 << 2),
index b2bb44f..d1fb051 100644 (file)
@@ -66,33 +66,15 @@ static inline ktime_t ktime_set(const s64 secs, const unsigned long nsecs)
  */
 #define ktime_sub_ns(kt, nsval)                ((kt) - (nsval))
 
-/* convert a timespec to ktime_t format: */
-static inline ktime_t timespec_to_ktime(struct timespec ts)
-{
-       return ktime_set(ts.tv_sec, ts.tv_nsec);
-}
-
 /* convert a timespec64 to ktime_t format: */
 static inline ktime_t timespec64_to_ktime(struct timespec64 ts)
 {
        return ktime_set(ts.tv_sec, ts.tv_nsec);
 }
 
-/* convert a timeval to ktime_t format: */
-static inline ktime_t timeval_to_ktime(struct timeval tv)
-{
-       return ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC);
-}
-
-/* Map the ktime_t to timespec conversion to ns_to_timespec function */
-#define ktime_to_timespec(kt)          ns_to_timespec((kt))
-
 /* Map the ktime_t to timespec conversion to ns_to_timespec function */
 #define ktime_to_timespec64(kt)                ns_to_timespec64((kt))
 
-/* Map the ktime_t to timeval conversion to ns_to_timeval function */
-#define ktime_to_timeval(kt)           ns_to_timeval((kt))
-
 /* Convert ktime_t to nanoseconds */
 static inline s64 ktime_to_ns(const ktime_t kt)
 {
@@ -215,25 +197,6 @@ static inline ktime_t ktime_sub_ms(const ktime_t kt, const u64 msec)
 
 extern ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs);
 
-/**
- * ktime_to_timespec_cond - convert a ktime_t variable to timespec
- *                         format only if the variable contains data
- * @kt:                the ktime_t variable to convert
- * @ts:                the timespec variable to store the result in
- *
- * Return: %true if there was a successful conversion, %false if kt was 0.
- */
-static inline __must_check bool ktime_to_timespec_cond(const ktime_t kt,
-                                                      struct timespec *ts)
-{
-       if (kt) {
-               *ts = ktime_to_timespec(kt);
-               return true;
-       } else {
-               return false;
-       }
-}
-
 /**
  * ktime_to_timespec64_cond - convert a ktime_t variable to timespec64
  *                         format only if the variable contains data
index ff8c9d5..bfdf415 100644 (file)
@@ -688,7 +688,10 @@ struct mlx5_ifc_flow_table_nic_cap_bits {
        u8         nic_rx_multi_path_tirs[0x1];
        u8         nic_rx_multi_path_tirs_fts[0x1];
        u8         allow_sniffer_and_nic_rx_shared_tir[0x1];
-       u8         reserved_at_3[0x1d];
+       u8         reserved_at_3[0x4];
+       u8         sw_owner_reformat_supported[0x1];
+       u8         reserved_at_8[0x18];
+
        u8         encap_general_header[0x1];
        u8         reserved_at_21[0xa];
        u8         log_max_packet_reformat_context[0x5];
index 9f1f633..6c3f703 100644 (file)
@@ -72,6 +72,8 @@ void netdev_set_default_ethtool_ops(struct net_device *dev,
 #define NET_RX_SUCCESS         0       /* keep 'em coming, baby */
 #define NET_RX_DROP            1       /* packet dropped */
 
+#define MAX_NEST_DEV 8
+
 /*
  * Transmit return codes: transmit return codes originate from three different
  * namespaces:
@@ -4389,11 +4391,8 @@ void *netdev_lower_get_next(struct net_device *dev,
             ldev; \
             ldev = netdev_lower_get_next(dev, &(iter)))
 
-struct net_device *netdev_all_lower_get_next(struct net_device *dev,
+struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
                                             struct list_head **iter);
-struct net_device *netdev_all_lower_get_next_rcu(struct net_device *dev,
-                                                struct list_head **iter);
-
 int netdev_walk_all_lower_dev(struct net_device *dev,
                              int (*fn)(struct net_device *lower_dev,
                                        void *data),
index e5b7520..9670b54 100644 (file)
@@ -145,6 +145,13 @@ static inline void hlist_nulls_add_tail_rcu(struct hlist_nulls_node *n,
        }
 }
 
+/* after that hlist_nulls_del will work */
+static inline void hlist_nulls_add_fake(struct hlist_nulls_node *n)
+{
+       n->pprev = &n->next;
+       n->next = (struct hlist_nulls_node *)NULLS_MARKER(NULL);
+}
+
 /**
  * hlist_nulls_for_each_entry_rcu - iterate over rcu list of given type
  * @tpos:      the type * to use as a loop cursor.
index ca8806b..5b50278 100644 (file)
@@ -611,9 +611,15 @@ typedef unsigned char *sk_buff_data_t;
  *     @next: Next buffer in list
  *     @prev: Previous buffer in list
  *     @tstamp: Time we arrived/left
+ *     @skb_mstamp_ns: (aka @tstamp) earliest departure time; start point
+ *             for retransmit timer
  *     @rbnode: RB tree node, alternative to next/prev for netem/tcp
+ *     @list: queue head
  *     @sk: Socket we are owned by
+ *     @ip_defrag_offset: (aka @sk) alternate use of @sk, used in
+ *             fragmentation management
  *     @dev: Device we arrived on/are leaving by
+ *     @dev_scratch: (aka @dev) alternate use of @dev when @dev would be %NULL
  *     @cb: Control buffer. Free for use by every layer. Put private vars here
  *     @_skb_refdst: destination entry (with norefcount bit)
  *     @sp: the security path, used for xfrm
@@ -632,6 +638,9 @@ typedef unsigned char *sk_buff_data_t;
  *     @pkt_type: Packet class
  *     @fclone: skbuff clone status
  *     @ipvs_property: skbuff is owned by ipvs
+ *     @inner_protocol_type: whether the inner protocol is
+ *             ENCAP_TYPE_ETHER or ENCAP_TYPE_IPPROTO
+ *     @remcsum_offload: remote checksum offload is enabled
  *     @offload_fwd_mark: Packet was L2-forwarded in hardware
  *     @offload_l3_fwd_mark: Packet was L3-forwarded in hardware
  *     @tc_skip_classify: do not classify packet. set by IFB device
@@ -650,6 +659,8 @@ typedef unsigned char *sk_buff_data_t;
  *     @tc_index: Traffic control index
  *     @hash: the packet hash
  *     @queue_mapping: Queue mapping for multiqueue devices
+ *     @head_frag: skb was allocated from page fragments,
+ *             not allocated by kmalloc() or vmalloc().
  *     @pfmemalloc: skbuff was allocated from PFMEMALLOC reserves
  *     @active_extensions: active extensions (skb_ext_id types)
  *     @ndisc_nodetype: router type (from link layer)
@@ -660,15 +671,28 @@ typedef unsigned char *sk_buff_data_t;
  *     @wifi_acked_valid: wifi_acked was set
  *     @wifi_acked: whether frame was acked on wifi or not
  *     @no_fcs:  Request NIC to treat last 4 bytes as Ethernet FCS
+ *     @encapsulation: indicates the inner headers in the skbuff are valid
+ *     @encap_hdr_csum: software checksum is needed
+ *     @csum_valid: checksum is already valid
  *     @csum_not_inet: use CRC32c to resolve CHECKSUM_PARTIAL
+ *     @csum_complete_sw: checksum was completed by software
+ *     @csum_level: indicates the number of consecutive checksums found in
+ *             the packet minus one that have been verified as
+ *             CHECKSUM_UNNECESSARY (max 3)
  *     @dst_pending_confirm: need to confirm neighbour
  *     @decrypted: Decrypted SKB
  *     @napi_id: id of the NAPI struct this skb came from
+ *     @sender_cpu: (aka @napi_id) source CPU in XPS
  *     @secmark: security marking
  *     @mark: Generic packet mark
+ *     @reserved_tailroom: (aka @mark) number of bytes of free space available
+ *             at the tail of an sk_buff
+ *     @vlan_present: VLAN tag is present
  *     @vlan_proto: vlan encapsulation protocol
  *     @vlan_tci: vlan tag control information
  *     @inner_protocol: Protocol (encapsulation)
+ *     @inner_ipproto: (aka @inner_protocol) stores ipproto when
+ *             skb->inner_protocol_type == ENCAP_TYPE_IPPROTO;
  *     @inner_transport_header: Inner transport layer header (encapsulation)
  *     @inner_network_header: Network layer header (encapsulation)
  *     @inner_mac_header: Link layer header (encapsulation)
@@ -750,7 +774,9 @@ struct sk_buff {
 #endif
 #define CLONED_OFFSET()                offsetof(struct sk_buff, __cloned_offset)
 
+       /* private: */
        __u8                    __cloned_offset[0];
+       /* public: */
        __u8                    cloned:1,
                                nohdr:1,
                                fclone:2,
@@ -775,7 +801,9 @@ struct sk_buff {
 #endif
 #define PKT_TYPE_OFFSET()      offsetof(struct sk_buff, __pkt_type_offset)
 
+       /* private: */
        __u8                    __pkt_type_offset[0];
+       /* public: */
        __u8                    pkt_type:3;
        __u8                    ignore_df:1;
        __u8                    nf_trace:1;
@@ -798,7 +826,9 @@ struct sk_buff {
 #define PKT_VLAN_PRESENT_BIT   0
 #endif
 #define PKT_VLAN_PRESENT_OFFSET()      offsetof(struct sk_buff, __pkt_vlan_present_offset)
+       /* private: */
        __u8                    __pkt_vlan_present_offset[0];
+       /* public: */
        __u8                    vlan_present:1;
        __u8                    csum_complete_sw:1;
        __u8                    csum_level:2;
index cde3dc1..046bb94 100644 (file)
@@ -64,6 +64,9 @@ extern void swiotlb_tbl_sync_single(struct device *hwdev,
                                    size_t size, enum dma_data_direction dir,
                                    enum dma_sync_target target);
 
+dma_addr_t swiotlb_map(struct device *dev, phys_addr_t phys,
+               size_t size, enum dma_data_direction dir, unsigned long attrs);
+
 #ifdef CONFIG_SWIOTLB
 extern enum swiotlb_force swiotlb_force;
 extern phys_addr_t io_tlb_start, io_tlb_end;
@@ -73,8 +76,6 @@ static inline bool is_swiotlb_buffer(phys_addr_t paddr)
        return paddr >= io_tlb_start && paddr < io_tlb_end;
 }
 
-bool swiotlb_map(struct device *dev, phys_addr_t *phys, dma_addr_t *dma_addr,
-               size_t size, enum dma_data_direction dir, unsigned long attrs);
 void __init swiotlb_exit(void);
 unsigned int swiotlb_max_segment(void);
 size_t swiotlb_max_mapping_size(struct device *dev);
@@ -85,12 +86,6 @@ static inline bool is_swiotlb_buffer(phys_addr_t paddr)
 {
        return false;
 }
-static inline bool swiotlb_map(struct device *dev, phys_addr_t *phys,
-               dma_addr_t *dma_addr, size_t size, enum dma_data_direction dir,
-               unsigned long attrs)
-{
-       return false;
-}
 static inline void swiotlb_exit(void)
 {
 }
index cad4c31..cf9320c 100644 (file)
@@ -12,8 +12,6 @@
 #include <linux/time64.h>
 #include <linux/timex.h>
 
-#define TIME_T_MAX     (__kernel_old_time_t)((1UL << ((sizeof(__kernel_old_time_t) << 3) - 1)) - 1)
-
 typedef s32            old_time32_t;
 
 struct old_timespec32 {
@@ -73,162 +71,12 @@ struct __kernel_timex;
 int get_old_timex32(struct __kernel_timex *, const struct old_timex32 __user *);
 int put_old_timex32(struct old_timex32 __user *, const struct __kernel_timex *);
 
-#if __BITS_PER_LONG == 64
-
-/* timespec64 is defined as timespec here */
-static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64)
-{
-       return *(const struct timespec *)&ts64;
-}
-
-static inline struct timespec64 timespec_to_timespec64(const struct timespec ts)
-{
-       return *(const struct timespec64 *)&ts;
-}
-
-#else
-static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64)
-{
-       struct timespec ret;
-
-       ret.tv_sec = (time_t)ts64.tv_sec;
-       ret.tv_nsec = ts64.tv_nsec;
-       return ret;
-}
-
-static inline struct timespec64 timespec_to_timespec64(const struct timespec ts)
-{
-       struct timespec64 ret;
-
-       ret.tv_sec = ts.tv_sec;
-       ret.tv_nsec = ts.tv_nsec;
-       return ret;
-}
-#endif
-
-static inline int timespec_equal(const struct timespec *a,
-                                const struct timespec *b)
-{
-       return (a->tv_sec == b->tv_sec) && (a->tv_nsec == b->tv_nsec);
-}
-
-/*
- * lhs < rhs:  return <0
- * lhs == rhs: return 0
- * lhs > rhs:  return >0
- */
-static inline int timespec_compare(const struct timespec *lhs, const struct timespec *rhs)
-{
-       if (lhs->tv_sec < rhs->tv_sec)
-               return -1;
-       if (lhs->tv_sec > rhs->tv_sec)
-               return 1;
-       return lhs->tv_nsec - rhs->tv_nsec;
-}
-
-/*
- * Returns true if the timespec is norm, false if denorm:
- */
-static inline bool timespec_valid(const struct timespec *ts)
-{
-       /* Dates before 1970 are bogus */
-       if (ts->tv_sec < 0)
-               return false;
-       /* Can't have more nanoseconds then a second */
-       if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
-               return false;
-       return true;
-}
-
-/**
- * timespec_to_ns - Convert timespec to nanoseconds
- * @ts:                pointer to the timespec variable to be converted
- *
- * Returns the scalar nanosecond representation of the timespec
- * parameter.
- */
-static inline s64 timespec_to_ns(const struct timespec *ts)
-{
-       return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
-}
-
 /**
- * ns_to_timespec - Convert nanoseconds to timespec
- * @nsec:      the nanoseconds value to be converted
- *
- * Returns the timespec representation of the nsec parameter.
- */
-extern struct timespec ns_to_timespec(const s64 nsec);
-
-/**
- * timespec_add_ns - Adds nanoseconds to a timespec
- * @a:         pointer to timespec to be incremented
- * @ns:                unsigned nanoseconds value to be added
- *
- * This must always be inlined because its used from the x86-64 vdso,
- * which cannot call other kernel functions.
- */
-static __always_inline void timespec_add_ns(struct timespec *a, u64 ns)
-{
-       a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, NSEC_PER_SEC, &ns);
-       a->tv_nsec = ns;
-}
-
-static inline unsigned long mktime(const unsigned int year,
-                       const unsigned int mon, const unsigned int day,
-                       const unsigned int hour, const unsigned int min,
-                       const unsigned int sec)
-{
-       return mktime64(year, mon, day, hour, min, sec);
-}
-
-static inline bool timeval_valid(const struct timeval *tv)
-{
-       /* Dates before 1970 are bogus */
-       if (tv->tv_sec < 0)
-               return false;
-
-       /* Can't have more microseconds then a second */
-       if (tv->tv_usec < 0 || tv->tv_usec >= USEC_PER_SEC)
-               return false;
-
-       return true;
-}
-
-/**
- * timeval_to_ns - Convert timeval to nanoseconds
- * @ts:                pointer to the timeval variable to be converted
- *
- * Returns the scalar nanosecond representation of the timeval
- * parameter.
- */
-static inline s64 timeval_to_ns(const struct timeval *tv)
-{
-       return ((s64) tv->tv_sec * NSEC_PER_SEC) +
-               tv->tv_usec * NSEC_PER_USEC;
-}
-
-/**
- * ns_to_timeval - Convert nanoseconds to timeval
+ * ns_to_kernel_old_timeval - Convert nanoseconds to timeval
  * @nsec:      the nanoseconds value to be converted
  *
  * Returns the timeval representation of the nsec parameter.
  */
-extern struct timeval ns_to_timeval(const s64 nsec);
 extern struct __kernel_old_timeval ns_to_kernel_old_timeval(s64 nsec);
 
-/*
- * Old names for the 32-bit time_t interfaces, these will be removed
- * when everything uses the new names.
- */
-#define compat_time_t          old_time32_t
-#define compat_timeval         old_timeval32
-#define compat_timespec                old_timespec32
-#define compat_itimerspec      old_itimerspec32
-#define ns_to_compat_timeval   ns_to_old_timeval32
-#define get_compat_itimerspec64        get_old_itimerspec32
-#define put_compat_itimerspec64        put_old_itimerspec32
-#define compat_get_timespec64  get_old_timespec32
-#define compat_put_timespec64  put_old_timespec32
-
 #endif
index cc59cc9..266017f 100644 (file)
@@ -11,36 +11,4 @@ static inline unsigned long get_seconds(void)
        return ktime_get_real_seconds();
 }
 
-static inline void getnstimeofday(struct timespec *ts)
-{
-       struct timespec64 ts64;
-
-       ktime_get_real_ts64(&ts64);
-       *ts = timespec64_to_timespec(ts64);
-}
-
-static inline void ktime_get_ts(struct timespec *ts)
-{
-       struct timespec64 ts64;
-
-       ktime_get_ts64(&ts64);
-       *ts = timespec64_to_timespec(ts64);
-}
-
-static inline void getrawmonotonic(struct timespec *ts)
-{
-       struct timespec64 ts64;
-
-       ktime_get_raw_ts64(&ts64);
-       *ts = timespec64_to_timespec(ts64);
-}
-
-static inline void getboottime(struct timespec *ts)
-{
-       struct timespec64 ts64;
-
-       getboottime64(&ts64);
-       *ts = timespec64_to_timespec(ts64);
-}
-
 #endif
index bfa4e2e..bd5fe0e 100644 (file)
@@ -225,6 +225,8 @@ struct tty_port_client_operations {
        void (*write_wakeup)(struct tty_port *port);
 };
 
+extern const struct tty_port_client_operations tty_port_default_client_ops;
+
 struct tty_port {
        struct tty_bufhead      buf;            /* Locked internally */
        struct tty_struct       *tty;           /* Back pointer */
index eb870ad..d3021c8 100644 (file)
@@ -65,11 +65,6 @@ typedef __kernel_ssize_t     ssize_t;
 typedef __kernel_ptrdiff_t     ptrdiff_t;
 #endif
 
-#ifndef _TIME_T
-#define _TIME_T
-typedef __kernel_old_time_t    time_t;
-#endif
-
 #ifndef _CLOCK_T
 #define _CLOCK_T
 typedef __kernel_clock_t       clock_t;
index a1be64c..22c1f57 100644 (file)
@@ -69,4 +69,7 @@
 /* Hub needs extra delay after resetting its port. */
 #define USB_QUIRK_HUB_SLOW_RESET               BIT(14)
 
+/* device has blacklisted endpoints */
+#define USB_QUIRK_ENDPOINT_BLACKLIST           BIT(15)
+
 #endif /* __LINUX_USB_QUIRKS_H */
index e9391e8..6283839 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/types.h>
 #include <linux/in6.h>
 #include <linux/siphash.h>
+#include <linux/string.h>
 #include <uapi/linux/if_ether.h>
 
 struct sk_buff;
@@ -348,4 +349,12 @@ struct bpf_flow_dissector {
        void                    *data_end;
 };
 
+static inline void
+flow_dissector_init_keys(struct flow_dissector_key_control *key_control,
+                        struct flow_dissector_key_basic *key_basic)
+{
+       memset(key_control, 0, sizeof(*key_control));
+       memset(key_basic, 0, sizeof(*key_basic));
+}
+
 #endif
index 02162b0..3285645 100644 (file)
@@ -117,19 +117,26 @@ typedef __u64 __bitwise __addrpair;
  *     struct sock_common - minimal network layer representation of sockets
  *     @skc_daddr: Foreign IPv4 addr
  *     @skc_rcv_saddr: Bound local IPv4 addr
+ *     @skc_addrpair: 8-byte-aligned __u64 union of @skc_daddr & @skc_rcv_saddr
  *     @skc_hash: hash value used with various protocol lookup tables
  *     @skc_u16hashes: two u16 hash values used by UDP lookup tables
  *     @skc_dport: placeholder for inet_dport/tw_dport
  *     @skc_num: placeholder for inet_num/tw_num
+ *     @skc_portpair: __u32 union of @skc_dport & @skc_num
  *     @skc_family: network address family
  *     @skc_state: Connection state
  *     @skc_reuse: %SO_REUSEADDR setting
  *     @skc_reuseport: %SO_REUSEPORT setting
+ *     @skc_ipv6only: socket is IPV6 only
+ *     @skc_net_refcnt: socket is using net ref counting
  *     @skc_bound_dev_if: bound device index if != 0
  *     @skc_bind_node: bind hash linkage for various protocol lookup tables
  *     @skc_portaddr_node: second hash linkage for UDP/UDP-Lite protocol
  *     @skc_prot: protocol handlers inside a network family
  *     @skc_net: reference to the network namespace of this socket
+ *     @skc_v6_daddr: IPV6 destination address
+ *     @skc_v6_rcv_saddr: IPV6 source address
+ *     @skc_cookie: socket's cookie value
  *     @skc_node: main hash linkage for various protocol lookup tables
  *     @skc_nulls_node: main hash linkage for TCP/UDP/UDP-Lite protocol
  *     @skc_tx_queue_mapping: tx queue number for this connection
@@ -137,7 +144,15 @@ typedef __u64 __bitwise __addrpair;
  *     @skc_flags: place holder for sk_flags
  *             %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE,
  *             %SO_OOBINLINE settings, %SO_TIMESTAMPING settings
+ *     @skc_listener: connection request listener socket (aka rsk_listener)
+ *             [union with @skc_flags]
+ *     @skc_tw_dr: (aka tw_dr) ptr to &struct inet_timewait_death_row
+ *             [union with @skc_flags]
  *     @skc_incoming_cpu: record/match cpu processing incoming packets
+ *     @skc_rcv_wnd: (aka rsk_rcv_wnd) TCP receive window size (possibly scaled)
+ *             [union with @skc_incoming_cpu]
+ *     @skc_tw_rcv_nxt: (aka tw_rcv_nxt) TCP window next expected seq number
+ *             [union with @skc_incoming_cpu]
  *     @skc_refcnt: reference count
  *
  *     This is the minimal network layer representation of sockets, the header
@@ -245,6 +260,7 @@ struct bpf_sk_storage;
   *    @sk_dst_cache: destination cache
   *    @sk_dst_pending_confirm: need to confirm neighbour
   *    @sk_policy: flow policy
+  *    @sk_rx_skb_cache: cache copy of recently accessed RX skb
   *    @sk_receive_queue: incoming packets
   *    @sk_wmem_alloc: transmit queue bytes committed
   *    @sk_tsq_flags: TCP Small Queues flags
@@ -265,6 +281,8 @@ struct bpf_sk_storage;
   *    @sk_no_check_rx: allow zero checksum in RX packets
   *    @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
   *    @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK)
+  *    @sk_route_forced_caps: static, forced route capabilities
+  *            (set in tcp_init_sock())
   *    @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4)
   *    @sk_gso_max_size: Maximum GSO segment size to build
   *    @sk_gso_max_segs: Maximum number of GSO segments
@@ -303,6 +321,8 @@ struct bpf_sk_storage;
   *    @sk_frag: cached page frag
   *    @sk_peek_off: current peek_offset value
   *    @sk_send_head: front of stuff to transmit
+  *    @tcp_rtx_queue: TCP re-transmit queue [union with @sk_send_head]
+  *    @sk_tx_skb_cache: cache copy of recently accessed TX skb
   *    @sk_security: used by security modules
   *    @sk_mark: generic packet mark
   *    @sk_cgrp_data: cgroup data for this cgroup
@@ -313,11 +333,14 @@ struct bpf_sk_storage;
   *    @sk_write_space: callback to indicate there is bf sending space available
   *    @sk_error_report: callback to indicate errors (e.g. %MSG_ERRQUEUE)
   *    @sk_backlog_rcv: callback to process the backlog
+  *    @sk_validate_xmit_skb: ptr to an optional validate function
   *    @sk_destruct: called at sock freeing time, i.e. when all refcnt == 0
   *    @sk_reuseport_cb: reuseport group container
+  *    @sk_bpf_storage: ptr to cache and control for bpf_sk_storage
   *    @sk_rcu: used during RCU grace period
   *    @sk_clockid: clockid used by time-based scheduling (SO_TXTIME)
   *    @sk_txtime_deadline_mode: set deadline mode for SO_TXTIME
+  *    @sk_txtime_report_errors: set report errors mode for SO_TXTIME
   *    @sk_txtime_unused: unused txtime flags
   */
 struct sock {
@@ -393,7 +416,9 @@ struct sock {
        struct sk_filter __rcu  *sk_filter;
        union {
                struct socket_wq __rcu  *sk_wq;
+               /* private: */
                struct socket_wq        *sk_wq_raw;
+               /* public: */
        };
 #ifdef CONFIG_XFRM
        struct xfrm_policy __rcu *sk_policy[2];
@@ -2017,7 +2042,7 @@ static inline int skb_copy_to_page_nocache(struct sock *sk, struct iov_iter *fro
  * sk_wmem_alloc_get - returns write allocations
  * @sk: socket
  *
- * Returns sk_wmem_alloc minus initial offset of one
+ * Return: sk_wmem_alloc minus initial offset of one
  */
 static inline int sk_wmem_alloc_get(const struct sock *sk)
 {
@@ -2028,7 +2053,7 @@ static inline int sk_wmem_alloc_get(const struct sock *sk)
  * sk_rmem_alloc_get - returns read allocations
  * @sk: socket
  *
- * Returns sk_rmem_alloc
+ * Return: sk_rmem_alloc
  */
 static inline int sk_rmem_alloc_get(const struct sock *sk)
 {
@@ -2039,7 +2064,7 @@ static inline int sk_rmem_alloc_get(const struct sock *sk)
  * sk_has_allocations - check if allocations are outstanding
  * @sk: socket
  *
- * Returns true if socket has write or read allocations
+ * Return: true if socket has write or read allocations
  */
 static inline bool sk_has_allocations(const struct sock *sk)
 {
@@ -2050,7 +2075,7 @@ static inline bool sk_has_allocations(const struct sock *sk)
  * skwq_has_sleeper - check if there are any waiting processes
  * @wq: struct socket_wq
  *
- * Returns true if socket_wq has waiting processes
+ * Return: true if socket_wq has waiting processes
  *
  * The purpose of the skwq_has_sleeper and sock_poll_wait is to wrap the memory
  * barrier call. They were added due to the race found within the tcp code.
@@ -2238,6 +2263,9 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp,
  * gfpflags_allow_blocking() isn't enough here as direct reclaim may nest
  * inside other socket operations and end up recursing into sk_page_frag()
  * while it's already in use.
+ *
+ * Return: a per task page_frag if context allows that,
+ * otherwise a per socket one.
  */
 static inline struct page_frag *sk_page_frag(struct sock *sk)
 {
@@ -2432,6 +2460,7 @@ static inline void skb_setup_tx_timestamp(struct sk_buff *skb, __u16 tsflags)
                           &skb_shinfo(skb)->tskey);
 }
 
+DECLARE_STATIC_KEY_FALSE(tcp_rx_skb_cache_key);
 /**
  * sk_eat_skb - Release a skb if it is no longer needed
  * @sk: socket to eat this skb from
@@ -2440,7 +2469,6 @@ static inline void skb_setup_tx_timestamp(struct sk_buff *skb, __u16 tsflags)
  * This routine must be called with interrupts disabled or with the socket
  * locked so that the sk_buff queue operation is ok.
 */
-DECLARE_STATIC_KEY_FALSE(tcp_rx_skb_cache_key);
 static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb)
 {
        __skb_unlink(skb, &sk->sk_receive_queue);
index 533f567..b71b5c4 100644 (file)
@@ -627,7 +627,6 @@ struct iscsi_reject {
 #define ISCSI_REASON_BOOKMARK_INVALID  9
 #define ISCSI_REASON_BOOKMARK_NO_RESOURCES     10
 #define ISCSI_REASON_NEGOTIATION_RESET 11
-#define ISCSI_REASON_WAITING_FOR_LOGOUT        12
 
 /* Max. number of Key=Value pairs in a text message */
 #define MAX_KEY_VALUE_PAIRS    8192
index 40ab204..a36b722 100644 (file)
@@ -77,9 +77,9 @@ struct snd_rawmidi_substream {
        struct list_head list;          /* list of all substream for given stream */
        int stream;                     /* direction */
        int number;                     /* substream number */
-       unsigned int opened: 1,         /* open flag */
-                    append: 1,         /* append flag (merge more streams) */
-                    active_sensing: 1; /* send active sensing when close */
+       bool opened;                    /* open flag */
+       bool append;                    /* append flag (merge more streams) */
+       bool active_sensing;            /* send active sensing when close */
        int use_count;                  /* use counter (for output) */
        size_t bytes;
        struct snd_rawmidi *rmidi;
index 2a306c6..1b6afbc 100644 (file)
@@ -392,8 +392,6 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
 int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
-int snd_soc_dapm_put_enum_double_locked(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol);
 int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_info *uinfo);
 int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
index 2f9c805..b5f7594 100644 (file)
@@ -87,7 +87,9 @@ typedef struct {
 typedef __kernel_long_t        __kernel_off_t;
 typedef long long      __kernel_loff_t;
 typedef __kernel_long_t        __kernel_old_time_t;
+#ifndef __KERNEL__
 typedef __kernel_long_t        __kernel_time_t;
+#endif
 typedef long long __kernel_time64_t;
 typedef __kernel_long_t        __kernel_clock_t;
 typedef int            __kernel_timer_t;
index f1d74a2..22f2352 100644 (file)
@@ -1045,9 +1045,9 @@ union bpf_attr {
  *             supports redirection to the egress interface, and accepts no
  *             flag at all.
  *
- *             The same effect can be attained with the more generic
- *             **bpf_redirect_map**\ (), which requires specific maps to be
- *             used but offers better performance.
+ *             The same effect can also be attained with the more generic
+ *             **bpf_redirect_map**\ (), which uses a BPF map to store the
+ *             redirect target instead of providing it directly to the helper.
  *     Return
  *             For XDP, the helper returns **XDP_REDIRECT** on success or
  *             **XDP_ABORTED** on error. For other program types, the values
@@ -1611,13 +1611,11 @@ union bpf_attr {
  *             the caller. Any higher bits in the *flags* argument must be
  *             unset.
  *
- *             When used to redirect packets to net devices, this helper
- *             provides a high performance increase over **bpf_redirect**\ ().
- *             This is due to various implementation details of the underlying
- *             mechanisms, one of which is the fact that **bpf_redirect_map**\
- *             () tries to send packet as a "bulk" to the device.
+ *             See also bpf_redirect(), which only supports redirecting to an
+ *             ifindex, but doesn't require a map to do so.
  *     Return
- *             **XDP_REDIRECT** on success, or **XDP_ABORTED** on error.
+ *             **XDP_REDIRECT** on success, or the value of the two lower bits
+ *             of the **flags* argument on error.
  *
  * int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)
  *     Description
index 336014b..b6f0bb1 100644 (file)
@@ -97,6 +97,15 @@ enum ip_conntrack_status {
        IPS_UNTRACKED_BIT = 12,
        IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT),
 
+#ifdef __KERNEL__
+       /* Re-purposed for in-kernel use:
+        * Tags a conntrack entry that clashed with an existing entry
+        * on insert.
+        */
+       IPS_NAT_CLASH_BIT = IPS_UNTRACKED_BIT,
+       IPS_NAT_CLASH = IPS_UNTRACKED,
+#endif
+
        /* Conntrack got a helper explicitly attached via CT target. */
        IPS_HELPER_BIT = 13,
        IPS_HELPER = (1 << IPS_HELPER_BIT),
@@ -110,7 +119,8 @@ enum ip_conntrack_status {
         */
        IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
                                 IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING |
-                                IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_OFFLOAD),
+                                IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_UNTRACKED |
+                                IPS_OFFLOAD),
 
        __IPS_MAX_BIT = 15,
 };
index fa7f97d..7272f85 100644 (file)
@@ -135,9 +135,9 @@ static inline __attribute_const__ __u32 __fswahb32(__u32 val)
 
 static __always_inline unsigned long __swab(const unsigned long y)
 {
-#if BITS_PER_LONG == 64
+#if __BITS_PER_LONG == 64
        return __swab64(y);
-#else /* BITS_PER_LONG == 32 */
+#else /* __BITS_PER_LONG == 32 */
        return __swab32(y);
 #endif
 }
index a655aa2..4f4b6e4 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/types.h>
 #include <linux/time_types.h>
 
+#ifndef __KERNEL__
 #ifndef _STRUCT_TIMESPEC
 #define _STRUCT_TIMESPEC
 struct timespec {
@@ -18,6 +19,17 @@ struct timeval {
        __kernel_suseconds_t    tv_usec;        /* microseconds */
 };
 
+struct itimerspec {
+       struct timespec it_interval;/* timer period */
+       struct timespec it_value;       /* timer expiration */
+};
+
+struct itimerval {
+       struct timeval it_interval;/* timer interval */
+       struct timeval it_value;        /* current value */
+};
+#endif
+
 struct timezone {
        int     tz_minuteswest; /* minutes west of Greenwich */
        int     tz_dsttime;     /* type of dst correction */
@@ -31,16 +43,6 @@ struct timezone {
 #define        ITIMER_VIRTUAL          1
 #define        ITIMER_PROF             2
 
-struct itimerspec {
-       struct timespec it_interval;    /* timer period */
-       struct timespec it_value;       /* timer expiration */
-};
-
-struct itimerval {
-       struct timeval it_interval;     /* timer interval */
-       struct timeval it_value;        /* current value */
-};
-
 /*
  * The IDs of the various system clocks (for POSIX.1b interval timers):
  */
index 5f72af3..ad22079 100644 (file)
  * ACA (Accessory Charger Adapters)
  */
 enum usb_charger_type {
-       UNKNOWN_TYPE,
-       SDP_TYPE,
-       DCP_TYPE,
-       CDP_TYPE,
-       ACA_TYPE,
+       UNKNOWN_TYPE = 0,
+       SDP_TYPE = 1,
+       DCP_TYPE = 2,
+       CDP_TYPE = 3,
+       ACA_TYPE = 4,
 };
 
 /* USB charger state */
 enum usb_charger_state {
-       USB_CHARGER_DEFAULT,
-       USB_CHARGER_PRESENT,
-       USB_CHARGER_ABSENT,
+       USB_CHARGER_DEFAULT = 0,
+       USB_CHARGER_PRESENT = 1,
+       USB_CHARGER_ABSENT = 2,
 };
 
 #endif /* _UAPI__LINUX_USB_CHARGER_H */
index 4f4303f..3687b71 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -2384,11 +2384,9 @@ void exit_sem(struct task_struct *tsk)
                ipc_assert_locked_object(&sma->sem_perm);
                list_del(&un->list_id);
 
-               /* we are the last process using this ulp, acquiring ulp->lock
-                * isn't required. Besides that, we are also protected against
-                * IPC_RMID as we hold sma->sem_perm lock now
-                */
+               spin_lock(&ulp->lock);
                list_del_rcu(&un->list_proc);
+               spin_unlock(&ulp->lock);
 
                /* perform adjustments registered in un */
                for (i = 0; i < sma->sem_nsems; i++) {
index 805c43b..7871400 100644 (file)
@@ -4142,9 +4142,9 @@ int btf_distill_func_proto(struct bpf_verifier_log *log,
  * EFAULT - verifier bug
  * 0 - 99% match. The last 1% is validated by the verifier.
  */
-int btf_check_func_type_match(struct bpf_verifier_log *log,
-                             struct btf *btf1, const struct btf_type *t1,
-                             struct btf *btf2, const struct btf_type *t2)
+static int btf_check_func_type_match(struct bpf_verifier_log *log,
+                                    struct btf *btf1, const struct btf_type *t1,
+                                    struct btf *btf2, const struct btf_type *t2)
 {
        const struct btf_param *args1, *args2;
        const char *fn1, *fn2, *s1, *s2;
index 2d182c4..a1468e3 100644 (file)
@@ -56,6 +56,7 @@ struct htab_elem {
                        union {
                                struct bpf_htab *htab;
                                struct pcpu_freelist_node fnode;
+                               struct htab_elem *batch_flink;
                        };
                };
        };
@@ -126,6 +127,17 @@ free_elems:
        bpf_map_area_free(htab->elems);
 }
 
+/* The LRU list has a lock (lru_lock). Each htab bucket has a lock
+ * (bucket_lock). If both locks need to be acquired together, the lock
+ * order is always lru_lock -> bucket_lock and this only happens in
+ * bpf_lru_list.c logic. For example, certain code path of
+ * bpf_lru_pop_free(), which is called by function prealloc_lru_pop(),
+ * will acquire lru_lock first followed by acquiring bucket_lock.
+ *
+ * In hashtab.c, to avoid deadlock, lock acquisition of
+ * bucket_lock followed by lru_lock is not allowed. In such cases,
+ * bucket_lock needs to be released first before acquiring lru_lock.
+ */
 static struct htab_elem *prealloc_lru_pop(struct bpf_htab *htab, void *key,
                                          u32 hash)
 {
@@ -1256,10 +1268,12 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
        void __user *ukeys = u64_to_user_ptr(attr->batch.keys);
        void *ubatch = u64_to_user_ptr(attr->batch.in_batch);
        u32 batch, max_count, size, bucket_size;
+       struct htab_elem *node_to_free = NULL;
        u64 elem_map_flags, map_flags;
        struct hlist_nulls_head *head;
        struct hlist_nulls_node *n;
-       unsigned long flags;
+       unsigned long flags = 0;
+       bool locked = false;
        struct htab_elem *l;
        struct bucket *b;
        int ret = 0;
@@ -1319,15 +1333,25 @@ again_nocopy:
        dst_val = values;
        b = &htab->buckets[batch];
        head = &b->head;
-       raw_spin_lock_irqsave(&b->lock, flags);
+       /* do not grab the lock unless need it (bucket_cnt > 0). */
+       if (locked)
+               raw_spin_lock_irqsave(&b->lock, flags);
 
        bucket_cnt = 0;
        hlist_nulls_for_each_entry_rcu(l, n, head, hash_node)
                bucket_cnt++;
 
+       if (bucket_cnt && !locked) {
+               locked = true;
+               goto again_nocopy;
+       }
+
        if (bucket_cnt > (max_count - total)) {
                if (total == 0)
                        ret = -ENOSPC;
+               /* Note that since bucket_cnt > 0 here, it is implicit
+                * that the locked was grabbed, so release it.
+                */
                raw_spin_unlock_irqrestore(&b->lock, flags);
                rcu_read_unlock();
                this_cpu_dec(bpf_prog_active);
@@ -1337,6 +1361,9 @@ again_nocopy:
 
        if (bucket_cnt > bucket_size) {
                bucket_size = bucket_cnt;
+               /* Note that since bucket_cnt > 0 here, it is implicit
+                * that the locked was grabbed, so release it.
+                */
                raw_spin_unlock_irqrestore(&b->lock, flags);
                rcu_read_unlock();
                this_cpu_dec(bpf_prog_active);
@@ -1346,6 +1373,10 @@ again_nocopy:
                goto alloc;
        }
 
+       /* Next block is only safe to run if you have grabbed the lock */
+       if (!locked)
+               goto next_batch;
+
        hlist_nulls_for_each_entry_safe(l, n, head, hash_node) {
                memcpy(dst_key, l->key, key_size);
 
@@ -1370,16 +1401,33 @@ again_nocopy:
                }
                if (do_delete) {
                        hlist_nulls_del_rcu(&l->hash_node);
-                       if (is_lru_map)
-                               bpf_lru_push_free(&htab->lru, &l->lru_node);
-                       else
+
+                       /* bpf_lru_push_free() will acquire lru_lock, which
+                        * may cause deadlock. See comments in function
+                        * prealloc_lru_pop(). Let us do bpf_lru_push_free()
+                        * after releasing the bucket lock.
+                        */
+                       if (is_lru_map) {
+                               l->batch_flink = node_to_free;
+                               node_to_free = l;
+                       } else {
                                free_htab_elem(htab, l);
+                       }
                }
                dst_key += key_size;
                dst_val += value_size;
        }
 
        raw_spin_unlock_irqrestore(&b->lock, flags);
+       locked = false;
+
+       while (node_to_free) {
+               l = node_to_free;
+               node_to_free = node_to_free->batch_flink;
+               bpf_lru_push_free(&htab->lru, &l->lru_node);
+       }
+
+next_batch:
        /* If we are not copying data, we can go to next bucket and avoid
         * unlocking the rcu.
         */
index 2c5dc65..bd09290 100644 (file)
@@ -321,7 +321,7 @@ int bpf_prog_offload_info_fill(struct bpf_prog_info *info,
 
        ulen = info->jited_prog_len;
        info->jited_prog_len = aux->offload->jited_len;
-       if (info->jited_prog_len & ulen) {
+       if (info->jited_prog_len && ulen) {
                uinsns = u64_to_user_ptr(info->jited_prog_insns);
                ulen = min_t(u32, info->jited_prog_len, ulen);
                if (copy_to_user(uinsns, aux->offload->jited_image, ulen)) {
index 95005f8..843dd17 100644 (file)
 
 #include <linux/uaccess.h>
 
-static int __compat_get_timeval(struct timeval *tv, const struct old_timeval32 __user *ctv)
-{
-       return (!access_ok(ctv, sizeof(*ctv)) ||
-                       __get_user(tv->tv_sec, &ctv->tv_sec) ||
-                       __get_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
-}
-
-static int __compat_put_timeval(const struct timeval *tv, struct old_timeval32 __user *ctv)
-{
-       return (!access_ok(ctv, sizeof(*ctv)) ||
-                       __put_user(tv->tv_sec, &ctv->tv_sec) ||
-                       __put_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
-}
-
-static int __compat_get_timespec(struct timespec *ts, const struct old_timespec32 __user *cts)
-{
-       return (!access_ok(cts, sizeof(*cts)) ||
-                       __get_user(ts->tv_sec, &cts->tv_sec) ||
-                       __get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
-}
-
-static int __compat_put_timespec(const struct timespec *ts, struct old_timespec32 __user *cts)
-{
-       return (!access_ok(cts, sizeof(*cts)) ||
-                       __put_user(ts->tv_sec, &cts->tv_sec) ||
-                       __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
-}
-
-int compat_get_timeval(struct timeval *tv, const void __user *utv)
-{
-       if (COMPAT_USE_64BIT_TIME)
-               return copy_from_user(tv, utv, sizeof(*tv)) ? -EFAULT : 0;
-       else
-               return __compat_get_timeval(tv, utv);
-}
-EXPORT_SYMBOL_GPL(compat_get_timeval);
-
-int compat_put_timeval(const struct timeval *tv, void __user *utv)
-{
-       if (COMPAT_USE_64BIT_TIME)
-               return copy_to_user(utv, tv, sizeof(*tv)) ? -EFAULT : 0;
-       else
-               return __compat_put_timeval(tv, utv);
-}
-EXPORT_SYMBOL_GPL(compat_put_timeval);
-
-int compat_get_timespec(struct timespec *ts, const void __user *uts)
-{
-       if (COMPAT_USE_64BIT_TIME)
-               return copy_from_user(ts, uts, sizeof(*ts)) ? -EFAULT : 0;
-       else
-               return __compat_get_timespec(ts, uts);
-}
-EXPORT_SYMBOL_GPL(compat_get_timespec);
-
-int compat_put_timespec(const struct timespec *ts, void __user *uts)
-{
-       if (COMPAT_USE_64BIT_TIME)
-               return copy_to_user(uts, ts, sizeof(*ts)) ? -EFAULT : 0;
-       else
-               return __compat_put_timespec(ts, uts);
-}
-EXPORT_SYMBOL_GPL(compat_put_timespec);
-
 #ifdef __ARCH_WANT_SYS_SIGPROCMASK
 
 /*
index daa4e6e..8bc6f2d 100644 (file)
@@ -302,9 +302,16 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
        phys_addr_t align = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
        phys_addr_t mask = align - 1;
        unsigned long node = rmem->fdt_node;
+       bool default_cma = of_get_flat_dt_prop(node, "linux,cma-default", NULL);
        struct cma *cma;
        int err;
 
+       if (size_cmdline != -1 && default_cma) {
+               pr_info("Reserved memory: bypass %s node, using cmdline CMA params instead\n",
+                       rmem->name);
+               return -EBUSY;
+       }
+
        if (!of_get_flat_dt_prop(node, "reusable", NULL) ||
            of_get_flat_dt_prop(node, "no-map", NULL))
                return -EINVAL;
@@ -322,7 +329,7 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
        /* Architecture specific contiguous memory fixup. */
        dma_contiguous_early_fixup(rmem->base, rmem->size);
 
-       if (of_get_flat_dt_prop(node, "linux,cma-default", NULL))
+       if (default_cma)
                dma_contiguous_set_default(cma);
 
        rmem->ops = &rmem_cma_ops;
index 6af7ae8..ac7956c 100644 (file)
  */
 unsigned int zone_dma_bits __ro_after_init = 24;
 
-static void report_addr(struct device *dev, dma_addr_t dma_addr, size_t size)
-{
-       if (!dev->dma_mask) {
-               dev_err_once(dev, "DMA map on device without dma_mask\n");
-       } else if (*dev->dma_mask >= DMA_BIT_MASK(32) || dev->bus_dma_limit) {
-               dev_err_once(dev,
-                       "overflow %pad+%zu of DMA mask %llx bus limit %llx\n",
-                       &dma_addr, size, *dev->dma_mask, dev->bus_dma_limit);
-       }
-       WARN_ON_ONCE(1);
-}
-
 static inline dma_addr_t phys_to_dma_direct(struct device *dev,
                phys_addr_t phys)
 {
@@ -357,13 +345,6 @@ void dma_direct_unmap_sg(struct device *dev, struct scatterlist *sgl,
 EXPORT_SYMBOL(dma_direct_unmap_sg);
 #endif
 
-static inline bool dma_direct_possible(struct device *dev, dma_addr_t dma_addr,
-               size_t size)
-{
-       return swiotlb_force != SWIOTLB_FORCE &&
-               dma_capable(dev, dma_addr, size, true);
-}
-
 dma_addr_t dma_direct_map_page(struct device *dev, struct page *page,
                unsigned long offset, size_t size, enum dma_data_direction dir,
                unsigned long attrs)
@@ -371,9 +352,16 @@ dma_addr_t dma_direct_map_page(struct device *dev, struct page *page,
        phys_addr_t phys = page_to_phys(page) + offset;
        dma_addr_t dma_addr = phys_to_dma(dev, phys);
 
-       if (unlikely(!dma_direct_possible(dev, dma_addr, size)) &&
-           !swiotlb_map(dev, &phys, &dma_addr, size, dir, attrs)) {
-               report_addr(dev, dma_addr, size);
+       if (unlikely(swiotlb_force == SWIOTLB_FORCE))
+               return swiotlb_map(dev, phys, size, dir, attrs);
+
+       if (unlikely(!dma_capable(dev, dma_addr, size, true))) {
+               if (swiotlb_force != SWIOTLB_NO_FORCE)
+                       return swiotlb_map(dev, phys, size, dir, attrs);
+
+               dev_WARN_ONCE(dev, 1,
+                            "DMA addr %pad+%zu overflow (mask %llx, bus limit %llx).\n",
+                            &dma_addr, size, *dev->dma_mask, dev->bus_dma_limit);
                return DMA_MAPPING_ERROR;
        }
 
@@ -411,7 +399,10 @@ dma_addr_t dma_direct_map_resource(struct device *dev, phys_addr_t paddr,
        dma_addr_t dma_addr = paddr;
 
        if (unlikely(!dma_capable(dev, dma_addr, size, false))) {
-               report_addr(dev, dma_addr, size);
+               dev_err_once(dev,
+                            "DMA addr %pad+%zu overflow (mask %llx, bus limit %llx).\n",
+                            &dma_addr, size, *dev->dma_mask, dev->bus_dma_limit);
+               WARN_ON_ONCE(1);
                return DMA_MAPPING_ERROR;
        }
 
@@ -472,28 +463,26 @@ int dma_direct_mmap(struct device *dev, struct vm_area_struct *vma,
 }
 #endif /* CONFIG_MMU */
 
-/*
- * Because 32-bit DMA masks are so common we expect every architecture to be
- * able to satisfy them - either by not supporting more physical memory, or by
- * providing a ZONE_DMA32.  If neither is the case, the architecture needs to
- * use an IOMMU instead of the direct mapping.
- */
 int dma_direct_supported(struct device *dev, u64 mask)
 {
-       u64 min_mask;
+       u64 min_mask = (max_pfn - 1) << PAGE_SHIFT;
 
-       if (IS_ENABLED(CONFIG_ZONE_DMA))
-               min_mask = DMA_BIT_MASK(zone_dma_bits);
-       else
-               min_mask = DMA_BIT_MASK(32);
-
-       min_mask = min_t(u64, min_mask, (max_pfn - 1) << PAGE_SHIFT);
+       /*
+        * Because 32-bit DMA masks are so common we expect every architecture
+        * to be able to satisfy them - either by not supporting more physical
+        * memory, or by providing a ZONE_DMA32.  If neither is the case, the
+        * architecture needs to use an IOMMU instead of the direct mapping.
+        */
+       if (mask >= DMA_BIT_MASK(32))
+               return 1;
 
        /*
         * This check needs to be against the actual bit mask value, so
         * use __phys_to_dma() here so that the SME encryption mask isn't
         * part of the check.
         */
+       if (IS_ENABLED(CONFIG_ZONE_DMA))
+               min_mask = min_t(u64, min_mask, DMA_BIT_MASK(zone_dma_bits));
        return mask >= __phys_to_dma(dev, min_mask);
 }
 
index 9280d6f..c19379f 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <linux/cache.h>
 #include <linux/dma-direct.h>
+#include <linux/dma-noncoherent.h>
 #include <linux/mm.h>
 #include <linux/export.h>
 #include <linux/spinlock.h>
@@ -656,35 +657,38 @@ void swiotlb_tbl_sync_single(struct device *hwdev, phys_addr_t tlb_addr,
 }
 
 /*
- * Create a swiotlb mapping for the buffer at @phys, and in case of DMAing
+ * Create a swiotlb mapping for the buffer at @paddr, and in case of DMAing
  * to the device copy the data into it as well.
  */
-bool swiotlb_map(struct device *dev, phys_addr_t *phys, dma_addr_t *dma_addr,
-               size_t size, enum dma_data_direction dir, unsigned long attrs)
+dma_addr_t swiotlb_map(struct device *dev, phys_addr_t paddr, size_t size,
+               enum dma_data_direction dir, unsigned long attrs)
 {
-       trace_swiotlb_bounced(dev, *dma_addr, size, swiotlb_force);
+       phys_addr_t swiotlb_addr;
+       dma_addr_t dma_addr;
 
-       if (unlikely(swiotlb_force == SWIOTLB_NO_FORCE)) {
-               dev_warn_ratelimited(dev,
-                       "Cannot do DMA to address %pa\n", phys);
-               return false;
-       }
+       trace_swiotlb_bounced(dev, phys_to_dma(dev, paddr), size,
+                             swiotlb_force);
 
-       /* Oh well, have to allocate and map a bounce buffer. */
-       *phys = swiotlb_tbl_map_single(dev, __phys_to_dma(dev, io_tlb_start),
-                       *phys, size, size, dir, attrs);
-       if (*phys == (phys_addr_t)DMA_MAPPING_ERROR)
-               return false;
+       swiotlb_addr = swiotlb_tbl_map_single(dev,
+                       __phys_to_dma(dev, io_tlb_start),
+                       paddr, size, size, dir, attrs);
+       if (swiotlb_addr == (phys_addr_t)DMA_MAPPING_ERROR)
+               return DMA_MAPPING_ERROR;
 
        /* Ensure that the address returned is DMA'ble */
-       *dma_addr = __phys_to_dma(dev, *phys);
-       if (unlikely(!dma_capable(dev, *dma_addr, size, true))) {
-               swiotlb_tbl_unmap_single(dev, *phys, size, size, dir,
+       dma_addr = __phys_to_dma(dev, swiotlb_addr);
+       if (unlikely(!dma_capable(dev, dma_addr, size, true))) {
+               swiotlb_tbl_unmap_single(dev, swiotlb_addr, size, size, dir,
                        attrs | DMA_ATTR_SKIP_CPU_SYNC);
-               return false;
+               dev_WARN_ONCE(dev, 1,
+                       "swiotlb addr %pad+%zu overflow (mask %llx, bus limit %llx).\n",
+                       &dma_addr, size, *dev->dma_mask, dev->bus_dma_limit);
+               return DMA_MAPPING_ERROR;
        }
 
-       return true;
+       if (!dev_is_dma_coherent(dev) && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
+               arch_sync_dma_for_device(swiotlb_addr, size, dir);
+       return dma_addr;
 }
 
 size_t swiotlb_max_mapping_size(struct device *dev)
index 3924fbe..c9d8eb7 100644 (file)
@@ -128,8 +128,6 @@ static inline void unregister_handler_proc(unsigned int irq,
 
 extern bool irq_can_set_affinity_usr(unsigned int irq);
 
-extern int irq_select_affinity_usr(unsigned int irq);
-
 extern void irq_set_thread_affinity(struct irq_desc *desc);
 
 extern int irq_do_set_affinity(struct irq_data *data,
index 3089a60..7eee98c 100644 (file)
@@ -481,23 +481,9 @@ int irq_setup_affinity(struct irq_desc *desc)
 {
        return irq_select_affinity(irq_desc_get_irq(desc));
 }
-#endif
+#endif /* CONFIG_AUTO_IRQ_AFFINITY */
+#endif /* CONFIG_SMP */
 
-/*
- * Called when a bogus affinity is set via /proc/irq
- */
-int irq_select_affinity_usr(unsigned int irq)
-{
-       struct irq_desc *desc = irq_to_desc(irq);
-       unsigned long flags;
-       int ret;
-
-       raw_spin_lock_irqsave(&desc->lock, flags);
-       ret = irq_setup_affinity(desc);
-       raw_spin_unlock_irqrestore(&desc->lock, flags);
-       return ret;
-}
-#endif
 
 /**
  *     irq_set_vcpu_affinity - Set vcpu affinity for the interrupt
index 9e5783d..32c071d 100644 (file)
@@ -111,6 +111,28 @@ static int irq_affinity_list_proc_show(struct seq_file *m, void *v)
        return show_irq_affinity(AFFINITY_LIST, m);
 }
 
+#ifndef CONFIG_AUTO_IRQ_AFFINITY
+static inline int irq_select_affinity_usr(unsigned int irq)
+{
+       /*
+        * If the interrupt is started up already then this fails. The
+        * interrupt is assigned to an online CPU already. There is no
+        * point to move it around randomly. Tell user space that the
+        * selected mask is bogus.
+        *
+        * If not then any change to the affinity is pointless because the
+        * startup code invokes irq_setup_affinity() which will select
+        * a online CPU anyway.
+        */
+       return -EINVAL;
+}
+#else
+/* ALPHA magic affinity auto selector. Keep it for historical reasons. */
+static inline int irq_select_affinity_usr(unsigned int irq)
+{
+       return irq_select_affinity(irq);
+}
+#endif
 
 static ssize_t write_irq_affinity(int type, struct file *file,
                const char __user *buffer, size_t count, loff_t *pos)
index d396aaa..ad5b88a 100644 (file)
@@ -805,15 +805,6 @@ static struct ctl_table kern_table[] = {
                .extra2         = &maxolduid,
        },
 #ifdef CONFIG_S390
-#ifdef CONFIG_MATHEMU
-       {
-               .procname       = "ieee_emulation_warnings",
-               .data           = &sysctl_ieee_emulation_warnings,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec,
-       },
-#endif
        {
                .procname       = "userprocess_debug",
                .data           = &show_unhandled_signals,
index cdd7386..3985b2b 100644 (file)
@@ -449,49 +449,6 @@ time64_t mktime64(const unsigned int year0, const unsigned int mon0,
 }
 EXPORT_SYMBOL(mktime64);
 
-/**
- * ns_to_timespec - Convert nanoseconds to timespec
- * @nsec:       the nanoseconds value to be converted
- *
- * Returns the timespec representation of the nsec parameter.
- */
-struct timespec ns_to_timespec(const s64 nsec)
-{
-       struct timespec ts;
-       s32 rem;
-
-       if (!nsec)
-               return (struct timespec) {0, 0};
-
-       ts.tv_sec = div_s64_rem(nsec, NSEC_PER_SEC, &rem);
-       if (unlikely(rem < 0)) {
-               ts.tv_sec--;
-               rem += NSEC_PER_SEC;
-       }
-       ts.tv_nsec = rem;
-
-       return ts;
-}
-EXPORT_SYMBOL(ns_to_timespec);
-
-/**
- * ns_to_timeval - Convert nanoseconds to timeval
- * @nsec:       the nanoseconds value to be converted
- *
- * Returns the timeval representation of the nsec parameter.
- */
-struct timeval ns_to_timeval(const s64 nsec)
-{
-       struct timespec ts = ns_to_timespec(nsec);
-       struct timeval tv;
-
-       tv.tv_sec = ts.tv_sec;
-       tv.tv_usec = (suseconds_t) ts.tv_nsec / 1000;
-
-       return tv;
-}
-EXPORT_SYMBOL(ns_to_timeval);
-
 struct __kernel_old_timeval ns_to_kernel_old_timeval(const s64 nsec)
 {
        struct timespec64 ts = ns_to_timespec64(nsec);
index ed717dd..81c69c0 100644 (file)
@@ -83,15 +83,19 @@ static bool init_stack_slab(void **prealloc)
                return true;
        if (stack_slabs[depot_index] == NULL) {
                stack_slabs[depot_index] = *prealloc;
+               *prealloc = NULL;
        } else {
-               stack_slabs[depot_index + 1] = *prealloc;
+               /* If this is the last depot slab, do not touch the next one. */
+               if (depot_index + 1 < STACK_ALLOC_MAX_SLABS) {
+                       stack_slabs[depot_index + 1] = *prealloc;
+                       *prealloc = NULL;
+               }
                /*
                 * This smp_store_release pairs with smp_load_acquire() from
                 * |next_slab_inited| above and in stack_depot_save().
                 */
                smp_store_release(&next_slab_inited, 1);
        }
-       *prealloc = NULL;
        return true;
 }
 
index f607b96..6012c38 100644 (file)
@@ -699,6 +699,14 @@ EXPORT_SYMBOL(sysfs_streq);
  * @n:         number of strings in the array or -1 for NULL terminated arrays
  * @string:    string to match with
  *
+ * This routine will look for a string in an array of strings up to the
+ * n-th element in the array or until the first NULL element.
+ *
+ * Historically the value of -1 for @n, was used to search in arrays that
+ * are NULL terminated. However, the function does not make a distinction
+ * when finishing the search: either @n elements have been compared OR
+ * the first NULL element was found.
+ *
  * Return:
  * index of a @string in the @array if matches, or %-EINVAL otherwise.
  */
@@ -727,6 +735,14 @@ EXPORT_SYMBOL(match_string);
  *
  * Returns index of @str in the @array or -EINVAL, just like match_string().
  * Uses sysfs_streq instead of strcmp for matching.
+ *
+ * This routine will look for a string in an array of strings up to the
+ * n-th element in the array or until the first NULL element.
+ *
+ * Historically the value of -1 for @n, was used to search in arrays that
+ * are NULL terminated. However, the function does not make a distinction
+ * when finishing the search: either @n elements have been compared OR
+ * the first NULL element was found.
  */
 int __sysfs_match_string(const char * const *array, size_t n, const char *str)
 {
index 6f6dc87..d09776c 100644 (file)
@@ -409,8 +409,10 @@ int memcg_expand_shrinker_maps(int new_id)
                if (mem_cgroup_is_root(memcg))
                        continue;
                ret = memcg_expand_one_shrinker_map(memcg, size, old_size);
-               if (ret)
+               if (ret) {
+                       mem_cgroup_iter_break(NULL, memcg);
                        goto unlock;
+               }
        }
 unlock:
        if (!ret)
index 6756b8b..d681a20 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -195,8 +195,6 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
        bool downgraded = false;
        LIST_HEAD(uf);
 
-       brk = untagged_addr(brk);
-
        if (down_write_killable(&mm->mmap_sem))
                return -EINTR;
 
@@ -1557,8 +1555,6 @@ unsigned long ksys_mmap_pgoff(unsigned long addr, unsigned long len,
        struct file *file = NULL;
        unsigned long retval;
 
-       addr = untagged_addr(addr);
-
        if (!(flags & MAP_ANONYMOUS)) {
                audit_mmap_fd(fd, flags);
                file = fget(fd);
index 122938d..af36306 100644 (file)
@@ -607,7 +607,6 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
        LIST_HEAD(uf_unmap);
 
        addr = untagged_addr(addr);
-       new_addr = untagged_addr(new_addr);
 
        if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
                return ret;
index c184b69..596b2a4 100644 (file)
@@ -876,7 +876,7 @@ int __meminit sparse_add_section(int nid, unsigned long start_pfn,
         * Poison uninitialized struct pages in order to catch invalid flags
         * combinations.
         */
-       page_init_poison(pfn_to_page(start_pfn), sizeof(struct page) * nr_pages);
+       page_init_poison(memmap, sizeof(struct page) * nr_pages);
 
        ms = __nr_to_section(section_nr);
        set_section_nid(section_nr, nid);
index 2c33ff4..b2a2e45 100644 (file)
@@ -3157,7 +3157,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
        mapping = swap_file->f_mapping;
        inode = mapping->host;
 
-       /* If S_ISREG(inode->i_mode) will do inode_lock(inode); */
+       /* will take i_rwsem; */
        error = claim_swapfile(p, inode);
        if (unlikely(error))
                goto bad_swap;
index c05eb9e..8763705 100644 (file)
@@ -2415,10 +2415,13 @@ out:
                        /*
                         * Scan types proportional to swappiness and
                         * their relative recent reclaim efficiency.
-                        * Make sure we don't miss the last page
-                        * because of a round-off error.
+                        * Make sure we don't miss the last page on
+                        * the offlined memory cgroups because of a
+                        * round-off error.
                         */
-                       scan = DIV64_U64_ROUND_UP(scan * fraction[file],
+                       scan = mem_cgroup_online(memcg) ?
+                              div64_u64(scan * fraction[file], denominator) :
+                              DIV64_U64_ROUND_UP(scan * fraction[file],
                                                  denominator);
                        break;
                case SCAN_FILE:
index b0937a7..2eeb0e5 100644 (file)
@@ -189,7 +189,6 @@ config BRIDGE_NETFILTER
        depends on NETFILTER_ADVANCED
        select NETFILTER_FAMILY_BRIDGE
        select SKB_EXTENSIONS
-       default m
        ---help---
          Enabling this option will let arptables resp. iptables see bridged
          ARP resp. IP traffic. If you want a bridging firewall, you probably
index 6856a6d..1f14b84 100644 (file)
@@ -63,7 +63,8 @@ struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no)
 {
        struct net_bridge_port *p;
 
-       list_for_each_entry_rcu(p, &br->port_list, list) {
+       list_for_each_entry_rcu(p, &br->port_list, list,
+                               lockdep_is_held(&br->lock)) {
                if (p->port_no == port_no)
                        return p;
        }
index a6316b3..e10bd68 100644 (file)
 #include "net-sysfs.h"
 
 #define MAX_GRO_SKBS 8
-#define MAX_NEST_DEV 8
 
 /* This should be increased if a protocol with a bigger head is added. */
 #define GRO_MAX_HEAD (MAX_HEADER + 128)
@@ -331,6 +330,12 @@ int netdev_name_node_alt_destroy(struct net_device *dev, const char *name)
        name_node = netdev_name_node_lookup(net, name);
        if (!name_node)
                return -ENOENT;
+       /* lookup might have found our primary name or a name belonging
+        * to another device.
+        */
+       if (name_node == dev->name_node || name_node->dev != dev)
+               return -EINVAL;
+
        __netdev_name_node_alt_destroy(name_node);
 
        return 0;
@@ -3657,26 +3662,8 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
        qdisc_calculate_pkt_len(skb, q);
 
        if (q->flags & TCQ_F_NOLOCK) {
-               if ((q->flags & TCQ_F_CAN_BYPASS) && READ_ONCE(q->empty) &&
-                   qdisc_run_begin(q)) {
-                       if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED,
-                                             &q->state))) {
-                               __qdisc_drop(skb, &to_free);
-                               rc = NET_XMIT_DROP;
-                               goto end_run;
-                       }
-                       qdisc_bstats_cpu_update(q, skb);
-
-                       rc = NET_XMIT_SUCCESS;
-                       if (sch_direct_xmit(skb, q, dev, txq, NULL, true))
-                               __qdisc_run(q);
-
-end_run:
-                       qdisc_run_end(q);
-               } else {
-                       rc = q->enqueue(skb, q, &to_free) & NET_XMIT_MASK;
-                       qdisc_run(q);
-               }
+               rc = q->enqueue(skb, q, &to_free) & NET_XMIT_MASK;
+               qdisc_run(q);
 
                if (unlikely(to_free))
                        kfree_skb_list(to_free);
@@ -7201,8 +7188,8 @@ static int __netdev_walk_all_lower_dev(struct net_device *dev,
        return 0;
 }
 
-static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
-                                                   struct list_head **iter)
+struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
+                                            struct list_head **iter)
 {
        struct netdev_adjacent *lower;
 
@@ -7214,6 +7201,7 @@ static struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
 
        return lower->dev;
 }
+EXPORT_SYMBOL(netdev_next_lower_dev_rcu);
 
 static u8 __netdev_upper_depth(struct net_device *dev)
 {
index 3e7e152..bd7eba9 100644 (file)
@@ -974,7 +974,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
 
        frh = nlmsg_data(nlh);
        frh->family = ops->family;
-       frh->table = rule->table;
+       frh->table = rule->table < 256 ? rule->table : RT_TABLE_COMPAT;
        if (nla_put_u32(skb, FRA_TABLE, rule->table))
                goto nla_put_failure;
        if (nla_put_u32(skb, FRA_SUPPRESS_PREFIXLEN, rule->suppress_prefixlen))
index 09c44bf..e1152f4 100644 (file)
@@ -3504,27 +3504,25 @@ static int rtnl_alt_ifname(int cmd, struct net_device *dev, struct nlattr *attr,
        if (err)
                return err;
 
-       alt_ifname = nla_data(attr);
+       alt_ifname = nla_strdup(attr, GFP_KERNEL);
+       if (!alt_ifname)
+               return -ENOMEM;
+
        if (cmd == RTM_NEWLINKPROP) {
-               alt_ifname = kstrdup(alt_ifname, GFP_KERNEL);
-               if (!alt_ifname)
-                       return -ENOMEM;
                err = netdev_name_node_alt_create(dev, alt_ifname);
-               if (err) {
-                       kfree(alt_ifname);
-                       return err;
-               }
+               if (!err)
+                       alt_ifname = NULL;
        } else if (cmd == RTM_DELLINKPROP) {
                err = netdev_name_node_alt_destroy(dev, alt_ifname);
-               if (err)
-                       return err;
        } else {
-               WARN_ON(1);
-               return 0;
+               WARN_ON_ONCE(1);
+               err = -EINVAL;
        }
 
-       *changed = true;
-       return 0;
+       kfree(alt_ifname);
+       if (!err)
+               *changed = true;
+       return err;
 }
 
 static int rtnl_linkprop(int cmd, struct sk_buff *skb, struct nlmsghdr *nlh,
index 864cb9e..e1101a4 100644 (file)
@@ -467,7 +467,6 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len,
                return NULL;
        }
 
-       /* use OR instead of assignment to avoid clearing of bits in mask */
        if (pfmemalloc)
                skb->pfmemalloc = 1;
        skb->head_frag = 1;
@@ -527,7 +526,6 @@ struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len,
                return NULL;
        }
 
-       /* use OR instead of assignment to avoid clearing of bits in mask */
        if (nc->page.pfmemalloc)
                skb->pfmemalloc = 1;
        skb->head_frag = 1;
@@ -4805,9 +4803,9 @@ static __sum16 *skb_checksum_setup_ip(struct sk_buff *skb,
                                      typeof(IPPROTO_IP) proto,
                                      unsigned int off)
 {
-       switch (proto) {
-               int err;
+       int err;
 
+       switch (proto) {
        case IPPROTO_TCP:
                err = skb_maybe_pull_tail(skb, off + sizeof(struct tcphdr),
                                          off + MAX_TCP_HDR_LEN);
index fce45da..8977fe1 100644 (file)
@@ -447,7 +447,10 @@ ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits,
                                    "mask only allowed in compact bitset");
                return -EINVAL;
        }
+
        no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
+       if (no_mask)
+               ethnl_bitmap32_clear(bitmap, 0, nbits, mod);
 
        nla_for_each_nested(bit_attr, tb[ETHTOOL_A_BITSET_BITS], rem) {
                bool old_val, new_val;
index 364ea2c..3ba7f61 100644 (file)
@@ -155,7 +155,8 @@ static struct hsr_node *hsr_add_node(struct hsr_priv *hsr,
                new_node->seq_out[i] = seq_out;
 
        spin_lock_bh(&hsr->list_lock);
-       list_for_each_entry_rcu(node, node_db, mac_list) {
+       list_for_each_entry_rcu(node, node_db, mac_list,
+                               lockdep_is_held(&hsr->list_lock)) {
                if (ether_addr_equal(node->macaddress_A, addr))
                        goto out;
                if (ether_addr_equal(node->macaddress_B, addr))
index db76b96..08a41f1 100644 (file)
@@ -1857,8 +1857,12 @@ int __udp_disconnect(struct sock *sk, int flags)
        inet->inet_dport = 0;
        sock_rps_reset_rxhash(sk);
        sk->sk_bound_dev_if = 0;
-       if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
+       if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) {
                inet_reset_saddr(sk);
+               if (sk->sk_prot->rehash &&
+                   (sk->sk_userlocks & SOCK_BINDPORT_LOCK))
+                       sk->sk_prot->rehash(sk);
+       }
 
        if (!(sk->sk_userlocks & SOCK_BINDPORT_LOCK)) {
                sk->sk_prot->unhash(sk);
index 58fbde2..72abf89 100644 (file)
@@ -1102,8 +1102,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
                                        found++;
                                        break;
                                }
-                               if (rt_can_ecmp)
-                                       fallback_ins = fallback_ins ?: ins;
+                               fallback_ins = fallback_ins ?: ins;
                                goto next_iter;
                        }
 
@@ -1146,7 +1145,9 @@ next_iter:
        }
 
        if (fallback_ins && !found) {
-               /* No ECMP-able route found, replace first non-ECMP one */
+               /* No matching route with same ecmp-able-ness found, replace
+                * first matching route
+                */
                ins = fallback_ins;
                iter = rcu_dereference_protected(*ins,
                                    lockdep_is_held(&rt->fib6_table->tb6_lock));
index 55bfc51..781ca8c 100644 (file)
@@ -437,8 +437,6 @@ static int ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                return -ENOENT;
 
        switch (type) {
-               struct ipv6_tlv_tnl_enc_lim *tel;
-               __u32 teli;
        case ICMPV6_DEST_UNREACH:
                net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n",
                                    t->parms.name);
@@ -452,7 +450,10 @@ static int ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                        break;
                }
                return 0;
-       case ICMPV6_PARAMPROB:
+       case ICMPV6_PARAMPROB: {
+               struct ipv6_tlv_tnl_enc_lim *tel;
+               __u32 teli;
+
                teli = 0;
                if (code == ICMPV6_HDR_FIELD)
                        teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data);
@@ -468,6 +469,7 @@ static int ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                                            t->parms.name);
                }
                return 0;
+       }
        case ICMPV6_PKT_TOOBIG:
                ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
                return 0;
index 5d65436..4703b09 100644 (file)
@@ -517,8 +517,6 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt,
        err = 0;
 
        switch (*type) {
-               struct ipv6_tlv_tnl_enc_lim *tel;
-               __u32 mtu, teli;
        case ICMPV6_DEST_UNREACH:
                net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n",
                                    t->parms.name);
@@ -531,7 +529,10 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt,
                        rel_msg = 1;
                }
                break;
-       case ICMPV6_PARAMPROB:
+       case ICMPV6_PARAMPROB: {
+               struct ipv6_tlv_tnl_enc_lim *tel;
+               __u32 teli;
+
                teli = 0;
                if ((*code) == ICMPV6_HDR_FIELD)
                        teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data);
@@ -548,7 +549,10 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt,
                                            t->parms.name);
                }
                break;
-       case ICMPV6_PKT_TOOBIG:
+       }
+       case ICMPV6_PKT_TOOBIG: {
+               __u32 mtu;
+
                ip6_update_pmtu(skb, net, htonl(*info), 0, 0,
                                sock_net_uid(net, NULL));
                mtu = *info - offset;
@@ -562,6 +566,7 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt,
                        rel_msg = 1;
                }
                break;
+       }
        case NDISC_REDIRECT:
                ip6_redirect(skb, net, skb->dev->ifindex, 0,
                             sock_net_uid(net, NULL));
index 4fbdc60..2931224 100644 (file)
@@ -5198,6 +5198,7 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
                 */
                cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL |
                                                     NLM_F_REPLACE);
+               cfg->fc_nlinfo.nlh->nlmsg_flags |= NLM_F_CREATE;
                nhn++;
        }
 
index 49f6054..a9ed3bf 100644 (file)
@@ -4,6 +4,7 @@ config MPTCP
        depends on INET
        select SKB_EXTENSIONS
        select CRYPTO_LIB_SHA256
+       select CRYPTO
        help
          Multipath TCP (MPTCP) connections send and receive data over multiple
          subflows in order to utilize multiple network paths. Each subflow
index 030dee6..e9aa680 100644 (file)
@@ -755,60 +755,50 @@ static int mptcp_setsockopt(struct sock *sk, int level, int optname,
                            char __user *optval, unsigned int optlen)
 {
        struct mptcp_sock *msk = mptcp_sk(sk);
-       int ret = -EOPNOTSUPP;
        struct socket *ssock;
-       struct sock *ssk;
 
        pr_debug("msk=%p", msk);
 
        /* @@ the meaning of setsockopt() when the socket is connected and
-        * there are multiple subflows is not defined.
+        * there are multiple subflows is not yet defined. It is up to the
+        * MPTCP-level socket to configure the subflows until the subflow
+        * is in TCP fallback, when TCP socket options are passed through
+        * to the one remaining subflow.
         */
        lock_sock(sk);
-       ssock = __mptcp_socket_create(msk, MPTCP_SAME_STATE);
-       if (IS_ERR(ssock)) {
-               release_sock(sk);
-               return ret;
-       }
+       ssock = __mptcp_tcp_fallback(msk);
+       if (ssock)
+               return tcp_setsockopt(ssock->sk, level, optname, optval,
+                                     optlen);
 
-       ssk = ssock->sk;
-       sock_hold(ssk);
        release_sock(sk);
 
-       ret = tcp_setsockopt(ssk, level, optname, optval, optlen);
-       sock_put(ssk);
-
-       return ret;
+       return -EOPNOTSUPP;
 }
 
 static int mptcp_getsockopt(struct sock *sk, int level, int optname,
                            char __user *optval, int __user *option)
 {
        struct mptcp_sock *msk = mptcp_sk(sk);
-       int ret = -EOPNOTSUPP;
        struct socket *ssock;
-       struct sock *ssk;
 
        pr_debug("msk=%p", msk);
 
-       /* @@ the meaning of getsockopt() when the socket is connected and
-        * there are multiple subflows is not defined.
+       /* @@ the meaning of setsockopt() when the socket is connected and
+        * there are multiple subflows is not yet defined. It is up to the
+        * MPTCP-level socket to configure the subflows until the subflow
+        * is in TCP fallback, when socket options are passed through
+        * to the one remaining subflow.
         */
        lock_sock(sk);
-       ssock = __mptcp_socket_create(msk, MPTCP_SAME_STATE);
-       if (IS_ERR(ssock)) {
-               release_sock(sk);
-               return ret;
-       }
+       ssock = __mptcp_tcp_fallback(msk);
+       if (ssock)
+               return tcp_getsockopt(ssock->sk, level, optname, optval,
+                                     option);
 
-       ssk = ssock->sk;
-       sock_hold(ssk);
        release_sock(sk);
 
-       ret = tcp_getsockopt(ssk, level, optname, optval, option);
-       sock_put(ssk);
-
-       return ret;
+       return -EOPNOTSUPP;
 }
 
 static int mptcp_get_port(struct sock *sk, unsigned short snum)
index 8a99a29..9f8663b 100644 (file)
@@ -56,8 +56,8 @@
 #define MPTCP_DSS_FLAG_MASK    (0x1F)
 
 /* MPTCP socket flags */
-#define MPTCP_DATA_READY       BIT(0)
-#define MPTCP_SEND_SPACE       BIT(1)
+#define MPTCP_DATA_READY       0
+#define MPTCP_SEND_SPACE       1
 
 /* MPTCP connection sock */
 struct mptcp_sock {
index d130542..1927fc2 100644 (file)
@@ -894,32 +894,175 @@ static void nf_ct_acct_merge(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
        }
 }
 
-/* Resolve race on insertion if this protocol allows this. */
+static void __nf_conntrack_insert_prepare(struct nf_conn *ct)
+{
+       struct nf_conn_tstamp *tstamp;
+
+       atomic_inc(&ct->ct_general.use);
+       ct->status |= IPS_CONFIRMED;
+
+       /* set conntrack timestamp, if enabled. */
+       tstamp = nf_conn_tstamp_find(ct);
+       if (tstamp)
+               tstamp->start = ktime_get_real_ns();
+}
+
+static int __nf_ct_resolve_clash(struct sk_buff *skb,
+                                struct nf_conntrack_tuple_hash *h)
+{
+       /* This is the conntrack entry already in hashes that won race. */
+       struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
+       enum ip_conntrack_info ctinfo;
+       struct nf_conn *loser_ct;
+
+       loser_ct = nf_ct_get(skb, &ctinfo);
+
+       if (nf_ct_is_dying(ct))
+               return NF_DROP;
+
+       if (!atomic_inc_not_zero(&ct->ct_general.use))
+               return NF_DROP;
+
+       if (((ct->status & IPS_NAT_DONE_MASK) == 0) ||
+           nf_ct_match(ct, loser_ct)) {
+               struct net *net = nf_ct_net(ct);
+
+               nf_ct_acct_merge(ct, ctinfo, loser_ct);
+               nf_ct_add_to_dying_list(loser_ct);
+               nf_conntrack_put(&loser_ct->ct_general);
+               nf_ct_set(skb, ct, ctinfo);
+
+               NF_CT_STAT_INC(net, insert_failed);
+               return NF_ACCEPT;
+       }
+
+       nf_ct_put(ct);
+       return NF_DROP;
+}
+
+/**
+ * nf_ct_resolve_clash_harder - attempt to insert clashing conntrack entry
+ *
+ * @skb: skb that causes the collision
+ * @repl_idx: hash slot for reply direction
+ *
+ * Called when origin or reply direction had a clash.
+ * The skb can be handled without packet drop provided the reply direction
+ * is unique or there the existing entry has the identical tuple in both
+ * directions.
+ *
+ * Caller must hold conntrack table locks to prevent concurrent updates.
+ *
+ * Returns NF_DROP if the clash could not be handled.
+ */
+static int nf_ct_resolve_clash_harder(struct sk_buff *skb, u32 repl_idx)
+{
+       struct nf_conn *loser_ct = (struct nf_conn *)skb_nfct(skb);
+       const struct nf_conntrack_zone *zone;
+       struct nf_conntrack_tuple_hash *h;
+       struct hlist_nulls_node *n;
+       struct net *net;
+
+       zone = nf_ct_zone(loser_ct);
+       net = nf_ct_net(loser_ct);
+
+       /* Reply direction must never result in a clash, unless both origin
+        * and reply tuples are identical.
+        */
+       hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[repl_idx], hnnode) {
+               if (nf_ct_key_equal(h,
+                                   &loser_ct->tuplehash[IP_CT_DIR_REPLY].tuple,
+                                   zone, net))
+                       return __nf_ct_resolve_clash(skb, h);
+       }
+
+       /* We want the clashing entry to go away real soon: 1 second timeout. */
+       loser_ct->timeout = nfct_time_stamp + HZ;
+
+       /* IPS_NAT_CLASH removes the entry automatically on the first
+        * reply.  Also prevents UDP tracker from moving the entry to
+        * ASSURED state, i.e. the entry can always be evicted under
+        * pressure.
+        */
+       loser_ct->status |= IPS_FIXED_TIMEOUT | IPS_NAT_CLASH;
+
+       __nf_conntrack_insert_prepare(loser_ct);
+
+       /* fake add for ORIGINAL dir: we want lookups to only find the entry
+        * already in the table.  This also hides the clashing entry from
+        * ctnetlink iteration, i.e. conntrack -L won't show them.
+        */
+       hlist_nulls_add_fake(&loser_ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
+
+       hlist_nulls_add_head_rcu(&loser_ct->tuplehash[IP_CT_DIR_REPLY].hnnode,
+                                &nf_conntrack_hash[repl_idx]);
+       return NF_ACCEPT;
+}
+
+/**
+ * nf_ct_resolve_clash - attempt to handle clash without packet drop
+ *
+ * @skb: skb that causes the clash
+ * @h: tuplehash of the clashing entry already in table
+ * @hash_reply: hash slot for reply direction
+ *
+ * A conntrack entry can be inserted to the connection tracking table
+ * if there is no existing entry with an identical tuple.
+ *
+ * If there is one, @skb (and the assocated, unconfirmed conntrack) has
+ * to be dropped.  In case @skb is retransmitted, next conntrack lookup
+ * will find the already-existing entry.
+ *
+ * The major problem with such packet drop is the extra delay added by
+ * the packet loss -- it will take some time for a retransmit to occur
+ * (or the sender to time out when waiting for a reply).
+ *
+ * This function attempts to handle the situation without packet drop.
+ *
+ * If @skb has no NAT transformation or if the colliding entries are
+ * exactly the same, only the to-be-confirmed conntrack entry is discarded
+ * and @skb is associated with the conntrack entry already in the table.
+ *
+ * Failing that, the new, unconfirmed conntrack is still added to the table
+ * provided that the collision only occurs in the ORIGINAL direction.
+ * The new entry will be added after the existing one in the hash list,
+ * so packets in the ORIGINAL direction will continue to match the existing
+ * entry.  The new entry will also have a fixed timeout so it expires --
+ * due to the collision, it will not see bidirectional traffic.
+ *
+ * Returns NF_DROP if the clash could not be resolved.
+ */
 static __cold noinline int
-nf_ct_resolve_clash(struct net *net, struct sk_buff *skb,
-                   enum ip_conntrack_info ctinfo,
-                   struct nf_conntrack_tuple_hash *h)
+nf_ct_resolve_clash(struct sk_buff *skb, struct nf_conntrack_tuple_hash *h,
+                   u32 reply_hash)
 {
        /* This is the conntrack entry already in hashes that won race. */
        struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
        const struct nf_conntrack_l4proto *l4proto;
-       enum ip_conntrack_info oldinfo;
-       struct nf_conn *loser_ct = nf_ct_get(skb, &oldinfo);
+       enum ip_conntrack_info ctinfo;
+       struct nf_conn *loser_ct;
+       struct net *net;
+       int ret;
+
+       loser_ct = nf_ct_get(skb, &ctinfo);
+       net = nf_ct_net(loser_ct);
 
        l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct));
-       if (l4proto->allow_clash &&
-           !nf_ct_is_dying(ct) &&
-           atomic_inc_not_zero(&ct->ct_general.use)) {
-               if (((ct->status & IPS_NAT_DONE_MASK) == 0) ||
-                   nf_ct_match(ct, loser_ct)) {
-                       nf_ct_acct_merge(ct, ctinfo, loser_ct);
-                       nf_conntrack_put(&loser_ct->ct_general);
-                       nf_ct_set(skb, ct, oldinfo);
-                       return NF_ACCEPT;
-               }
-               nf_ct_put(ct);
-       }
+       if (!l4proto->allow_clash)
+               goto drop;
+
+       ret = __nf_ct_resolve_clash(skb, h);
+       if (ret == NF_ACCEPT)
+               return ret;
+
+       ret = nf_ct_resolve_clash_harder(skb, reply_hash);
+       if (ret == NF_ACCEPT)
+               return ret;
+
+drop:
+       nf_ct_add_to_dying_list(loser_ct);
        NF_CT_STAT_INC(net, drop);
+       NF_CT_STAT_INC(net, insert_failed);
        return NF_DROP;
 }
 
@@ -932,7 +1075,6 @@ __nf_conntrack_confirm(struct sk_buff *skb)
        struct nf_conntrack_tuple_hash *h;
        struct nf_conn *ct;
        struct nf_conn_help *help;
-       struct nf_conn_tstamp *tstamp;
        struct hlist_nulls_node *n;
        enum ip_conntrack_info ctinfo;
        struct net *net;
@@ -989,6 +1131,7 @@ __nf_conntrack_confirm(struct sk_buff *skb)
 
        if (unlikely(nf_ct_is_dying(ct))) {
                nf_ct_add_to_dying_list(ct);
+               NF_CT_STAT_INC(net, insert_failed);
                goto dying;
        }
 
@@ -1009,13 +1152,8 @@ __nf_conntrack_confirm(struct sk_buff *skb)
           setting time, otherwise we'd get timer wrap in
           weird delay cases. */
        ct->timeout += nfct_time_stamp;
-       atomic_inc(&ct->ct_general.use);
-       ct->status |= IPS_CONFIRMED;
 
-       /* set conntrack timestamp, if enabled. */
-       tstamp = nf_conn_tstamp_find(ct);
-       if (tstamp)
-               tstamp->start = ktime_get_real_ns();
+       __nf_conntrack_insert_prepare(ct);
 
        /* Since the lookup is lockless, hash insertion must be done after
         * starting the timer and setting the CONFIRMED bit. The RCU barriers
@@ -1035,11 +1173,9 @@ __nf_conntrack_confirm(struct sk_buff *skb)
        return NF_ACCEPT;
 
 out:
-       nf_ct_add_to_dying_list(ct);
-       ret = nf_ct_resolve_clash(net, skb, ctinfo, h);
+       ret = nf_ct_resolve_clash(skb, h, reply_hash);
 dying:
        nf_conntrack_double_unlock(hash, reply_hash);
-       NF_CT_STAT_INC(net, insert_failed);
        local_bh_enable();
        return ret;
 }
index 7365b43..760ca24 100644 (file)
@@ -81,6 +81,18 @@ static bool udp_error(struct sk_buff *skb,
        return false;
 }
 
+static void nf_conntrack_udp_refresh_unreplied(struct nf_conn *ct,
+                                              struct sk_buff *skb,
+                                              enum ip_conntrack_info ctinfo,
+                                              u32 extra_jiffies)
+{
+       if (unlikely(ctinfo == IP_CT_ESTABLISHED_REPLY &&
+                    ct->status & IPS_NAT_CLASH))
+               nf_ct_kill(ct);
+       else
+               nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies);
+}
+
 /* Returns verdict for packet, and may modify conntracktype */
 int nf_conntrack_udp_packet(struct nf_conn *ct,
                            struct sk_buff *skb,
@@ -116,8 +128,8 @@ int nf_conntrack_udp_packet(struct nf_conn *ct,
                if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
                        nf_conntrack_event_cache(IPCT_ASSURED, ct);
        } else {
-               nf_ct_refresh_acct(ct, ctinfo, skb,
-                                  timeouts[UDP_CT_UNREPLIED]);
+               nf_conntrack_udp_refresh_unreplied(ct, skb, ctinfo,
+                                                  timeouts[UDP_CT_UNREPLIED]);
        }
        return NF_ACCEPT;
 }
@@ -198,8 +210,8 @@ int nf_conntrack_udplite_packet(struct nf_conn *ct,
                if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
                        nf_conntrack_event_cache(IPCT_ASSURED, ct);
        } else {
-               nf_ct_refresh_acct(ct, ctinfo, skb,
-                                  timeouts[UDP_CT_UNREPLIED]);
+               nf_conntrack_udp_refresh_unreplied(ct, skb, ctinfo,
+                                                  timeouts[UDP_CT_UNREPLIED]);
        }
        return NF_ACCEPT;
 }
index 83e1db3..06f00cd 100644 (file)
@@ -847,9 +847,6 @@ static int nf_flow_table_offload_cmd(struct flow_block_offload *bo,
 {
        int err;
 
-       if (!nf_flowtable_hw_offload(flowtable))
-               return 0;
-
        if (!dev->netdev_ops->ndo_setup_tc)
                return -EOPNOTSUPP;
 
@@ -876,6 +873,9 @@ int nf_flow_table_offload_setup(struct nf_flowtable *flowtable,
        struct flow_block_offload bo;
        int err;
 
+       if (!nf_flowtable_hw_offload(flowtable))
+               return 0;
+
        err = nf_flow_table_offload_cmd(&bo, flowtable, dev, cmd, &extack);
        if (err < 0)
                return err;
index f0cb1e1..feac855 100644 (file)
  * ::
  *
  *       rule indices in last field:    0    1
- *       map to elements:             0x42  0x66
+ *       map to elements:             0x66  0x42
  *
  *
  * Matching
  * ::
  *
  *       rule indices in last field:    0    1
- *       map to elements:             0x42  0x66
+ *       map to elements:             0x66  0x42
  *
  *      the matching element is at 0x42.
  *
@@ -503,7 +503,7 @@ static int pipapo_refill(unsigned long *map, int len, int rules,
                                return -1;
                        }
 
-                       if (unlikely(match_only)) {
+                       if (match_only) {
                                bitmap_clear(map, i, 1);
                                return i;
                        }
index bccd47c..7a2c4b8 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/netfilter_ipv6/ip6_tables.h>
 #include <linux/mutex.h>
 #include <linux/kernel.h>
+#include <linux/refcount.h>
 #include <uapi/linux/netfilter/xt_hashlimit.h>
 
 #define XT_HASHLIMIT_ALL (XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT | \
@@ -114,7 +115,7 @@ struct dsthash_ent {
 
 struct xt_hashlimit_htable {
        struct hlist_node node;         /* global list of all htables */
-       int use;
+       refcount_t use;
        u_int8_t family;
        bool rnd_initialized;
 
@@ -315,7 +316,7 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg,
        for (i = 0; i < hinfo->cfg.size; i++)
                INIT_HLIST_HEAD(&hinfo->hash[i]);
 
-       hinfo->use = 1;
+       refcount_set(&hinfo->use, 1);
        hinfo->count = 0;
        hinfo->family = family;
        hinfo->rnd_initialized = false;
@@ -420,7 +421,7 @@ static struct xt_hashlimit_htable *htable_find_get(struct net *net,
        hlist_for_each_entry(hinfo, &hashlimit_net->htables, node) {
                if (!strcmp(name, hinfo->name) &&
                    hinfo->family == family) {
-                       hinfo->use++;
+                       refcount_inc(&hinfo->use);
                        return hinfo;
                }
        }
@@ -429,12 +430,11 @@ static struct xt_hashlimit_htable *htable_find_get(struct net *net,
 
 static void htable_put(struct xt_hashlimit_htable *hinfo)
 {
-       mutex_lock(&hashlimit_mutex);
-       if (--hinfo->use == 0) {
+       if (refcount_dec_and_mutex_lock(&hinfo->use, &hashlimit_mutex)) {
                hlist_del(&hinfo->node);
+               mutex_unlock(&hashlimit_mutex);
                htable_destroy(hinfo);
        }
-       mutex_unlock(&hashlimit_mutex);
 }
 
 /* The algorithm used is the Simple Token Bucket Filter (TBF)
@@ -837,6 +837,8 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
        return hashlimit_mt_common(skb, par, hinfo, &info->cfg, 3);
 }
 
+#define HASHLIMIT_MAX_SIZE 1048576
+
 static int hashlimit_mt_check_common(const struct xt_mtchk_param *par,
                                     struct xt_hashlimit_htable **hinfo,
                                     struct hashlimit_cfg3 *cfg,
@@ -847,6 +849,14 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par,
 
        if (cfg->gc_interval == 0 || cfg->expire == 0)
                return -EINVAL;
+       if (cfg->size > HASHLIMIT_MAX_SIZE) {
+               cfg->size = HASHLIMIT_MAX_SIZE;
+               pr_info_ratelimited("size too large, truncated to %u\n", cfg->size);
+       }
+       if (cfg->max > HASHLIMIT_MAX_SIZE) {
+               cfg->max = HASHLIMIT_MAX_SIZE;
+               pr_info_ratelimited("max too large, truncated to %u\n", cfg->max);
+       }
        if (par->family == NFPROTO_IPV4) {
                if (cfg->srcmask > 32 || cfg->dstmask > 32)
                        return -EINVAL;
index f5d34da..a1f2320 100644 (file)
@@ -143,7 +143,8 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain,
        if (domain != NULL) {
                bkt = netlbl_domhsh_hash(domain);
                bkt_list = &netlbl_domhsh_rcu_deref(netlbl_domhsh)->tbl[bkt];
-               list_for_each_entry_rcu(iter, bkt_list, list)
+               list_for_each_entry_rcu(iter, bkt_list, list,
+                                       lockdep_is_held(&netlbl_domhsh_lock))
                        if (iter->valid &&
                            netlbl_family_match(iter->family, family) &&
                            strcmp(iter->domain, domain) == 0)
index d2e4ab8..77bb1bb 100644 (file)
@@ -207,7 +207,8 @@ static struct netlbl_unlhsh_iface *netlbl_unlhsh_search_iface(int ifindex)
 
        bkt = netlbl_unlhsh_hash(ifindex);
        bkt_list = &netlbl_unlhsh_rcu_deref(netlbl_unlhsh)->tbl[bkt];
-       list_for_each_entry_rcu(iter, bkt_list, list)
+       list_for_each_entry_rcu(iter, bkt_list, list,
+                               lockdep_is_held(&netlbl_unlhsh_lock))
                if (iter->valid && iter->ifindex == ifindex)
                        return iter;
 
index 4e31721..edf3e28 100644 (file)
@@ -1014,7 +1014,8 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
        if (nlk->netlink_bind && groups) {
                int group;
 
-               for (group = 0; group < nlk->ngroups; group++) {
+               /* nl_groups is a u32, so cap the maximum groups we can bind */
+               for (group = 0; group < BITS_PER_TYPE(u32); group++) {
                        if (!test_bit(group, &groups))
                                continue;
                        err = nlk->netlink_bind(net, group + 1);
@@ -1033,7 +1034,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
                        netlink_insert(sk, nladdr->nl_pid) :
                        netlink_autobind(sock);
                if (err) {
-                       netlink_undo_bind(nlk->ngroups, groups, sk);
+                       netlink_undo_bind(BITS_PER_TYPE(u32), groups, sk);
                        goto unlock;
                }
        }
index 659c2a7..c047afd 100644 (file)
@@ -179,7 +179,8 @@ struct vport *ovs_lookup_vport(const struct datapath *dp, u16 port_no)
        struct hlist_head *head;
 
        head = vport_hash_bucket(dp, port_no);
-       hlist_for_each_entry_rcu(vport, head, dp_hash_node) {
+       hlist_for_each_entry_rcu(vport, head, dp_hash_node,
+                               lockdep_ovsl_is_held()) {
                if (vport->port_no == port_no)
                        return vport;
        }
@@ -2042,7 +2043,8 @@ static unsigned int ovs_get_max_headroom(struct datapath *dp)
        int i;
 
        for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++) {
-               hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node) {
+               hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node,
+                                       lockdep_ovsl_is_held()) {
                        dev = vport->dev;
                        dev_headroom = netdev_get_fwd_headroom(dev);
                        if (dev_headroom > max_headroom)
@@ -2061,7 +2063,8 @@ static void ovs_update_headroom(struct datapath *dp, unsigned int new_headroom)
 
        dp->max_headroom = new_headroom;
        for (i = 0; i < DP_VPORT_HASH_BUCKETS; i++)
-               hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node)
+               hlist_for_each_entry_rcu(vport, &dp->ports[i], dp_hash_node,
+                                       lockdep_ovsl_is_held())
                        netdev_set_rx_headroom(vport->dev, new_headroom);
 }
 
index 7da4230..288122e 100644 (file)
@@ -2708,10 +2708,6 @@ static int validate_set(const struct nlattr *a,
                return -EINVAL;
 
        switch (key_type) {
-       const struct ovs_key_ipv4 *ipv4_key;
-       const struct ovs_key_ipv6 *ipv6_key;
-       int err;
-
        case OVS_KEY_ATTR_PRIORITY:
        case OVS_KEY_ATTR_SKB_MARK:
        case OVS_KEY_ATTR_CT_MARK:
@@ -2723,7 +2719,9 @@ static int validate_set(const struct nlattr *a,
                        return -EINVAL;
                break;
 
-       case OVS_KEY_ATTR_TUNNEL:
+       case OVS_KEY_ATTR_TUNNEL: {
+               int err;
+
                if (masked)
                        return -EINVAL; /* Masked tunnel set not supported. */
 
@@ -2732,8 +2730,10 @@ static int validate_set(const struct nlattr *a,
                if (err)
                        return err;
                break;
+       }
+       case OVS_KEY_ATTR_IPV4: {
+               const struct ovs_key_ipv4 *ipv4_key;
 
-       case OVS_KEY_ATTR_IPV4:
                if (eth_type != htons(ETH_P_IP))
                        return -EINVAL;
 
@@ -2753,8 +2753,10 @@ static int validate_set(const struct nlattr *a,
                                return -EINVAL;
                }
                break;
+       }
+       case OVS_KEY_ATTR_IPV6: {
+               const struct ovs_key_ipv6 *ipv6_key;
 
-       case OVS_KEY_ATTR_IPV6:
                if (eth_type != htons(ETH_P_IPV6))
                        return -EINVAL;
 
@@ -2781,7 +2783,7 @@ static int validate_set(const struct nlattr *a,
                        return -EINVAL;
 
                break;
-
+       }
        case OVS_KEY_ATTR_TCP:
                if ((eth_type != htons(ETH_P_IP) &&
                     eth_type != htons(ETH_P_IPV6)) ||
index 5904e93..fd8a01c 100644 (file)
@@ -585,7 +585,8 @@ static struct sw_flow *masked_flow_lookup(struct table_instance *ti,
        head = find_bucket(ti, hash);
        (*n_mask_hit)++;
 
-       hlist_for_each_entry_rcu(flow, head, flow_table.node[ti->node_ver]) {
+       hlist_for_each_entry_rcu(flow, head, flow_table.node[ti->node_ver],
+                               lockdep_ovsl_is_held()) {
                if (flow->mask == mask && flow->flow_table.hash == hash &&
                    flow_cmp_masked_key(flow, &masked_key, &mask->range))
                        return flow;
@@ -769,7 +770,8 @@ struct sw_flow *ovs_flow_tbl_lookup_ufid(struct flow_table *tbl,
 
        hash = ufid_hash(ufid);
        head = find_bucket(ti, hash);
-       hlist_for_each_entry_rcu(flow, head, ufid_table.node[ti->node_ver]) {
+       hlist_for_each_entry_rcu(flow, head, ufid_table.node[ti->node_ver],
+                               lockdep_ovsl_is_held()) {
                if (flow->ufid_table.hash == hash &&
                    ovs_flow_cmp_ufid(flow, ufid))
                        return flow;
index 3323b79..5010d1d 100644 (file)
@@ -61,7 +61,8 @@ static struct dp_meter *lookup_meter(const struct datapath *dp,
        struct hlist_head *head;
 
        head = meter_hash_bucket(dp, meter_id);
-       hlist_for_each_entry_rcu(meter, head, dp_hash_node) {
+       hlist_for_each_entry_rcu(meter, head, dp_hash_node,
+                               lockdep_ovsl_is_held()) {
                if (meter->id == meter_id)
                        return meter;
        }
index 5da9392..47febb4 100644 (file)
@@ -96,7 +96,8 @@ struct vport *ovs_vport_locate(const struct net *net, const char *name)
        struct hlist_head *bucket = hash_bucket(net, name);
        struct vport *vport;
 
-       hlist_for_each_entry_rcu(vport, bucket, hash_node)
+       hlist_for_each_entry_rcu(vport, bucket, hash_node,
+                               lockdep_ovsl_is_held())
                if (!strcmp(name, ovs_vport_name(vport)) &&
                    net_eq(ovs_dp_get_net(vport->dp), net))
                        return vport;
index 3341eee..585e6b3 100644 (file)
@@ -162,10 +162,9 @@ static int rds_pin_pages(unsigned long user_addr, unsigned int nr_pages,
        if (write)
                gup_flags |= FOLL_WRITE;
 
-       ret = get_user_pages_fast(user_addr, nr_pages, gup_flags, pages);
+       ret = pin_user_pages_fast(user_addr, nr_pages, gup_flags, pages);
        if (ret >= 0 && ret < nr_pages) {
-               while (ret--)
-                       put_page(pages[ret]);
+               unpin_user_pages(pages, ret);
                ret = -EFAULT;
        }
 
@@ -300,8 +299,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
                 * to release anything.
                 */
                if (!need_odp) {
-                       for (i = 0 ; i < nents; i++)
-                               put_page(sg_page(&sg[i]));
+                       unpin_user_pages(pages, nr_pages);
                        kfree(sg);
                }
                ret = PTR_ERR(trans_private);
@@ -325,7 +323,12 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
        if (cookie_ret)
                *cookie_ret = cookie;
 
-       if (args->cookie_addr && put_user(cookie, (u64 __user *)(unsigned long) args->cookie_addr)) {
+       if (args->cookie_addr &&
+           put_user(cookie, (u64 __user *)(unsigned long)args->cookie_addr)) {
+               if (!need_odp) {
+                       unpin_user_pages(pages, nr_pages);
+                       kfree(sg);
+               }
                ret = -EFAULT;
                goto out;
        }
@@ -496,9 +499,7 @@ void rds_rdma_free_op(struct rm_rdma_op *ro)
                         * is the case for a RDMA_READ which copies from remote
                         * to local memory
                         */
-                       if (!ro->op_write)
-                               set_page_dirty(page);
-                       put_page(page);
+                       unpin_user_pages_dirty_lock(&page, 1, !ro->op_write);
                }
        }
 
@@ -515,8 +516,7 @@ void rds_atomic_free_op(struct rm_atomic_op *ao)
        /* Mark page dirty if it was possibly modified, which
         * is the case for a RDMA_READ which copies from remote
         * to local memory */
-       set_page_dirty(page);
-       put_page(page);
+       unpin_user_pages_dirty_lock(&page, 1, true);
 
        kfree(ao->op_notifier);
        ao->op_notifier = NULL;
@@ -944,7 +944,7 @@ int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
        return ret;
 err:
        if (page)
-               put_page(page);
+               unpin_user_page(page);
        rm->atomic.op_active = 0;
        kfree(rm->atomic.op_notifier);
 
index 7e54d2a..d32d423 100644 (file)
@@ -305,6 +305,7 @@ static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp,
        struct cls_fl_filter *f;
 
        list_for_each_entry_rcu(mask, &head->masks, list) {
+               flow_dissector_init_keys(&skb_key.control, &skb_key.basic);
                fl_clear_masked_range(&skb_key, mask);
 
                skb_flow_dissect_meta(skb, &mask->dissector, &skb_key);
index 748e3b1..6a16af4 100644 (file)
@@ -170,6 +170,16 @@ static inline bool sctp_chunk_length_valid(struct sctp_chunk *chunk,
        return true;
 }
 
+/* Check for format error in an ABORT chunk */
+static inline bool sctp_err_chunk_valid(struct sctp_chunk *chunk)
+{
+       struct sctp_errhdr *err;
+
+       sctp_walk_errors(err, chunk->chunk_hdr);
+
+       return (void *)err == (void *)chunk->chunk_end;
+}
+
 /**********************************************************
  * These are the state functions for handling chunk events.
  **********************************************************/
@@ -2255,6 +2265,9 @@ enum sctp_disposition sctp_sf_shutdown_pending_abort(
                    sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
                return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
 
+       if (!sctp_err_chunk_valid(chunk))
+               return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+
        return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands);
 }
 
@@ -2298,6 +2311,9 @@ enum sctp_disposition sctp_sf_shutdown_sent_abort(
                    sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
                return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
 
+       if (!sctp_err_chunk_valid(chunk))
+               return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+
        /* Stop the T2-shutdown timer. */
        sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
@@ -2565,6 +2581,9 @@ enum sctp_disposition sctp_sf_do_9_1_abort(
                    sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest))
                return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands);
 
+       if (!sctp_err_chunk_valid(chunk))
+               return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
+
        return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands);
 }
 
@@ -2582,16 +2601,8 @@ static enum sctp_disposition __sctp_sf_do_9_1_abort(
 
        /* See if we have an error cause code in the chunk.  */
        len = ntohs(chunk->chunk_hdr->length);
-       if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) {
-               struct sctp_errhdr *err;
-
-               sctp_walk_errors(err, chunk->chunk_hdr);
-               if ((void *)err != (void *)chunk->chunk_end)
-                       return sctp_sf_pdiscard(net, ep, asoc, type, arg,
-                                               commands);
-
+       if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
                error = ((struct sctp_errhdr *)chunk->skb->data)->cause;
-       }
 
        sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET));
        /* ASSOC_FAILED will DELETE_TCB. */
index 1ba5a92..1c5574e 100644 (file)
@@ -593,7 +593,7 @@ struct tls_record_info *tls_get_record(struct tls_offload_context_tx *context,
                                       u32 seq, u64 *p_record_sn)
 {
        u64 record_sn = context->hint_record_sn;
-       struct tls_record_info *info;
+       struct tls_record_info *info, *last;
 
        info = context->retransmit_hint;
        if (!info ||
@@ -605,6 +605,24 @@ struct tls_record_info *tls_get_record(struct tls_offload_context_tx *context,
                                                struct tls_record_info, list);
                if (!info)
                        return NULL;
+               /* send the start_marker record if seq number is before the
+                * tls offload start marker sequence number. This record is
+                * required to handle TCP packets which are before TLS offload
+                * started.
+                *  And if it's not start marker, look if this seq number
+                * belongs to the list.
+                */
+               if (likely(!tls_record_is_start_marker(info))) {
+                       /* we have the first record, get the last record to see
+                        * if this seq number belongs to the list.
+                        */
+                       last = list_last_entry(&context->records_list,
+                                              struct tls_record_info, list);
+
+                       if (!between(seq, tls_record_start_seq(info),
+                                    last->end_seq))
+                               return NULL;
+               }
                record_sn = context->unacked_record_sn;
        }
 
index df60048..356f90e 100644 (file)
@@ -217,6 +217,7 @@ static int xsk_rcv(struct xdp_sock *xs, struct xdp_buff *xdp)
 static void xsk_flush(struct xdp_sock *xs)
 {
        xskq_prod_submit(xs->rx);
+       __xskq_cons_release(xs->umem->fq);
        sock_def_readable(&xs->sk);
 }
 
@@ -304,6 +305,7 @@ void xsk_umem_consume_tx_done(struct xdp_umem *umem)
 
        rcu_read_lock();
        list_for_each_entry_rcu(xs, &umem->xsk_list, list) {
+               __xskq_cons_release(xs->tx);
                xs->sk.sk_write_space(&xs->sk);
        }
        rcu_read_unlock();
index bec2af1..89a01ac 100644 (file)
@@ -271,7 +271,8 @@ static inline void xskq_cons_release(struct xsk_queue *q)
 {
        /* To improve performance, only update local state here.
         * Reflect this to global state when we get new entries
-        * from the ring in xskq_cons_get_entries().
+        * from the ring in xskq_cons_get_entries() and whenever
+        * Rx or Tx processing are completed in the NAPI loop.
         */
        q->cached_cons++;
 }
index 34085d1..6cbcd1a 100755 (executable)
@@ -932,10 +932,6 @@ sub get_maintainers {
        }
     }
 
-    foreach my $fix (@fixes) {
-       vcs_add_commit_signers($fix, "blamed_fixes");
-    }
-
     foreach my $email (@email_to, @list_to) {
        $email->[0] = deduplicate_email($email->[0]);
     }
@@ -974,6 +970,10 @@ sub get_maintainers {
        }
     }
 
+    foreach my $fix (@fixes) {
+       vcs_add_commit_signers($fix, "blamed_fixes");
+    }
+
     my @to = ();
     if ($email || $email_list) {
        if ($email) {
@@ -1341,35 +1341,11 @@ sub add_categories {
                    }
                }
            } elsif ($ptype eq "M") {
-               my ($name, $address) = parse_email($pvalue);
-               if ($name eq "") {
-                   if ($i > 0) {
-                       my $tv = $typevalue[$i - 1];
-                       if ($tv =~ m/^([A-Z]):\s*(.*)/) {
-                           if ($1 eq "P") {
-                               $name = $2;
-                               $pvalue = format_email($name, $address, $email_usename);
-                           }
-                       }
-                   }
-               }
                if ($email_maintainer) {
                    my $role = get_maintainer_role($i);
                    push_email_addresses($pvalue, $role);
                }
            } elsif ($ptype eq "R") {
-               my ($name, $address) = parse_email($pvalue);
-               if ($name eq "") {
-                   if ($i > 0) {
-                       my $tv = $typevalue[$i - 1];
-                       if ($tv =~ m/^([A-Z]):\s*(.*)/) {
-                           if ($1 eq "P") {
-                               $name = $2;
-                               $pvalue = format_email($name, $address, $email_usename);
-                           }
-                       }
-                   }
-               }
                if ($email_reviewer) {
                    my $subsystem = get_subsystem_name($i);
                    push_email_addresses($pvalue, "reviewer:$subsystem");
index 711ff10..3f3ee4e 100644 (file)
@@ -112,6 +112,10 @@ choice
        config IMA_DEFAULT_HASH_WP512
                bool "WP512"
                depends on CRYPTO_WP512=y && !IMA_TEMPLATE
+
+       config IMA_DEFAULT_HASH_SM3
+               bool "SM3"
+               depends on CRYPTO_SM3=y && !IMA_TEMPLATE
 endchoice
 
 config IMA_DEFAULT_HASH
@@ -121,6 +125,7 @@ config IMA_DEFAULT_HASH
        default "sha256" if IMA_DEFAULT_HASH_SHA256
        default "sha512" if IMA_DEFAULT_HASH_SHA512
        default "wp512" if IMA_DEFAULT_HASH_WP512
+       default "sm3" if IMA_DEFAULT_HASH_SM3
 
 config IMA_WRITE_POLICY
        bool "Enable multiple writes to the IMA policy"
index 111898a..f0c9082 100644 (file)
@@ -35,16 +35,18 @@ static __init bool uefi_check_ignore_db(void)
  * Get a certificate list blob from the named EFI variable.
  */
 static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
-                                 unsigned long *size)
+                                 unsigned long *size, efi_status_t *status)
 {
-       efi_status_t status;
        unsigned long lsize = 4;
        unsigned long tmpdb[4];
        void *db;
 
-       status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
-       if (status != EFI_BUFFER_TOO_SMALL) {
-               pr_err("Couldn't get size: 0x%lx\n", status);
+       *status = efi.get_variable(name, guid, NULL, &lsize, &tmpdb);
+       if (*status == EFI_NOT_FOUND)
+               return NULL;
+
+       if (*status != EFI_BUFFER_TOO_SMALL) {
+               pr_err("Couldn't get size: 0x%lx\n", *status);
                return NULL;
        }
 
@@ -52,10 +54,10 @@ static __init void *get_cert_list(efi_char16_t *name, efi_guid_t *guid,
        if (!db)
                return NULL;
 
-       status = efi.get_variable(name, guid, NULL, &lsize, db);
-       if (status != EFI_SUCCESS) {
+       *status = efi.get_variable(name, guid, NULL, &lsize, db);
+       if (*status != EFI_SUCCESS) {
                kfree(db);
-               pr_err("Error reading db var: 0x%lx\n", status);
+               pr_err("Error reading db var: 0x%lx\n", *status);
                return NULL;
        }
 
@@ -74,6 +76,7 @@ static int __init load_uefi_certs(void)
        efi_guid_t mok_var = EFI_SHIM_LOCK_GUID;
        void *db = NULL, *dbx = NULL, *mok = NULL;
        unsigned long dbsize = 0, dbxsize = 0, moksize = 0;
+       efi_status_t status;
        int rc = 0;
 
        if (!efi.get_variable)
@@ -83,9 +86,12 @@ static int __init load_uefi_certs(void)
         * an error if we can't get them.
         */
        if (!uefi_check_ignore_db()) {
-               db = get_cert_list(L"db", &secure_var, &dbsize);
+               db = get_cert_list(L"db", &secure_var, &dbsize, &status);
                if (!db) {
-                       pr_err("MODSIGN: Couldn't get UEFI db list\n");
+                       if (status == EFI_NOT_FOUND)
+                               pr_debug("MODSIGN: db variable wasn't found\n");
+                       else
+                               pr_err("MODSIGN: Couldn't get UEFI db list\n");
                } else {
                        rc = parse_efi_signature_list("UEFI:db",
                                        db, dbsize, get_handler_for_db);
@@ -96,9 +102,12 @@ static int __init load_uefi_certs(void)
                }
        }
 
-       mok = get_cert_list(L"MokListRT", &mok_var, &moksize);
+       mok = get_cert_list(L"MokListRT", &mok_var, &moksize, &status);
        if (!mok) {
-               pr_info("Couldn't get UEFI MokListRT\n");
+               if (status == EFI_NOT_FOUND)
+                       pr_debug("MokListRT variable wasn't found\n");
+               else
+                       pr_info("Couldn't get UEFI MokListRT\n");
        } else {
                rc = parse_efi_signature_list("UEFI:MokListRT",
                                              mok, moksize, get_handler_for_db);
@@ -107,9 +116,12 @@ static int __init load_uefi_certs(void)
                kfree(mok);
        }
 
-       dbx = get_cert_list(L"dbx", &secure_var, &dbxsize);
+       dbx = get_cert_list(L"dbx", &secure_var, &dbxsize, &status);
        if (!dbx) {
-               pr_info("Couldn't get UEFI dbx list\n");
+               if (status == EFI_NOT_FOUND)
+                       pr_debug("dbx variable wasn't found\n");
+               else
+                       pr_info("Couldn't get UEFI dbx list\n");
        } else {
                rc = parse_efi_signature_list("UEFI:dbx",
                                              dbx, dbxsize,
index 6d9592f..cc93157 100644 (file)
@@ -580,7 +580,7 @@ static int update_timestamp_of_queue(struct snd_seq_event *event,
        event->queue = queue;
        event->flags &= ~SNDRV_SEQ_TIME_STAMP_MASK;
        if (real_time) {
-               event->time.time = snd_seq_timer_get_cur_time(q->timer);
+               event->time.time = snd_seq_timer_get_cur_time(q->timer, true);
                event->flags |= SNDRV_SEQ_TIME_STAMP_REAL;
        } else {
                event->time.tick = snd_seq_timer_get_cur_tick(q->timer);
@@ -1659,7 +1659,7 @@ static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client,
        tmr = queue->timer;
        status->events = queue->tickq->cells + queue->timeq->cells;
 
-       status->time = snd_seq_timer_get_cur_time(tmr);
+       status->time = snd_seq_timer_get_cur_time(tmr, true);
        status->tick = snd_seq_timer_get_cur_tick(tmr);
 
        status->running = tmr->running;
index caf68bf..71a6ea6 100644 (file)
@@ -238,6 +238,8 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
 {
        unsigned long flags;
        struct snd_seq_event_cell *cell;
+       snd_seq_tick_time_t cur_tick;
+       snd_seq_real_time_t cur_time;
 
        if (q == NULL)
                return;
@@ -254,17 +256,18 @@ void snd_seq_check_queue(struct snd_seq_queue *q, int atomic, int hop)
 
       __again:
        /* Process tick queue... */
+       cur_tick = snd_seq_timer_get_cur_tick(q->timer);
        for (;;) {
-               cell = snd_seq_prioq_cell_out(q->tickq,
-                                             &q->timer->tick.cur_tick);
+               cell = snd_seq_prioq_cell_out(q->tickq, &cur_tick);
                if (!cell)
                        break;
                snd_seq_dispatch_event(cell, atomic, hop);
        }
 
        /* Process time queue... */
+       cur_time = snd_seq_timer_get_cur_time(q->timer, false);
        for (;;) {
-               cell = snd_seq_prioq_cell_out(q->timeq, &q->timer->cur_time);
+               cell = snd_seq_prioq_cell_out(q->timeq, &cur_time);
                if (!cell)
                        break;
                snd_seq_dispatch_event(cell, atomic, hop);
@@ -392,6 +395,7 @@ int snd_seq_queue_check_access(int queueid, int client)
 int snd_seq_queue_set_owner(int queueid, int client, int locked)
 {
        struct snd_seq_queue *q = queueptr(queueid);
+       unsigned long flags;
 
        if (q == NULL)
                return -EINVAL;
@@ -401,8 +405,10 @@ int snd_seq_queue_set_owner(int queueid, int client, int locked)
                return -EPERM;
        }
 
+       spin_lock_irqsave(&q->owner_lock, flags);
        q->locked = locked ? 1 : 0;
        q->owner = client;
+       spin_unlock_irqrestore(&q->owner_lock, flags);
        queue_access_unlock(q);
        queuefree(q);
 
@@ -539,15 +545,17 @@ void snd_seq_queue_client_termination(int client)
        unsigned long flags;
        int i;
        struct snd_seq_queue *q;
+       bool matched;
 
        for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
                if ((q = queueptr(i)) == NULL)
                        continue;
                spin_lock_irqsave(&q->owner_lock, flags);
-               if (q->owner == client)
+               matched = (q->owner == client);
+               if (matched)
                        q->klocked = 1;
                spin_unlock_irqrestore(&q->owner_lock, flags);
-               if (q->owner == client) {
+               if (matched) {
                        if (q->timer->running)
                                snd_seq_timer_stop(q->timer);
                        snd_seq_timer_reset(q->timer);
@@ -739,6 +747,8 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry,
        int i, bpm;
        struct snd_seq_queue *q;
        struct snd_seq_timer *tmr;
+       bool locked;
+       int owner;
 
        for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
                if ((q = queueptr(i)) == NULL)
@@ -750,9 +760,14 @@ void snd_seq_info_queues_read(struct snd_info_entry *entry,
                else
                        bpm = 0;
 
+               spin_lock_irq(&q->owner_lock);
+               locked = q->locked;
+               owner = q->owner;
+               spin_unlock_irq(&q->owner_lock);
+
                snd_iprintf(buffer, "queue %d: [%s]\n", q->queue, q->name);
-               snd_iprintf(buffer, "owned by client    : %d\n", q->owner);
-               snd_iprintf(buffer, "lock status        : %s\n", q->locked ? "Locked" : "Free");
+               snd_iprintf(buffer, "owned by client    : %d\n", owner);
+               snd_iprintf(buffer, "lock status        : %s\n", locked ? "Locked" : "Free");
                snd_iprintf(buffer, "queued time events : %d\n", snd_seq_prioq_avail(q->timeq));
                snd_iprintf(buffer, "queued tick events : %d\n", snd_seq_prioq_avail(q->tickq));
                snd_iprintf(buffer, "timer state        : %s\n", tmr->running ? "Running" : "Stopped");
index be59b59..1645e41 100644 (file)
@@ -428,14 +428,15 @@ int snd_seq_timer_continue(struct snd_seq_timer *tmr)
 }
 
 /* return current 'real' time. use timeofday() to get better granularity. */
-snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
+snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr,
+                                              bool adjust_ktime)
 {
        snd_seq_real_time_t cur_time;
        unsigned long flags;
 
        spin_lock_irqsave(&tmr->lock, flags);
        cur_time = tmr->cur_time;
-       if (tmr->running) { 
+       if (adjust_ktime && tmr->running) {
                struct timespec64 tm;
 
                ktime_get_ts64(&tm);
@@ -452,7 +453,13 @@ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
  high PPQ values) */
 snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr)
 {
-       return tmr->tick.cur_tick;
+       snd_seq_tick_time_t cur_tick;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tmr->lock, flags);
+       cur_tick = tmr->tick.cur_tick;
+       spin_unlock_irqrestore(&tmr->lock, flags);
+       return cur_tick;
 }
 
 
index 66c3e34..4bec57d 100644 (file)
@@ -120,7 +120,8 @@ int snd_seq_timer_set_tempo_ppq(struct snd_seq_timer *tmr, int tempo, int ppq);
 int snd_seq_timer_set_position_tick(struct snd_seq_timer *tmr, snd_seq_tick_time_t position);
 int snd_seq_timer_set_position_time(struct snd_seq_timer *tmr, snd_seq_real_time_t position);
 int snd_seq_timer_set_skew(struct snd_seq_timer *tmr, unsigned int skew, unsigned int base);
-snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr);
+snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr,
+                                              bool adjust_ktime);
 snd_seq_tick_time_t snd_seq_timer_get_cur_tick(struct snd_seq_timer *tmr);
 
 extern int seq_default_timer_class;
index a684f05..4d060d5 100644 (file)
@@ -254,6 +254,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down_all);
 int snd_hdac_ext_bus_link_get(struct hdac_bus *bus,
                                struct hdac_ext_link *link)
 {
+       unsigned long codec_mask;
        int ret = 0;
 
        mutex_lock(&bus->lock);
@@ -280,9 +281,11 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus,
                 *  HDA spec section 4.3 - Codec Discovery
                 */
                udelay(521);
-               bus->codec_mask = snd_hdac_chip_readw(bus, STATESTS);
-               dev_dbg(bus->dev, "codec_mask = 0x%lx\n", bus->codec_mask);
-               snd_hdac_chip_writew(bus, STATESTS, bus->codec_mask);
+               codec_mask = snd_hdac_chip_readw(bus, STATESTS);
+               dev_dbg(bus->dev, "codec_mask = 0x%lx\n", codec_mask);
+               snd_hdac_chip_writew(bus, STATESTS, codec_mask);
+               if (!bus->codec_mask)
+                       bus->codec_mask = codec_mask;
        }
 
        mutex_unlock(&bus->lock);
index 5fd6d57..aad5c4b 100644 (file)
@@ -250,7 +250,7 @@ void snd_hdac_print_channel_allocation(int spk_alloc, char *buf, int buflen)
 
        for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) {
                if (spk_alloc & (1 << i))
-                       j += snprintf(buf + j, buflen - j,  " %s",
+                       j += scnprintf(buf + j, buflen - j,  " %s",
                                        cea_speaker_allocation_names[i]);
        }
        buf[j] = '\0';  /* necessary when j == 0 */
index 5dc42f9..53e7732 100644 (file)
@@ -4022,7 +4022,7 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen)
 
        for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
                if (pcm & (AC_SUPPCM_BITS_8 << i))
-                       j += snprintf(buf + j, buflen - j,  " %d", bits[i]);
+                       j += scnprintf(buf + j, buflen - j,  " %d", bits[i]);
 
        buf[j] = '\0'; /* necessary when j == 0 */
 }
index bb46c89..136477e 100644 (file)
@@ -360,7 +360,7 @@ static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
 
        for (i = 0, j = 0; i < ARRAY_SIZE(alsa_rates); i++)
                if (pcm & (1 << i))
-                       j += snprintf(buf + j, buflen - j,  " %d",
+                       j += scnprintf(buf + j, buflen - j,  " %d",
                                alsa_rates[i]);
 
        buf[j] = '\0'; /* necessary when j == 0 */
index 0607ed5..eb8ec10 100644 (file)
@@ -222,7 +222,7 @@ static ssize_t init_verbs_show(struct device *dev,
        int i, len = 0;
        mutex_lock(&codec->user_mutex);
        snd_array_for_each(&codec->init_verbs, i, v) {
-               len += snprintf(buf + len, PAGE_SIZE - len,
+               len += scnprintf(buf + len, PAGE_SIZE - len,
                                "0x%02x 0x%03x 0x%04x\n",
                                v->nid, v->verb, v->param);
        }
@@ -272,7 +272,7 @@ static ssize_t hints_show(struct device *dev,
        int i, len = 0;
        mutex_lock(&codec->user_mutex);
        snd_array_for_each(&codec->hints, i, hint) {
-               len += snprintf(buf + len, PAGE_SIZE - len,
+               len += scnprintf(buf + len, PAGE_SIZE - len,
                                "%s = %s\n", hint->key, hint->val);
        }
        mutex_unlock(&codec->user_mutex);
index 6c8cb4c..477589e 100644 (file)
@@ -2447,7 +2447,9 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
        SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
+       SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
        SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
        SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
index 31cd400..91a3881 100644 (file)
@@ -170,6 +170,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
        struct snd_soc_card *card;
        struct acp3x_platform_info *pinfo;
        u32 ret, val, period_bytes, reg_val, ier_val, water_val;
+       u32 buf_size, buf_reg;
 
        prtd = substream->private_data;
        rtd = substream->runtime->private_data;
@@ -183,6 +184,8 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
        }
        period_bytes = frames_to_bytes(substream->runtime,
                        substream->runtime->period_size);
+       buf_size = frames_to_bytes(substream->runtime,
+                       substream->runtime->buffer_size);
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
@@ -196,6 +199,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
                                        mmACP_BT_TX_INTR_WATERMARK_SIZE;
                                reg_val = mmACP_BTTDM_ITER;
                                ier_val = mmACP_BTTDM_IER;
+                               buf_reg = mmACP_BT_TX_RINGBUFSIZE;
                                break;
                        case I2S_SP_INSTANCE:
                        default:
@@ -203,6 +207,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
                                        mmACP_I2S_TX_INTR_WATERMARK_SIZE;
                                reg_val = mmACP_I2STDM_ITER;
                                ier_val = mmACP_I2STDM_IER;
+                               buf_reg = mmACP_I2S_TX_RINGBUFSIZE;
                        }
                } else {
                        switch (rtd->i2s_instance) {
@@ -211,6 +216,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
                                        mmACP_BT_RX_INTR_WATERMARK_SIZE;
                                reg_val = mmACP_BTTDM_IRER;
                                ier_val = mmACP_BTTDM_IER;
+                               buf_reg = mmACP_BT_RX_RINGBUFSIZE;
                                break;
                        case I2S_SP_INSTANCE:
                        default:
@@ -218,9 +224,11 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream,
                                        mmACP_I2S_RX_INTR_WATERMARK_SIZE;
                                reg_val = mmACP_I2STDM_IRER;
                                ier_val = mmACP_I2STDM_IER;
+                               buf_reg = mmACP_I2S_RX_RINGBUFSIZE;
                        }
                }
                rv_writel(period_bytes, rtd->acp3x_base + water_val);
+               rv_writel(buf_size, rtd->acp3x_base + buf_reg);
                val = rv_readl(rtd->acp3x_base + reg_val);
                val = val | BIT(0);
                rv_writel(val, rtd->acp3x_base + reg_val);
index aecc3c0..d62c0d9 100644 (file)
@@ -110,7 +110,7 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 {
        u16 page_idx;
        u32 low, high, val, acp_fifo_addr, reg_fifo_addr;
-       u32 reg_ringbuf_size, reg_dma_size, reg_fifo_size;
+       u32 reg_dma_size, reg_fifo_size;
        dma_addr_t addr;
 
        addr = rtd->dma_addr;
@@ -157,7 +157,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
        if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
                switch (rtd->i2s_instance) {
                case I2S_BT_INSTANCE:
-                       reg_ringbuf_size = mmACP_BT_TX_RINGBUFSIZE;
                        reg_dma_size = mmACP_BT_TX_DMA_SIZE;
                        acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
                                                BT_PB_FIFO_ADDR_OFFSET;
@@ -169,7 +168,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 
                case I2S_SP_INSTANCE:
                default:
-                       reg_ringbuf_size = mmACP_I2S_TX_RINGBUFSIZE;
                        reg_dma_size = mmACP_I2S_TX_DMA_SIZE;
                        acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
                                                SP_PB_FIFO_ADDR_OFFSET;
@@ -181,7 +179,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
        } else {
                switch (rtd->i2s_instance) {
                case I2S_BT_INSTANCE:
-                       reg_ringbuf_size = mmACP_BT_RX_RINGBUFSIZE;
                        reg_dma_size = mmACP_BT_RX_DMA_SIZE;
                        acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
                                                BT_CAPT_FIFO_ADDR_OFFSET;
@@ -193,7 +190,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
 
                case I2S_SP_INSTANCE:
                default:
-                       reg_ringbuf_size = mmACP_I2S_RX_RINGBUFSIZE;
                        reg_dma_size = mmACP_I2S_RX_DMA_SIZE;
                        acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
                                                SP_CAPT_FIFO_ADDR_OFFSET;
@@ -203,7 +199,6 @@ static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
                                rtd->acp3x_base + mmACP_I2S_RX_RINGBUFADDR);
                }
        }
-       rv_writel(MAX_BUFFER, rtd->acp3x_base + reg_ringbuf_size);
        rv_writel(DMA_SIZE, rtd->acp3x_base + reg_dma_size);
        rv_writel(acp_fifo_addr, rtd->acp3x_base + reg_fifo_addr);
        rv_writel(FIFO_SIZE, rtd->acp3x_base + reg_fifo_size);
index 65330bb..da60e2e 100644 (file)
@@ -45,23 +45,6 @@ static int acp3x_power_on(void __iomem *acp3x_base)
        return -ETIMEDOUT;
 }
 
-static int acp3x_power_off(void __iomem *acp3x_base)
-{
-       u32 val;
-       int timeout;
-
-       rv_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
-                       acp3x_base + mmACP_PGFSM_CONTROL);
-       timeout = 0;
-       while (++timeout < 500) {
-               val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
-               if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
-                       return 0;
-               udelay(1);
-       }
-       return -ETIMEDOUT;
-}
-
 static int acp3x_reset(void __iomem *acp3x_base)
 {
        u32 val;
@@ -115,12 +98,6 @@ static int acp3x_deinit(void __iomem *acp3x_base)
                pr_err("ACP3x reset failed\n");
                return ret;
        }
-       /* power off */
-       ret = acp3x_power_off(acp3x_base);
-       if (ret) {
-               pr_err("ACP3x power off failed\n");
-               return ret;
-       }
        return 0;
 }
 
index d1dc8e6..71f2d42 100644 (file)
@@ -10,11 +10,11 @@ config SND_ATMEL_SOC
 if SND_ATMEL_SOC
 
 config SND_ATMEL_SOC_PDC
-       tristate
+       bool
        depends on HAS_DMA
 
 config SND_ATMEL_SOC_DMA
-       tristate
+       bool
        select SND_SOC_GENERIC_DMAENGINE_PCM
 
 config SND_ATMEL_SOC_SSC
index 1f6890e..c7d2989 100644 (file)
@@ -6,8 +6,14 @@ snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
 snd-soc-atmel-i2s-objs := atmel-i2s.o
 snd-soc-mchp-i2s-mcc-objs := mchp-i2s-mcc.o
 
-obj-$(CONFIG_SND_ATMEL_SOC_PDC) += snd-soc-atmel-pcm-pdc.o
-obj-$(CONFIG_SND_ATMEL_SOC_DMA) += snd-soc-atmel-pcm-dma.o
+# pdc and dma need to both be built-in if any user of
+# ssc is built-in.
+ifdef CONFIG_SND_ATMEL_SOC_PDC
+obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel-pcm-pdc.o
+endif
+ifdef CONFIG_SND_ATMEL_SOC_DMA
+obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel-pcm-dma.o
+endif
 obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
 obj-$(CONFIG_SND_ATMEL_SOC_I2S) += snd-soc-atmel-i2s.o
 obj-$(CONFIG_SND_MCHP_SOC_I2S_MCC) += snd-soc-mchp-i2s-mcc.o
index 444cc4e..f005751 100644 (file)
@@ -779,7 +779,17 @@ static int hdmi_of_xlate_dai_id(struct snd_soc_component *component,
        return ret;
 }
 
+static void hdmi_remove(struct snd_soc_component *component)
+{
+       struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);
+
+       if (hcp->hcd.ops->hook_plugged_cb)
+               hcp->hcd.ops->hook_plugged_cb(component->dev->parent,
+                                             hcp->hcd.data, NULL, NULL);
+}
+
 static const struct snd_soc_component_driver hdmi_driver = {
+       .remove                 = hdmi_remove,
        .dapm_widgets           = hdmi_widgets,
        .num_dapm_widgets       = ARRAY_SIZE(hdmi_widgets),
        .of_xlate_dai_id        = hdmi_of_xlate_dai_id,
index 5bc2c64..032adc1 100644 (file)
  * Copyright 2011-2012 Maxim Integrated Products
  */
 
-#include <linux/acpi.h>
-#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
-#include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
+#include <linux/acpi.h>
+#include <linux/clk.h>
 #include <sound/jack.h>
-#include <sound/max98090.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/tlv.h>
+#include <sound/max98090.h>
 #include "max98090.h"
 
-static void max98090_shdn_save_locked(struct max98090_priv *max98090)
-{
-       int shdn = 0;
-
-       /* saved_shdn, saved_count, SHDN are protected by card->dapm_mutex */
-       regmap_read(max98090->regmap, M98090_REG_DEVICE_SHUTDOWN, &shdn);
-       max98090->saved_shdn |= shdn;
-       ++max98090->saved_count;
-
-       if (shdn)
-               regmap_write(max98090->regmap, M98090_REG_DEVICE_SHUTDOWN, 0x0);
-}
-
-static void max98090_shdn_restore_locked(struct max98090_priv *max98090)
-{
-       /* saved_shdn, saved_count, SHDN are protected by card->dapm_mutex */
-       if (--max98090->saved_count == 0) {
-               if (max98090->saved_shdn) {
-                       regmap_write(max98090->regmap,
-                                    M98090_REG_DEVICE_SHUTDOWN,
-                                    M98090_SHDNN_MASK);
-                       max98090->saved_shdn = 0;
-               }
-       }
-}
-
-static void max98090_shdn_save(struct max98090_priv *max98090)
-{
-       mutex_lock_nested(&max98090->component->card->dapm_mutex,
-                         SND_SOC_DAPM_CLASS_RUNTIME);
-       max98090_shdn_save_locked(max98090);
-}
-
-static void max98090_shdn_restore(struct max98090_priv *max98090)
-{
-       max98090_shdn_restore_locked(max98090);
-       mutex_unlock(&max98090->component->card->dapm_mutex);
-}
-
-static int max98090_put_volsw(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_component *component =
-               snd_soc_kcontrol_component(kcontrol);
-       struct max98090_priv *max98090 =
-               snd_soc_component_get_drvdata(component);
-       int ret;
-
-       max98090_shdn_save(max98090);
-       ret = snd_soc_put_volsw(kcontrol, ucontrol);
-       max98090_shdn_restore(max98090);
-
-       return ret;
-}
-
-static int max98090_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_component *component =
-               snd_soc_dapm_kcontrol_component(kcontrol);
-       struct max98090_priv *max98090 =
-               snd_soc_component_get_drvdata(component);
-       int ret;
-
-       max98090_shdn_save(max98090);
-       ret = snd_soc_dapm_put_enum_double_locked(kcontrol, ucontrol);
-       max98090_shdn_restore(max98090);
-
-       return ret;
-}
-
-static int max98090_put_enum_double(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_component *component =
-               snd_soc_kcontrol_component(kcontrol);
-       struct max98090_priv *max98090 =
-               snd_soc_component_get_drvdata(component);
-       int ret;
-
-       max98090_shdn_save(max98090);
-       ret = snd_soc_put_enum_double(kcontrol, ucontrol);
-       max98090_shdn_restore(max98090);
-
-       return ret;
-}
-
-static int max98090_bytes_put(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       struct snd_soc_component *component =
-               snd_soc_kcontrol_component(kcontrol);
-       struct max98090_priv *max98090 =
-               snd_soc_component_get_drvdata(component);
-       int ret;
-
-       max98090_shdn_save(max98090);
-       ret = snd_soc_bytes_put(kcontrol, ucontrol);
-       max98090_shdn_restore(max98090);
-
-       return ret;
-}
-
-static int max98090_dapm_event(struct snd_soc_dapm_widget *w,
-       struct snd_kcontrol *kcontrol, int event)
-{
-       struct snd_soc_component *component =
-               snd_soc_dapm_to_component(w->dapm);
-       struct max98090_priv *max98090 =
-               snd_soc_component_get_drvdata(component);
-
-       switch (event) {
-       case SND_SOC_DAPM_PRE_PMU:
-       case SND_SOC_DAPM_PRE_PMD:
-               max98090_shdn_save_locked(max98090);
-               break;
-       case SND_SOC_DAPM_POST_PMU:
-       case SND_SOC_DAPM_POST_PMD:
-               max98090_shdn_restore_locked(max98090);
-               break;
-       }
-
-       return 0;
-}
-
 /* Allows for sparsely populated register maps */
 static const struct reg_default max98090_reg[] = {
        { 0x00, 0x00 }, /* 00 Software Reset */
@@ -632,13 +506,10 @@ static SOC_ENUM_SINGLE_DECL(max98090_adchp_enum,
                            max98090_pwr_perf_text);
 
 static const struct snd_kcontrol_new max98090_snd_controls[] = {
-       SOC_ENUM_EXT("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
+       SOC_ENUM("MIC Bias VCM Bandgap", max98090_vcmbandgap_enum),
 
-       SOC_SINGLE_EXT("DMIC MIC Comp Filter Config",
-               M98090_REG_DIGITAL_MIC_CONFIG,
-               M98090_DMIC_COMP_SHIFT, M98090_DMIC_COMP_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
+       SOC_SINGLE("DMIC MIC Comp Filter Config", M98090_REG_DIGITAL_MIC_CONFIG,
+               M98090_DMIC_COMP_SHIFT, M98090_DMIC_COMP_NUM - 1, 0),
 
        SOC_SINGLE_EXT_TLV("MIC1 Boost Volume",
                M98090_REG_MIC1_INPUT_LEVEL, M98090_MIC_PA1EN_SHIFT,
@@ -693,34 +564,24 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
                M98090_AVR_SHIFT, M98090_AVR_NUM - 1, 1,
                max98090_av_tlv),
 
-       SOC_ENUM_EXT("ADC Oversampling Rate", max98090_osr128_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_SINGLE_EXT("ADC Quantizer Dither", M98090_REG_ADC_CONTROL,
-               M98090_ADCDITHER_SHIFT, M98090_ADCDITHER_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_ENUM_EXT("ADC High Performance Mode", max98090_adchp_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-
-       SOC_SINGLE_EXT("DAC Mono Mode", M98090_REG_IO_CONFIGURATION,
-               M98090_DMONO_SHIFT, M98090_DMONO_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_SINGLE_EXT("SDIN Mode", M98090_REG_IO_CONFIGURATION,
-               M98090_SDIEN_SHIFT, M98090_SDIEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_SINGLE_EXT("SDOUT Mode", M98090_REG_IO_CONFIGURATION,
-               M98090_SDOEN_SHIFT, M98090_SDOEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_SINGLE_EXT("SDOUT Hi-Z Mode", M98090_REG_IO_CONFIGURATION,
-               M98090_HIZOFF_SHIFT, M98090_HIZOFF_NUM - 1, 1,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_ENUM_EXT("Filter Mode", max98090_mode_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_SINGLE_EXT("Record Path DC Blocking", M98090_REG_FILTER_CONFIG,
-               M98090_AHPF_SHIFT, M98090_AHPF_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_SINGLE_EXT("Playback Path DC Blocking", M98090_REG_FILTER_CONFIG,
-               M98090_DHPF_SHIFT, M98090_DHPF_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
+       SOC_ENUM("ADC Oversampling Rate", max98090_osr128_enum),
+       SOC_SINGLE("ADC Quantizer Dither", M98090_REG_ADC_CONTROL,
+               M98090_ADCDITHER_SHIFT, M98090_ADCDITHER_NUM - 1, 0),
+       SOC_ENUM("ADC High Performance Mode", max98090_adchp_enum),
+
+       SOC_SINGLE("DAC Mono Mode", M98090_REG_IO_CONFIGURATION,
+               M98090_DMONO_SHIFT, M98090_DMONO_NUM - 1, 0),
+       SOC_SINGLE("SDIN Mode", M98090_REG_IO_CONFIGURATION,
+               M98090_SDIEN_SHIFT, M98090_SDIEN_NUM - 1, 0),
+       SOC_SINGLE("SDOUT Mode", M98090_REG_IO_CONFIGURATION,
+               M98090_SDOEN_SHIFT, M98090_SDOEN_NUM - 1, 0),
+       SOC_SINGLE("SDOUT Hi-Z Mode", M98090_REG_IO_CONFIGURATION,
+               M98090_HIZOFF_SHIFT, M98090_HIZOFF_NUM - 1, 1),
+       SOC_ENUM("Filter Mode", max98090_mode_enum),
+       SOC_SINGLE("Record Path DC Blocking", M98090_REG_FILTER_CONFIG,
+               M98090_AHPF_SHIFT, M98090_AHPF_NUM - 1, 0),
+       SOC_SINGLE("Playback Path DC Blocking", M98090_REG_FILTER_CONFIG,
+               M98090_DHPF_SHIFT, M98090_DHPF_NUM - 1, 0),
        SOC_SINGLE_TLV("Digital BQ Volume", M98090_REG_ADC_BIQUAD_LEVEL,
                M98090_AVBQ_SHIFT, M98090_AVBQ_NUM - 1, 1, max98090_dv_tlv),
        SOC_SINGLE_EXT_TLV("Digital Sidetone Volume",
@@ -733,17 +594,13 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
        SOC_SINGLE_TLV("Digital Volume", M98090_REG_DAI_PLAYBACK_LEVEL,
                M98090_DV_SHIFT, M98090_DV_NUM - 1, 1,
                max98090_dv_tlv),
-       SND_SOC_BYTES_E("EQ Coefficients", M98090_REG_EQUALIZER_BASE, 105,
-               snd_soc_bytes_get, max98090_bytes_put),
-       SOC_SINGLE_EXT("Digital EQ 3 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
-               M98090_EQ3BANDEN_SHIFT, M98090_EQ3BANDEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_SINGLE_EXT("Digital EQ 5 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
-               M98090_EQ5BANDEN_SHIFT, M98090_EQ5BANDEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_SINGLE_EXT("Digital EQ 7 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
-               M98090_EQ7BANDEN_SHIFT, M98090_EQ7BANDEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
+       SND_SOC_BYTES("EQ Coefficients", M98090_REG_EQUALIZER_BASE, 105),
+       SOC_SINGLE("Digital EQ 3 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
+               M98090_EQ3BANDEN_SHIFT, M98090_EQ3BANDEN_NUM - 1, 0),
+       SOC_SINGLE("Digital EQ 5 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
+               M98090_EQ5BANDEN_SHIFT, M98090_EQ5BANDEN_NUM - 1, 0),
+       SOC_SINGLE("Digital EQ 7 Band Switch", M98090_REG_DSP_FILTER_ENABLE,
+               M98090_EQ7BANDEN_SHIFT, M98090_EQ7BANDEN_NUM - 1, 0),
        SOC_SINGLE("Digital EQ Clipping Detection", M98090_REG_DAI_PLAYBACK_LEVEL_EQ,
                M98090_EQCLPN_SHIFT, M98090_EQCLPN_NUM - 1,
                1),
@@ -751,34 +608,25 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
                M98090_DVEQ_SHIFT, M98090_DVEQ_NUM - 1, 1,
                max98090_dv_tlv),
 
-       SOC_SINGLE_EXT("ALC Enable", M98090_REG_DRC_TIMING,
-               M98090_DRCEN_SHIFT, M98090_DRCEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
-       SOC_ENUM_EXT("ALC Attack Time", max98090_drcatk_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_ENUM_EXT("ALC Release Time", max98090_drcrls_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
+       SOC_SINGLE("ALC Enable", M98090_REG_DRC_TIMING,
+               M98090_DRCEN_SHIFT, M98090_DRCEN_NUM - 1, 0),
+       SOC_ENUM("ALC Attack Time", max98090_drcatk_enum),
+       SOC_ENUM("ALC Release Time", max98090_drcrls_enum),
        SOC_SINGLE_TLV("ALC Make Up Volume", M98090_REG_DRC_GAIN,
                M98090_DRCG_SHIFT, M98090_DRCG_NUM - 1, 0,
                max98090_alcmakeup_tlv),
-       SOC_ENUM_EXT("ALC Compression Ratio", max98090_alccmp_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_ENUM_EXT("ALC Expansion Ratio", max98090_drcexp_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_SINGLE_EXT_TLV("ALC Compression Threshold Volume",
+       SOC_ENUM("ALC Compression Ratio", max98090_alccmp_enum),
+       SOC_ENUM("ALC Expansion Ratio", max98090_drcexp_enum),
+       SOC_SINGLE_TLV("ALC Compression Threshold Volume",
                M98090_REG_DRC_COMPRESSOR, M98090_DRCTHC_SHIFT,
-               M98090_DRCTHC_NUM - 1, 1,
-               snd_soc_get_volsw, max98090_put_volsw, max98090_alccomp_tlv),
-       SOC_SINGLE_EXT_TLV("ALC Expansion Threshold Volume",
+               M98090_DRCTHC_NUM - 1, 1, max98090_alccomp_tlv),
+       SOC_SINGLE_TLV("ALC Expansion Threshold Volume",
                M98090_REG_DRC_EXPANDER, M98090_DRCTHE_SHIFT,
-               M98090_DRCTHE_NUM - 1, 1,
-               snd_soc_get_volsw, max98090_put_volsw, max98090_drcexp_tlv),
+               M98090_DRCTHE_NUM - 1, 1, max98090_drcexp_tlv),
 
-       SOC_ENUM_EXT("DAC HP Playback Performance Mode",
-               max98090_dac_perfmode_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_ENUM_EXT("DAC High Performance Mode", max98090_dachp_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
+       SOC_ENUM("DAC HP Playback Performance Mode",
+               max98090_dac_perfmode_enum),
+       SOC_ENUM("DAC High Performance Mode", max98090_dachp_enum),
 
        SOC_SINGLE_TLV("Headphone Left Mixer Volume",
                M98090_REG_HP_CONTROL, M98090_MIXHPLG_SHIFT,
@@ -836,12 +684,9 @@ static const struct snd_kcontrol_new max98090_snd_controls[] = {
        SOC_SINGLE("Volume Adjustment Smoothing", M98090_REG_LEVEL_CONTROL,
                M98090_VSENN_SHIFT, M98090_VSENN_NUM - 1, 1),
 
-       SND_SOC_BYTES_E("Biquad Coefficients",
-               M98090_REG_RECORD_BIQUAD_BASE, 15,
-               snd_soc_bytes_get, max98090_bytes_put),
-       SOC_SINGLE_EXT("Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
-               M98090_ADCBQEN_SHIFT, M98090_ADCBQEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
+       SND_SOC_BYTES("Biquad Coefficients", M98090_REG_RECORD_BIQUAD_BASE, 15),
+       SOC_SINGLE("Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
+               M98090_ADCBQEN_SHIFT, M98090_ADCBQEN_NUM - 1, 0),
 };
 
 static const struct snd_kcontrol_new max98091_snd_controls[] = {
@@ -850,12 +695,10 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = {
                M98090_DMIC34_ZEROPAD_SHIFT,
                M98090_DMIC34_ZEROPAD_NUM - 1, 0),
 
-       SOC_ENUM_EXT("Filter DMIC34 Mode", max98090_filter_dmic34mode_enum,
-               snd_soc_get_enum_double, max98090_put_enum_double),
-       SOC_SINGLE_EXT("DMIC34 DC Blocking", M98090_REG_FILTER_CONFIG,
+       SOC_ENUM("Filter DMIC34 Mode", max98090_filter_dmic34mode_enum),
+       SOC_SINGLE("DMIC34 DC Blocking", M98090_REG_FILTER_CONFIG,
                M98090_FLT_DMIC34HPF_SHIFT,
-               M98090_FLT_DMIC34HPF_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
+               M98090_FLT_DMIC34HPF_NUM - 1, 0),
 
        SOC_SINGLE_TLV("DMIC3 Boost Volume", M98090_REG_DMIC3_VOLUME,
                M98090_DMIC_AV3G_SHIFT, M98090_DMIC_AV3G_NUM - 1, 0,
@@ -873,9 +716,8 @@ static const struct snd_kcontrol_new max98091_snd_controls[] = {
 
        SND_SOC_BYTES("DMIC34 Biquad Coefficients",
                M98090_REG_DMIC34_BIQUAD_BASE, 15),
-       SOC_SINGLE_EXT("DMIC34 Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
-               M98090_DMIC34BQEN_SHIFT, M98090_DMIC34BQEN_NUM - 1, 0,
-               snd_soc_get_volsw, max98090_put_volsw),
+       SOC_SINGLE("DMIC34 Biquad Switch", M98090_REG_DSP_FILTER_ENABLE,
+               M98090_DMIC34BQEN_SHIFT, M98090_DMIC34BQEN_NUM - 1, 0),
 
        SOC_SINGLE_TLV("DMIC34 BQ PreAttenuation Volume",
                M98090_REG_DMIC34_BQ_PREATTEN, M98090_AV34BQ_SHIFT,
@@ -929,6 +771,19 @@ static int max98090_micinput_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
+static int max98090_shdn_event(struct snd_soc_dapm_widget *w,
+                                struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
+       struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
+
+       if (event & SND_SOC_DAPM_POST_PMU)
+               max98090->shdn_pending = true;
+
+       return 0;
+
+}
+
 static const char *mic1_mux_text[] = { "IN12", "IN56" };
 
 static SOC_ENUM_SINGLE_DECL(mic1_mux_enum,
@@ -1029,14 +884,10 @@ static SOC_ENUM_SINGLE_DECL(ltenr_mux_enum,
                            lten_mux_text);
 
 static const struct snd_kcontrol_new max98090_ltenl_mux =
-       SOC_DAPM_ENUM_EXT("LTENL Mux", ltenl_mux_enum,
-                         snd_soc_dapm_get_enum_double,
-                         max98090_dapm_put_enum_double);
+       SOC_DAPM_ENUM("LTENL Mux", ltenl_mux_enum);
 
 static const struct snd_kcontrol_new max98090_ltenr_mux =
-       SOC_DAPM_ENUM_EXT("LTENR Mux", ltenr_mux_enum,
-                         snd_soc_dapm_get_enum_double,
-                         max98090_dapm_put_enum_double);
+       SOC_DAPM_ENUM("LTENR Mux", ltenr_mux_enum);
 
 static const char *lben_mux_text[] = { "Normal", "Loopback" };
 
@@ -1051,14 +902,10 @@ static SOC_ENUM_SINGLE_DECL(lbenr_mux_enum,
                            lben_mux_text);
 
 static const struct snd_kcontrol_new max98090_lbenl_mux =
-       SOC_DAPM_ENUM_EXT("LBENL Mux", lbenl_mux_enum,
-                         snd_soc_dapm_get_enum_double,
-                         max98090_dapm_put_enum_double);
+       SOC_DAPM_ENUM("LBENL Mux", lbenl_mux_enum);
 
 static const struct snd_kcontrol_new max98090_lbenr_mux =
-       SOC_DAPM_ENUM_EXT("LBENR Mux", lbenr_mux_enum,
-                         snd_soc_dapm_get_enum_double,
-                         max98090_dapm_put_enum_double);
+       SOC_DAPM_ENUM("LBENR Mux", lbenr_mux_enum);
 
 static const char *stenl_mux_text[] = { "Normal", "Sidetone Left" };
 
@@ -1225,25 +1072,21 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("IN56"),
 
        SND_SOC_DAPM_SUPPLY("MICBIAS", M98090_REG_INPUT_ENABLE,
-               M98090_MBEN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+               M98090_MBEN_SHIFT, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("SHDN", M98090_REG_DEVICE_SHUTDOWN,
                M98090_SHDNN_SHIFT, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("SDIEN", M98090_REG_IO_CONFIGURATION,
-               M98090_SDIEN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+               M98090_SDIEN_SHIFT, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("SDOEN", M98090_REG_IO_CONFIGURATION,
-               M98090_SDOEN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+               M98090_SDOEN_SHIFT, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("DMICL_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
-               M98090_DIGMICL_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+                M98090_DIGMICL_SHIFT, 0, max98090_shdn_event,
+                       SND_SOC_DAPM_POST_PMU),
        SND_SOC_DAPM_SUPPLY("DMICR_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
-               M98090_DIGMICR_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+                M98090_DIGMICR_SHIFT, 0, max98090_shdn_event,
+                        SND_SOC_DAPM_POST_PMU),
        SND_SOC_DAPM_SUPPLY("AHPF", M98090_REG_FILTER_CONFIG,
-               M98090_AHPF_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+               M98090_AHPF_SHIFT, 0, NULL, 0),
 
 /*
  * Note: Sysclk and misc power supplies are taken care of by SHDN
@@ -1273,12 +1116,10 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
                &max98090_lineb_mixer_controls[0],
                ARRAY_SIZE(max98090_lineb_mixer_controls)),
 
-       SND_SOC_DAPM_PGA_E("LINEA Input", M98090_REG_INPUT_ENABLE,
-               M98090_LINEAEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-       SND_SOC_DAPM_PGA_E("LINEB Input", M98090_REG_INPUT_ENABLE,
-               M98090_LINEBEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+       SND_SOC_DAPM_PGA("LINEA Input", M98090_REG_INPUT_ENABLE,
+               M98090_LINEAEN_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("LINEB Input", M98090_REG_INPUT_ENABLE,
+               M98090_LINEBEN_SHIFT, 0, NULL, 0),
 
        SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
                &max98090_left_adc_mixer_controls[0],
@@ -1289,11 +1130,11 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
                ARRAY_SIZE(max98090_right_adc_mixer_controls)),
 
        SND_SOC_DAPM_ADC_E("ADCL", NULL, M98090_REG_INPUT_ENABLE,
-               M98090_ADLEN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+               M98090_ADLEN_SHIFT, 0, max98090_shdn_event,
+               SND_SOC_DAPM_POST_PMU),
        SND_SOC_DAPM_ADC_E("ADCR", NULL, M98090_REG_INPUT_ENABLE,
-               M98090_ADREN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+               M98090_ADREN_SHIFT, 0, max98090_shdn_event,
+               SND_SOC_DAPM_POST_PMU),
 
        SND_SOC_DAPM_AIF_OUT("AIFOUTL", "HiFi Capture", 0,
                SND_SOC_NOPM, 0, 0),
@@ -1321,12 +1162,10 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
        SND_SOC_DAPM_AIF_IN("AIFINL", "HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
        SND_SOC_DAPM_AIF_IN("AIFINR", "HiFi Playback", 1, SND_SOC_NOPM, 0, 0),
 
-       SND_SOC_DAPM_DAC_E("DACL", NULL, M98090_REG_OUTPUT_ENABLE,
-               M98090_DALEN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-       SND_SOC_DAPM_DAC_E("DACR", NULL, M98090_REG_OUTPUT_ENABLE,
-               M98090_DAREN_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+       SND_SOC_DAPM_DAC("DACL", NULL, M98090_REG_OUTPUT_ENABLE,
+               M98090_DALEN_SHIFT, 0),
+       SND_SOC_DAPM_DAC("DACR", NULL, M98090_REG_OUTPUT_ENABLE,
+               M98090_DAREN_SHIFT, 0),
 
        SND_SOC_DAPM_MIXER("Left Headphone Mixer", SND_SOC_NOPM, 0, 0,
                &max98090_left_hp_mixer_controls[0],
@@ -1361,26 +1200,20 @@ static const struct snd_soc_dapm_widget max98090_dapm_widgets[] = {
        SND_SOC_DAPM_MUX("MIXHPRSEL Mux", SND_SOC_NOPM, 0, 0,
                &max98090_mixhprsel_mux),
 
-       SND_SOC_DAPM_PGA_E("HP Left Out", M98090_REG_OUTPUT_ENABLE,
-               M98090_HPLEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-       SND_SOC_DAPM_PGA_E("HP Right Out", M98090_REG_OUTPUT_ENABLE,
-               M98090_HPREN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-
-       SND_SOC_DAPM_PGA_E("SPK Left Out", M98090_REG_OUTPUT_ENABLE,
-               M98090_SPLEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-       SND_SOC_DAPM_PGA_E("SPK Right Out", M98090_REG_OUTPUT_ENABLE,
-               M98090_SPREN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-
-       SND_SOC_DAPM_PGA_E("RCV Left Out", M98090_REG_OUTPUT_ENABLE,
-               M98090_RCVLEN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
-       SND_SOC_DAPM_PGA_E("RCV Right Out", M98090_REG_OUTPUT_ENABLE,
-               M98090_RCVREN_SHIFT, 0, NULL, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+       SND_SOC_DAPM_PGA("HP Left Out", M98090_REG_OUTPUT_ENABLE,
+               M98090_HPLEN_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("HP Right Out", M98090_REG_OUTPUT_ENABLE,
+               M98090_HPREN_SHIFT, 0, NULL, 0),
+
+       SND_SOC_DAPM_PGA("SPK Left Out", M98090_REG_OUTPUT_ENABLE,
+               M98090_SPLEN_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("SPK Right Out", M98090_REG_OUTPUT_ENABLE,
+               M98090_SPREN_SHIFT, 0, NULL, 0),
+
+       SND_SOC_DAPM_PGA("RCV Left Out", M98090_REG_OUTPUT_ENABLE,
+               M98090_RCVLEN_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("RCV Right Out", M98090_REG_OUTPUT_ENABLE,
+               M98090_RCVREN_SHIFT, 0, NULL, 0),
 
        SND_SOC_DAPM_OUTPUT("HPL"),
        SND_SOC_DAPM_OUTPUT("HPR"),
@@ -1395,11 +1228,9 @@ static const struct snd_soc_dapm_widget max98091_dapm_widgets[] = {
        SND_SOC_DAPM_INPUT("DMIC4"),
 
        SND_SOC_DAPM_SUPPLY("DMIC3_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
-               M98090_DIGMIC3_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+                M98090_DIGMIC3_SHIFT, 0, NULL, 0),
        SND_SOC_DAPM_SUPPLY("DMIC4_ENA", M98090_REG_DIGITAL_MIC_ENABLE,
-               M98090_DIGMIC4_SHIFT, 0, max98090_dapm_event,
-               SND_SOC_DAPM_PRE_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+                M98090_DIGMIC4_SHIFT, 0, NULL, 0),
 };
 
 static const struct snd_soc_dapm_route max98090_dapm_routes[] = {
@@ -1670,11 +1501,6 @@ static void max98090_configure_bclk(struct snd_soc_component *component)
                return;
        }
 
-       /*
-        * Master mode: no need to save and restore SHDN for the following
-        * sensitive registers.
-        */
-
        /* Check for supported PCLK to LRCLK ratios */
        for (i = 0; i < ARRAY_SIZE(pclk_rates); i++) {
                if ((pclk_rates[i] == max98090->sysclk) &&
@@ -1761,14 +1587,12 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
                switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
                case SND_SOC_DAIFMT_CBS_CFS:
                        /* Set to slave mode PLL - MAS mode off */
-                       max98090_shdn_save(max98090);
                        snd_soc_component_write(component,
                                M98090_REG_CLOCK_RATIO_NI_MSB, 0x00);
                        snd_soc_component_write(component,
                                M98090_REG_CLOCK_RATIO_NI_LSB, 0x00);
                        snd_soc_component_update_bits(component, M98090_REG_CLOCK_MODE,
                                M98090_USE_M1_MASK, 0);
-                       max98090_shdn_restore(max98090);
                        max98090->master = false;
                        break;
                case SND_SOC_DAIFMT_CBM_CFM:
@@ -1794,9 +1618,7 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
                        dev_err(component->dev, "DAI clock mode unsupported");
                        return -EINVAL;
                }
-               max98090_shdn_save(max98090);
                snd_soc_component_write(component, M98090_REG_MASTER_MODE, regval);
-               max98090_shdn_restore(max98090);
 
                regval = 0;
                switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -1841,10 +1663,8 @@ static int max98090_dai_set_fmt(struct snd_soc_dai *codec_dai,
                if (max98090->tdm_slots > 1)
                        regval ^= M98090_BCI_MASK;
 
-               max98090_shdn_save(max98090);
                snd_soc_component_write(component,
                        M98090_REG_INTERFACE_FORMAT, regval);
-               max98090_shdn_restore(max98090);
        }
 
        return 0;
@@ -1856,7 +1676,6 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai,
        struct snd_soc_component *component = codec_dai->component;
        struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
        struct max98090_cdata *cdata;
-
        cdata = &max98090->dai[0];
 
        if (slots < 0 || slots > 4)
@@ -1866,7 +1685,6 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai,
        max98090->tdm_width = slot_width;
 
        if (max98090->tdm_slots > 1) {
-               max98090_shdn_save(max98090);
                /* SLOTL SLOTR SLOTDLY */
                snd_soc_component_write(component, M98090_REG_TDM_FORMAT,
                        0 << M98090_TDM_SLOTL_SHIFT |
@@ -1877,7 +1695,6 @@ static int max98090_set_tdm_slot(struct snd_soc_dai *codec_dai,
                snd_soc_component_update_bits(component, M98090_REG_TDM_CONTROL,
                        M98090_TDM_MASK,
                        M98090_TDM_MASK);
-               max98090_shdn_restore(max98090);
        }
 
        /*
@@ -2077,7 +1894,6 @@ static int max98090_configure_dmic(struct max98090_priv *max98090,
        dmic_freq = dmic_table[pclk_index].settings[micclk_index].freq;
        dmic_comp = dmic_table[pclk_index].settings[micclk_index].comp[i];
 
-       max98090_shdn_save(max98090);
        regmap_update_bits(max98090->regmap, M98090_REG_DIGITAL_MIC_ENABLE,
                           M98090_MICCLK_MASK,
                           micclk_index << M98090_MICCLK_SHIFT);
@@ -2086,7 +1902,6 @@ static int max98090_configure_dmic(struct max98090_priv *max98090,
                           M98090_DMIC_COMP_MASK | M98090_DMIC_FREQ_MASK,
                           dmic_comp << M98090_DMIC_COMP_SHIFT |
                           dmic_freq << M98090_DMIC_FREQ_SHIFT);
-       max98090_shdn_restore(max98090);
 
        return 0;
 }
@@ -2123,10 +1938,8 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
 
        switch (params_width(params)) {
        case 16:
-               max98090_shdn_save(max98090);
                snd_soc_component_update_bits(component, M98090_REG_INTERFACE_FORMAT,
                        M98090_WS_MASK, 0);
-               max98090_shdn_restore(max98090);
                break;
        default:
                return -EINVAL;
@@ -2137,7 +1950,6 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
 
        cdata->rate = max98090->lrclk;
 
-       max98090_shdn_save(max98090);
        /* Update filter mode */
        if (max98090->lrclk < 24000)
                snd_soc_component_update_bits(component, M98090_REG_FILTER_CONFIG,
@@ -2153,7 +1965,6 @@ static int max98090_dai_hw_params(struct snd_pcm_substream *substream,
        else
                snd_soc_component_update_bits(component, M98090_REG_FILTER_CONFIG,
                        M98090_DHF_MASK, M98090_DHF_MASK);
-       max98090_shdn_restore(max98090);
 
        max98090_configure_dmic(max98090, max98090->dmic_freq, max98090->pclk,
                                max98090->lrclk);
@@ -2184,7 +1995,6 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
         *               0x02 (when master clk is 20MHz to 40MHz)..
         *               0x03 (when master clk is 40MHz to 60MHz)..
         */
-       max98090_shdn_save(max98090);
        if ((freq >= 10000000) && (freq <= 20000000)) {
                snd_soc_component_write(component, M98090_REG_SYSTEM_CLOCK,
                        M98090_PSCLK_DIV1);
@@ -2199,10 +2009,8 @@ static int max98090_dai_set_sysclk(struct snd_soc_dai *dai,
                max98090->pclk = freq >> 2;
        } else {
                dev_err(component->dev, "Invalid master clock frequency\n");
-               max98090_shdn_restore(max98090);
                return -EINVAL;
        }
-       max98090_shdn_restore(max98090);
 
        max98090->sysclk = freq;
 
@@ -2314,12 +2122,10 @@ static void max98090_pll_work(struct max98090_priv *max98090)
         */
 
        /* Toggle shutdown OFF then ON */
-       mutex_lock(&component->card->dapm_mutex);
        snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
                            M98090_SHDNN_MASK, 0);
        snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
                            M98090_SHDNN_MASK, M98090_SHDNN_MASK);
-       mutex_unlock(&component->card->dapm_mutex);
 
        for (i = 0; i < 10; ++i) {
                /* Give PLL time to lock */
@@ -2642,12 +2448,7 @@ static int max98090_probe(struct snd_soc_component *component)
         */
        snd_soc_component_read32(component, M98090_REG_DEVICE_STATUS);
 
-       /*
-        * SHDN should be 0 at the point, no need to save/restore for the
-        * following registers.
-        *
-        * High Performance is default
-        */
+       /* High Performance is default */
        snd_soc_component_update_bits(component, M98090_REG_DAC_CONTROL,
                M98090_DACHP_MASK,
                1 << M98090_DACHP_SHIFT);
@@ -2658,12 +2459,7 @@ static int max98090_probe(struct snd_soc_component *component)
                M98090_ADCHP_MASK,
                1 << M98090_ADCHP_SHIFT);
 
-       /*
-        * SHDN should be 0 at the point, no need to save/restore for the
-        * following registers.
-        *
-        * Turn on VCM bandgap reference
-        */
+       /* Turn on VCM bandgap reference */
        snd_soc_component_write(component, M98090_REG_BIAS_CONTROL,
                M98090_VCM_MODE_MASK);
 
@@ -2695,9 +2491,25 @@ static void max98090_remove(struct snd_soc_component *component)
        max98090->component = NULL;
 }
 
+static void max98090_seq_notifier(struct snd_soc_component *component,
+       enum snd_soc_dapm_type event, int subseq)
+{
+       struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
+
+       if (max98090->shdn_pending) {
+               snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
+                               M98090_SHDNN_MASK, 0);
+               msleep(40);
+               snd_soc_component_update_bits(component, M98090_REG_DEVICE_SHUTDOWN,
+                               M98090_SHDNN_MASK, M98090_SHDNN_MASK);
+               max98090->shdn_pending = false;
+       }
+}
+
 static const struct snd_soc_component_driver soc_component_dev_max98090 = {
        .probe                  = max98090_probe,
        .remove                 = max98090_remove,
+       .seq_notifier           = max98090_seq_notifier,
        .set_bias_level         = max98090_set_bias_level,
        .idle_bias_on           = 1,
        .use_pmdown_time        = 1,
index 0a31708..a197114 100644 (file)
@@ -1539,8 +1539,7 @@ struct max98090_priv {
        unsigned int pa2en;
        unsigned int sidetone;
        bool master;
-       int saved_count;
-       int saved_shdn;
+       bool shdn_pending;
 };
 
 int max98090_mic_detect(struct snd_soc_component *component,
index 8c3ea73..9d436b0 100644 (file)
@@ -1020,12 +1020,24 @@ static int fsl_sai_probe(struct platform_device *pdev)
        ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
                        &fsl_sai_dai, 1);
        if (ret)
-               return ret;
+               goto err_pm_disable;
 
-       if (sai->soc_data->use_imx_pcm)
-               return imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
-       else
-               return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+       if (sai->soc_data->use_imx_pcm) {
+               ret = imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE);
+               if (ret)
+                       goto err_pm_disable;
+       } else {
+               ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
+               if (ret)
+                       goto err_pm_disable;
+       }
+
+       return ret;
+
+err_pm_disable:
+       pm_runtime_disable(&pdev->dev);
+
+       return ret;
 }
 
 static int fsl_sai_remove(struct platform_device *pdev)
index bc20ad9..9b13056 100644 (file)
@@ -3441,8 +3441,17 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
 
-static int __snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol, int locked)
+/**
+ * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
+ * @kcontrol: mixer control
+ * @ucontrol: control element information
+ *
+ * Callback to set the value of a dapm enumerated double mixer control.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
        struct snd_soc_card *card = dapm->card;
@@ -3465,9 +3474,7 @@ static int __snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
                mask |= e->mask << e->shift_r;
        }
 
-       if (!locked)
-               mutex_lock_nested(&card->dapm_mutex,
-                                 SND_SOC_DAPM_CLASS_RUNTIME);
+       mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 
        change = dapm_kcontrol_set_value(kcontrol, val);
 
@@ -3489,50 +3496,15 @@ static int __snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
                card->update = NULL;
        }
 
-       if (!locked)
-               mutex_unlock(&card->dapm_mutex);
+       mutex_unlock(&card->dapm_mutex);
 
        if (ret > 0)
                soc_dpcm_runtime_update(card);
 
        return change;
 }
-
-/**
- * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
- * @kcontrol: mixer control
- * @ucontrol: control element information
- *
- * Callback to set the value of a dapm enumerated double mixer control.
- *
- * Returns 0 for success.
- */
-int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       return __snd_soc_dapm_put_enum_double(kcontrol, ucontrol, 0);
-}
 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
 
-/**
- * snd_soc_dapm_put_enum_double_locked - dapm enumerated double mixer set
- * callback
- * @kcontrol: mixer control
- * @ucontrol: control element information
- *
- * Callback to set the value of a dapm enumerated double mixer control.
- * Must acquire dapm_mutex before calling the function.
- *
- * Returns 0 for success.
- */
-int snd_soc_dapm_put_enum_double_locked(struct snd_kcontrol *kcontrol,
-       struct snd_ctl_elem_value *ucontrol)
-{
-       dapm_assert_locked(snd_soc_dapm_kcontrol_dapm(kcontrol));
-       return __snd_soc_dapm_put_enum_double(kcontrol, ucontrol, 1);
-}
-EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double_locked);
-
 /**
  * snd_soc_dapm_info_pin_switch - Info for a pin switch
  *
@@ -3916,9 +3888,6 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w,
        runtime->rate = params_rate(params);
 
 out:
-       if (ret < 0)
-               kfree(runtime);
-
        kfree(params);
        return ret;
 }
index 9106ab8..ff45075 100644 (file)
@@ -174,8 +174,10 @@ void hda_codec_i915_display_power(struct snd_sof_dev *sdev, bool enable)
 {
        struct hdac_bus *bus = sof_to_bus(sdev);
 
-       dev_dbg(bus->dev, "Turning i915 HDAC power %d\n", enable);
-       snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, enable);
+       if (HDA_IDISP_CODEC(bus->codec_mask)) {
+               dev_dbg(bus->dev, "Turning i915 HDAC power %d\n", enable);
+               snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, enable);
+       }
 }
 EXPORT_SYMBOL_NS(hda_codec_i915_display_power, SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
 
@@ -189,7 +191,8 @@ int hda_codec_i915_init(struct snd_sof_dev *sdev)
        if (ret < 0)
                return ret;
 
-       hda_codec_i915_display_power(sdev, true);
+       /* codec_mask not yet known, power up for probe */
+       snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
 
        return 0;
 }
@@ -200,7 +203,8 @@ int hda_codec_i915_exit(struct snd_sof_dev *sdev)
        struct hdac_bus *bus = sof_to_bus(sdev);
        int ret;
 
-       hda_codec_i915_display_power(sdev, false);
+       /* power down unconditionally */
+       snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
 
        ret = snd_hdac_i915_exit(bus);
 
index 4a4d318..0848b79 100644 (file)
@@ -428,6 +428,9 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
                return ret;
        }
 
+       /* display codec can powered off after link reset */
+       hda_codec_i915_display_power(sdev, false);
+
        return 0;
 }
 
@@ -439,6 +442,9 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume)
 #endif
        int ret;
 
+       /* display codec must be powered before link reset */
+       hda_codec_i915_display_power(sdev, true);
+
        /*
         * clear TCSEL to clear playback on some HD Audio
         * codecs. PCI TCSEL is defined in the Intel manuals.
@@ -482,6 +488,8 @@ int hda_dsp_resume(struct snd_sof_dev *sdev)
        struct pci_dev *pci = to_pci_dev(sdev->dev);
 
        if (sdev->s0_suspend) {
+               hda_codec_i915_display_power(sdev, true);
+
                /* restore L1SEN bit */
                if (hda->l1_support_changed)
                        snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
@@ -531,6 +539,9 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev)
        int ret;
 
        if (sdev->s0_suspend) {
+               /* we can't keep a wakeref to display driver at suspend */
+               hda_codec_i915_display_power(sdev, false);
+
                /* enable L1SEN to make sure the system can enter S0Ix */
                hda->l1_support_changed =
                        snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR,
index 65b86dd..25946a1 100644 (file)
@@ -286,6 +286,13 @@ static int hda_init(struct snd_sof_dev *sdev)
        /* HDA base */
        sdev->bar[HDA_DSP_HDA_BAR] = bus->remap_addr;
 
+       /* init i915 and HDMI codecs */
+       ret = hda_codec_i915_init(sdev);
+       if (ret < 0) {
+               dev_err(sdev->dev, "error: init i915 and HDMI codec failed\n");
+               return ret;
+       }
+
        /* get controller capabilities */
        ret = hda_dsp_ctrl_get_caps(sdev);
        if (ret < 0)
@@ -353,15 +360,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
        if (bus->ppcap)
                dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n");
 
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
-       /* init i915 and HDMI codecs */
-       ret = hda_codec_i915_init(sdev);
-       if (ret < 0) {
-               dev_err(sdev->dev, "error: init i915 and HDMI codec failed\n");
-               return ret;
-       }
-#endif
-
        /* Init HDA controller after i915 init */
        ret = hda_dsp_ctrl_init_chip(sdev, true);
        if (ret < 0) {
@@ -381,7 +379,7 @@ static int hda_init_caps(struct snd_sof_dev *sdev)
        hda_codec_probe_bus(sdev, hda_codec_use_common_hdmi);
 
        if (!HDA_IDISP_CODEC(bus->codec_mask))
-               hda_codec_i915_display_power(sdev, false);
+               hda_codec_i915_exit(sdev);
 
        /*
         * we are done probing so decrement link counts
@@ -611,6 +609,7 @@ free_streams:
        iounmap(sdev->bar[HDA_DSP_BAR]);
 hdac_bus_unmap:
        iounmap(bus->remap_addr);
+       hda_codec_i915_exit(sdev);
 err:
        return ret;
 }
index 55798bc..686561d 100644 (file)
@@ -80,6 +80,7 @@
 
 #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK         GENMASK(15, 12)
 #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK         GENMASK(11, 8)
+#define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK  GENMASK(3, 2)
 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK  GENMASK(5, 4)
 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK  GENMASK(8, 6)
 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK  GENMASK(12, 9)
@@ -241,7 +242,7 @@ static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                return -EINVAL;
        }
        regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL,
-                          BIT(SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT),
+                          SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK,
                           value << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT);
 
        return 0;
index f1d74a2..22f2352 100644 (file)
@@ -1045,9 +1045,9 @@ union bpf_attr {
  *             supports redirection to the egress interface, and accepts no
  *             flag at all.
  *
- *             The same effect can be attained with the more generic
- *             **bpf_redirect_map**\ (), which requires specific maps to be
- *             used but offers better performance.
+ *             The same effect can also be attained with the more generic
+ *             **bpf_redirect_map**\ (), which uses a BPF map to store the
+ *             redirect target instead of providing it directly to the helper.
  *     Return
  *             For XDP, the helper returns **XDP_REDIRECT** on success or
  *             **XDP_ABORTED** on error. For other program types, the values
@@ -1611,13 +1611,11 @@ union bpf_attr {
  *             the caller. Any higher bits in the *flags* argument must be
  *             unset.
  *
- *             When used to redirect packets to net devices, this helper
- *             provides a high performance increase over **bpf_redirect**\ ().
- *             This is due to various implementation details of the underlying
- *             mechanisms, one of which is the fact that **bpf_redirect_map**\
- *             () tries to send packet as a "bulk" to the device.
+ *             See also bpf_redirect(), which only supports redirecting to an
+ *             ifindex, but doesn't require a map to do so.
  *     Return
- *             **XDP_REDIRECT** on success, or **XDP_ABORTED** on error.
+ *             **XDP_REDIRECT** on success, or the value of the two lower bits
+ *             of the **flags* argument on error.
  *
  * int bpf_sk_redirect_map(struct sk_buff *skb, struct bpf_map *map, u32 key, u64 flags)
  *     Description
index 514b1a5..7469c7d 100644 (file)
@@ -24,6 +24,7 @@
 #include <endian.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <ctype.h>
 #include <asm/unistd.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
@@ -1283,7 +1284,7 @@ static size_t bpf_map_mmap_sz(const struct bpf_map *map)
 static char *internal_map_name(struct bpf_object *obj,
                               enum libbpf_map_type type)
 {
-       char map_name[BPF_OBJ_NAME_LEN];
+       char map_name[BPF_OBJ_NAME_LEN], *p;
        const char *sfx = libbpf_type_to_btf_name[type];
        int sfx_len = max((size_t)7, strlen(sfx));
        int pfx_len = min((size_t)BPF_OBJ_NAME_LEN - sfx_len - 1,
@@ -1292,6 +1293,11 @@ static char *internal_map_name(struct bpf_object *obj,
        snprintf(map_name, sizeof(map_name), "%.*s%.*s", pfx_len, obj->name,
                 sfx_len, libbpf_type_to_btf_name[type]);
 
+       /* sanitise map name to characters allowed by kernel */
+       for (p = map_name; *p && p < map_name + sizeof(map_name); p++)
+               if (!isalnum(*p) && *p != '_' && *p != '.')
+                       *p = '_';
+
        return strdup(map_name);
 }
 
index 63430e2..6ec5039 100644 (file)
@@ -77,6 +77,12 @@ ifneq ($(SKIP_TARGETS),)
        override TARGETS := $(TMP)
 endif
 
+# User can set FORCE_TARGETS to 1 to require all targets to be successfully
+# built; make will fail if any of the targets cannot be built. If
+# FORCE_TARGETS is not set (the default), make will succeed if at least one
+# of the targets gets built.
+FORCE_TARGETS ?=
+
 # Clear LDFLAGS and MAKEFLAGS if called from main
 # Makefile to avoid test build failures when test
 # Makefile doesn't have explicit build rules.
@@ -151,7 +157,8 @@ all: khdr
        for TARGET in $(TARGETS); do                            \
                BUILD_TARGET=$$BUILD/$$TARGET;                  \
                mkdir $$BUILD_TARGET  -p;                       \
-               $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET;      \
+               $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET       \
+                               $(if $(FORCE_TARGETS),|| exit); \
                ret=$$((ret * $$?));                            \
        done; exit $$ret;
 
@@ -205,7 +212,8 @@ ifdef INSTALL_PATH
        @ret=1; \
        for TARGET in $(TARGETS); do \
                BUILD_TARGET=$$BUILD/$$TARGET;  \
-               $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \
+               $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install \
+                               $(if $(FORCE_TARGETS),|| exit); \
                ret=$$((ret * $$?));            \
        done; exit $$ret;
 
index 098bcae..0800036 100644 (file)
@@ -506,8 +506,10 @@ static void test_syncookie(int type, sa_family_t family)
                .pass_on_failure = 0,
        };
 
-       if (type != SOCK_STREAM)
+       if (type != SOCK_STREAM) {
+               test__skip();
                return;
+       }
 
        /*
         * +1 for TCP-SYN and
@@ -822,8 +824,10 @@ void test_select_reuseport(void)
                goto out;
 
        saved_tcp_fo = read_int_sysctl(TCP_FO_SYSCTL);
+       if (saved_tcp_fo < 0)
+               goto out;
        saved_tcp_syncookie = read_int_sysctl(TCP_SYNCOOKIE_SYSCTL);
-       if (saved_tcp_syncookie < 0 || saved_tcp_syncookie < 0)
+       if (saved_tcp_syncookie < 0)
                goto out;
 
        if (enable_fastopen())
index 07f5b46..aa43e0b 100644 (file)
@@ -3,6 +3,11 @@
 
 #include "test_progs.h"
 
+#define TCP_REPAIR             19      /* TCP sock is under repair right now */
+
+#define TCP_REPAIR_ON          1
+#define TCP_REPAIR_OFF_NO_WP   -1      /* Turn off without window probes */
+
 static int connected_socket_v4(void)
 {
        struct sockaddr_in addr = {
index 64cfcc7..f2ee1e8 100644 (file)
@@ -1,6 +1,7 @@
 #!/bin/sh
 # SPDX-License-Identifier: GPL-2.0
 # description: ftrace - function pid filters
+# flags: instance
 
 # Make sure that function pid matching filter works.
 # Also test it on an instance directory
@@ -96,13 +97,6 @@ do_test() {
 }
 
 do_test
-
-mkdir instances/foo
-cd instances/foo
-do_test
-cd ../../
-rmdir instances/foo
-
 do_reset
 
 exit 0
index 3099630..2320782 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 INCLUDES := -I../include -I../../
 CFLAGS := $(CFLAGS) -g -O2 -Wall -D_GNU_SOURCE -pthread $(INCLUDES)
-LDFLAGS := $(LDFLAGS) -pthread -lrt
+LDLIBS := -lpthread -lrt
 
 HEADERS := \
        ../include/futextest.h \
index 1c8a196..3ed0134 100644 (file)
@@ -83,17 +83,20 @@ else
        $(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS))
 endif
 
+define INSTALL_SINGLE_RULE
+       $(if $(INSTALL_LIST),@mkdir -p $(INSTALL_PATH))
+       $(if $(INSTALL_LIST),@echo rsync -a $(INSTALL_LIST) $(INSTALL_PATH)/)
+       $(if $(INSTALL_LIST),@rsync -a $(INSTALL_LIST) $(INSTALL_PATH)/)
+endef
+
 define INSTALL_RULE
-       @if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then                                        \
-               mkdir -p ${INSTALL_PATH};                                                                               \
-               echo "rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/";    \
-               rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/;           \
-       fi
-       @if [ "X$(TEST_GEN_PROGS)$(TEST_CUSTOM_PROGS)$(TEST_GEN_PROGS_EXTENDED)$(TEST_GEN_FILES)" != "X" ]; then                                        \
-               mkdir -p ${INSTALL_PATH};                                                                               \
-               echo "rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/";   \
-               rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/;          \
-       fi
+       $(eval INSTALL_LIST = $(TEST_PROGS)) $(INSTALL_SINGLE_RULE)
+       $(eval INSTALL_LIST = $(TEST_PROGS_EXTENDED)) $(INSTALL_SINGLE_RULE)
+       $(eval INSTALL_LIST = $(TEST_FILES)) $(INSTALL_SINGLE_RULE)
+       $(eval INSTALL_LIST = $(TEST_GEN_PROGS)) $(INSTALL_SINGLE_RULE)
+       $(eval INSTALL_LIST = $(TEST_CUSTOM_PROGS)) $(INSTALL_SINGLE_RULE)
+       $(eval INSTALL_LIST = $(TEST_GEN_PROGS_EXTENDED)) $(INSTALL_SINGLE_RULE)
+       $(eval INSTALL_LIST = $(TEST_GEN_FILES)) $(INSTALL_SINGLE_RULE)
 endef
 
 install: all
index b569419..287ae91 100644 (file)
@@ -27,5 +27,5 @@ KSFT_KHDR_INSTALL := 1
 include ../lib.mk
 
 $(OUTPUT)/reuseport_bpf_numa: LDLIBS += -lnuma
-$(OUTPUT)/tcp_mmap: LDFLAGS += -lpthread
-$(OUTPUT)/tcp_inq: LDFLAGS += -lpthread
+$(OUTPUT)/tcp_mmap: LDLIBS += -lpthread
+$(OUTPUT)/tcp_inq: LDLIBS += -lpthread
index 6dd4031..60273f1 100755 (executable)
@@ -910,6 +910,12 @@ ipv6_rt_replace_mpath()
        check_route6 "2001:db8:104::/64 via 2001:db8:101::3 dev veth1 metric 1024"
        log_test $? 0 "Multipath with single path via multipath attribute"
 
+       # multipath with dev-only
+       add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
+       run_cmd "$IP -6 ro replace 2001:db8:104::/64 dev veth1"
+       check_route6 "2001:db8:104::/64 dev veth1 metric 1024"
+       log_test $? 0 "Multipath with dev-only"
+
        # route replace fails - invalid nexthop 1
        add_initial_route6 "nexthop via 2001:db8:101::2 nexthop via 2001:db8:103::2"
        run_cmd "$IP -6 ro replace 2001:db8:104::/64 nexthop via 2001:db8:111::3 nexthop via 2001:db8:103::3"
index e6fd7a1..0266443 100755 (executable)
@@ -63,22 +63,23 @@ test_span_gre_mac()
 {
        local tundev=$1; shift
        local direction=$1; shift
-       local prot=$1; shift
        local what=$1; shift
 
-       local swp3mac=$(mac_get $swp3)
-       local h3mac=$(mac_get $h3)
+       case "$direction" in
+       ingress) local src_mac=$(mac_get $h1); local dst_mac=$(mac_get $h2)
+               ;;
+       egress) local src_mac=$(mac_get $h2); local dst_mac=$(mac_get $h1)
+               ;;
+       esac
 
        RET=0
 
        mirror_install $swp1 $direction $tundev "matchall $tcflags"
-       tc filter add dev $h3 ingress pref 77 prot $prot \
-               flower ip_proto 0x2f src_mac $swp3mac dst_mac $h3mac \
-               action pass
+       icmp_capture_install h3-${tundev} "src_mac $src_mac dst_mac $dst_mac"
 
-       mirror_test v$h1 192.0.2.1 192.0.2.2 $h3 77 10
+       mirror_test v$h1 192.0.2.1 192.0.2.2 h3-${tundev} 100 10
 
-       tc filter del dev $h3 ingress pref 77
+       icmp_capture_uninstall h3-${tundev}
        mirror_uninstall $swp1 $direction
 
        log_test "$direction $what: envelope MAC ($tcflags)"
@@ -120,14 +121,14 @@ test_ip6gretap()
 
 test_gretap_mac()
 {
-       test_span_gre_mac gt4 ingress ip "mirror to gretap"
-       test_span_gre_mac gt4 egress ip "mirror to gretap"
+       test_span_gre_mac gt4 ingress "mirror to gretap"
+       test_span_gre_mac gt4 egress "mirror to gretap"
 }
 
 test_ip6gretap_mac()
 {
-       test_span_gre_mac gt6 ingress ipv6 "mirror to ip6gretap"
-       test_span_gre_mac gt6 egress ipv6 "mirror to ip6gretap"
+       test_span_gre_mac gt6 ingress "mirror to ip6gretap"
+       test_span_gre_mac gt6 egress "mirror to ip6gretap"
 }
 
 test_all()
index bb10e33..ce6bea9 100755 (executable)
@@ -516,9 +516,9 @@ test_tos()
        RET=0
 
        tc filter add dev v1 egress pref 77 prot ip \
-               flower ip_tos 0x40 action pass
-       vxlan_ping_test $h1 192.0.2.3 "-Q 0x40" v1 egress 77 10
-       vxlan_ping_test $h1 192.0.2.3 "-Q 0x30" v1 egress 77 0
+               flower ip_tos 0x14 action pass
+       vxlan_ping_test $h1 192.0.2.3 "-Q 0x14" v1 egress 77 10
+       vxlan_ping_test $h1 192.0.2.3 "-Q 0x18" v1 egress 77 0
        tc filter del dev v1 egress pref 77 prot ip
 
        log_test "VXLAN: envelope TOS inheritance"
index e9a6557..5074681 100644 (file)
@@ -46,7 +46,7 @@ int sys_renameat2(int olddirfd, const char *oldpath,
 
 int touchat(int dfd, const char *path)
 {
-       int fd = openat(dfd, path, O_CREAT);
+       int fd = openat(dfd, path, O_CREAT, 0700);
        if (fd >= 0)
                close(fd);
        return fd;
index 7a94b1d..bbafad4 100644 (file)
@@ -230,7 +230,7 @@ void test_openat2_opath_tests(void)
                { .name = "[in_root] garbage link to /root",
                  .path = "cheeky/garbageself", .how.resolve = RESOLVE_IN_ROOT,
                  .out.path = "root",           .pass = true },
-               { .name = "[in_root] chainged garbage links to /root",
+               { .name = "[in_root] chained garbage links to /root",
                  .path = "abscheeky/garbageself", .how.resolve = RESOLVE_IN_ROOT,
                  .out.path = "root",           .pass = true },
                { .name = "[in_root] relative path to 'root'",
index de9c856..2d93d65 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 CFLAGS += -O3 -Wl,-no-as-needed -Wall
-LDFLAGS += -lrt -lpthread -lm
+LDLIBS += -lrt -lpthread -lm
 
 TEST_GEN_PROGS = rtctest
 
index e9fb30b..b4fd9a9 100644 (file)
@@ -2,6 +2,6 @@ TEST_GEN_PROGS := timens timerfd timer clock_nanosleep procfs exec
 TEST_GEN_PROGS_EXTENDED := gettime_perf
 
 CFLAGS := -Wall -Werror -pthread
-LDFLAGS := -lrt -ldl
+LDLIBS := -lrt -ldl
 
 include ../lib.mk
index 8155c2e..b630c7b 100755 (executable)
@@ -1,8 +1,17 @@
 #!/bin/bash
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+self.flags = flags
 
-python -m unittest -v tpm2_tests.SmokeTest
-python -m unittest -v tpm2_tests.AsyncTest
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
+
+if [ -f /dev/tpm0 ] ; then
+       python -m unittest -v tpm2_tests.SmokeTest
+       python -m unittest -v tpm2_tests.AsyncTest
+else
+       exit $ksft_skip
+fi
 
 CLEAR_CMD=$(which tpm2_clear)
 if [ -n $CLEAR_CMD ]; then
index a6f5e34..180b469 100755 (executable)
@@ -1,4 +1,11 @@
 #!/bin/bash
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
 
-python -m unittest -v tpm2_tests.SpaceTest
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
+if [ -f /dev/tpmrm0 ] ; then
+       python -m unittest -v tpm2_tests.SpaceTest
+else
+       exit $ksft_skip
+fi
index a692ea8..f337148 100755 (executable)
@@ -112,6 +112,17 @@ echo "NOTE: The above hugetlb tests provide minimal coverage.  Use"
 echo "      https://github.com/libhugetlbfs/libhugetlbfs.git for"
 echo "      hugetlb regression testing."
 
+echo "---------------------------"
+echo "running map_fixed_noreplace"
+echo "---------------------------"
+./map_fixed_noreplace
+if [ $? -ne 0 ]; then
+       echo "[FAIL]"
+       exitcode=1
+else
+       echo "[PASS]"
+fi
+
 echo "-------------------"
 echo "running userfaultfd"
 echo "-------------------"
@@ -186,6 +197,17 @@ else
        echo "[PASS]"
 fi
 
+echo "-------------------------"
+echo "running mlock-random-test"
+echo "-------------------------"
+./mlock-random-test
+if [ $? -ne 0 ]; then
+       echo "[FAIL]"
+       exitcode=1
+else
+       echo "[PASS]"
+fi
+
 echo "--------------------"
 echo "running mlock2-tests"
 echo "--------------------"
@@ -197,6 +219,17 @@ else
        echo "[PASS]"
 fi
 
+echo "-----------------"
+echo "running thuge-gen"
+echo "-----------------"
+./thuge-gen
+if [ $? -ne 0 ]; then
+       echo "[FAIL]"
+       exitcode=1
+else
+       echo "[PASS]"
+fi
+
 if [ $VADDR64 -ne 0 ]; then
 echo "-----------------------------"
 echo "running virtual_address_range"
index f10aa35..28d4776 100644 (file)
@@ -38,19 +38,17 @@ endef
 define file_download =
 $(DISTFILES_PATH)/$(1):
        mkdir -p $(DISTFILES_PATH)
-       flock -x $$@.lock -c '[ -f $$@ ] && exit 0; wget -O $$@.tmp $(MIRROR)$(1) || wget -O $$@.tmp $(2)$(1) || rm -f $$@.tmp'
-       if echo "$(3)  $$@.tmp" | sha256sum -c -; then mv $$@.tmp $$@; else rm -f $$@.tmp; exit 71; fi
+       flock -x $$@.lock -c '[ -f $$@ ] && exit 0; wget -O $$@.tmp $(MIRROR)$(1) || wget -O $$@.tmp $(2)$(1) || rm -f $$@.tmp; [ -f $$@.tmp ] || exit 1; if echo "$(3)  $$@.tmp" | sha256sum -c -; then mv $$@.tmp $$@; else rm -f $$@.tmp; exit 71; fi'
 endef
 
 $(eval $(call tar_download,MUSL,musl,1.1.24,.tar.gz,https://www.musl-libc.org/releases/,1370c9a812b2cf2a7d92802510cca0058cc37e66a7bedd70051f0a34015022a3))
-$(eval $(call tar_download,LIBMNL,libmnl,1.0.4,.tar.bz2,https://www.netfilter.org/projects/libmnl/files/,171f89699f286a5854b72b91d06e8f8e3683064c5901fb09d954a9ab6f551f81))
 $(eval $(call tar_download,IPERF,iperf,3.7,.tar.gz,https://downloads.es.net/pub/iperf/,d846040224317caf2f75c843d309a950a7db23f9b44b94688ccbe557d6d1710c))
 $(eval $(call tar_download,BASH,bash,5.0,.tar.gz,https://ftp.gnu.org/gnu/bash/,b4a80f2ac66170b2913efbfb9f2594f1f76c7b1afd11f799e22035d63077fb4d))
 $(eval $(call tar_download,IPROUTE2,iproute2,5.4.0,.tar.xz,https://www.kernel.org/pub/linux/utils/net/iproute2/,fe97aa60a0d4c5ac830be18937e18dc3400ca713a33a89ad896ff1e3d46086ae))
 $(eval $(call tar_download,IPTABLES,iptables,1.8.4,.tar.bz2,https://www.netfilter.org/projects/iptables/files/,993a3a5490a544c2cbf2ef15cf7e7ed21af1845baf228318d5c36ef8827e157c))
 $(eval $(call tar_download,NMAP,nmap,7.80,.tar.bz2,https://nmap.org/dist/,fcfa5a0e42099e12e4bf7a68ebe6fde05553383a682e816a7ec9256ab4773faa))
 $(eval $(call tar_download,IPUTILS,iputils,s20190709,.tar.gz,https://github.com/iputils/iputils/archive/s20190709.tar.gz/#,a15720dd741d7538dd2645f9f516d193636ae4300ff7dbc8bfca757bf166490a))
-$(eval $(call tar_download,WIREGUARD_TOOLS,wireguard-tools,1.0.20191226,.tar.xz,https://git.zx2c4.com/wireguard-tools/snapshot/,aa8af0fdc9872d369d8c890a84dbc2a2466b55795dccd5b47721b2d97644b04f))
+$(eval $(call tar_download,WIREGUARD_TOOLS,wireguard-tools,1.0.20200206,.tar.xz,https://git.zx2c4.com/wireguard-tools/snapshot/,f5207248c6a3c3e3bfc9ab30b91c1897b00802ed861e1f9faaed873366078c64))
 
 KERNEL_BUILD_PATH := $(BUILD_PATH)/kernel$(if $(findstring yes,$(DEBUG_KERNEL)),-debug)
 rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
@@ -295,21 +293,13 @@ $(IPERF_PATH)/src/iperf3: | $(IPERF_PATH)/.installed $(USERSPACE_DEPS)
        $(MAKE) -C $(IPERF_PATH)
        $(STRIP) -s $@
 
-$(LIBMNL_PATH)/.installed: $(LIBMNL_TAR)
-       flock -s $<.lock tar -C $(BUILD_PATH) -xf $<
-       touch $@
-
-$(LIBMNL_PATH)/src/.libs/libmnl.a: | $(LIBMNL_PATH)/.installed $(USERSPACE_DEPS)
-       cd $(LIBMNL_PATH) && ./configure --prefix=/ $(CROSS_COMPILE_FLAG) --enable-static --disable-shared
-       $(MAKE) -C $(LIBMNL_PATH)
-       sed -i 's:prefix=.*:prefix=$(LIBMNL_PATH):' $(LIBMNL_PATH)/libmnl.pc
-
 $(WIREGUARD_TOOLS_PATH)/.installed: $(WIREGUARD_TOOLS_TAR)
+       mkdir -p $(BUILD_PATH)
        flock -s $<.lock tar -C $(BUILD_PATH) -xf $<
        touch $@
 
-$(WIREGUARD_TOOLS_PATH)/src/wg: | $(WIREGUARD_TOOLS_PATH)/.installed $(LIBMNL_PATH)/src/.libs/libmnl.a $(USERSPACE_DEPS)
-       LDFLAGS="$(LDFLAGS) -L$(LIBMNL_PATH)/src/.libs" $(MAKE) -C $(WIREGUARD_TOOLS_PATH)/src LIBMNL_CFLAGS="-I$(LIBMNL_PATH)/include" LIBMNL_LDLIBS="-lmnl" wg
+$(WIREGUARD_TOOLS_PATH)/src/wg: | $(WIREGUARD_TOOLS_PATH)/.installed $(USERSPACE_DEPS)
+       $(MAKE) -C $(WIREGUARD_TOOLS_PATH)/src wg
        $(STRIP) -s $@
 
 $(BUILD_PATH)/init: init.c | $(USERSPACE_DEPS)
@@ -340,17 +330,17 @@ $(BASH_PATH)/bash: | $(BASH_PATH)/.installed $(USERSPACE_DEPS)
 $(IPROUTE2_PATH)/.installed: $(IPROUTE2_TAR)
        mkdir -p $(BUILD_PATH)
        flock -s $<.lock tar -C $(BUILD_PATH) -xf $<
-       printf 'CC:=$(CC)\nPKG_CONFIG:=pkg-config\nTC_CONFIG_XT:=n\nTC_CONFIG_ATM:=n\nTC_CONFIG_IPSET:=n\nIP_CONFIG_SETNS:=y\nHAVE_ELF:=n\nHAVE_MNL:=y\nHAVE_BERKELEY_DB:=n\nHAVE_LATEX:=n\nHAVE_PDFLATEX:=n\nCFLAGS+=-DHAVE_SETNS -DHAVE_LIBMNL -I$(LIBMNL_PATH)/include\nLDLIBS+=-lmnl' > $(IPROUTE2_PATH)/config.mk
+       printf 'CC:=$(CC)\nPKG_CONFIG:=pkg-config\nTC_CONFIG_XT:=n\nTC_CONFIG_ATM:=n\nTC_CONFIG_IPSET:=n\nIP_CONFIG_SETNS:=y\nHAVE_ELF:=n\nHAVE_MNL:=n\nHAVE_BERKELEY_DB:=n\nHAVE_LATEX:=n\nHAVE_PDFLATEX:=n\nCFLAGS+=-DHAVE_SETNS\n' > $(IPROUTE2_PATH)/config.mk
        printf 'lib: snapshot\n\t$$(MAKE) -C lib\nip/ip: lib\n\t$$(MAKE) -C ip ip\nmisc/ss: lib\n\t$$(MAKE) -C misc ss\n' >> $(IPROUTE2_PATH)/Makefile
        touch $@
 
-$(IPROUTE2_PATH)/ip/ip: | $(IPROUTE2_PATH)/.installed $(LIBMNL_PATH)/src/.libs/libmnl.a $(USERSPACE_DEPS)
-       LDFLAGS="$(LDFLAGS) -L$(LIBMNL_PATH)/src/.libs" PKG_CONFIG_LIBDIR="$(LIBMNL_PATH)" $(MAKE) -C $(IPROUTE2_PATH) PREFIX=/ ip/ip
-       $(STRIP) -s $(IPROUTE2_PATH)/ip/ip
+$(IPROUTE2_PATH)/ip/ip: | $(IPROUTE2_PATH)/.installed $(USERSPACE_DEPS)
+       $(MAKE) -C $(IPROUTE2_PATH) PREFIX=/ ip/ip
+       $(STRIP) -s $@
 
-$(IPROUTE2_PATH)/misc/ss: | $(IPROUTE2_PATH)/.installed $(LIBMNL_PATH)/src/.libs/libmnl.a $(USERSPACE_DEPS)
-       LDFLAGS="$(LDFLAGS) -L$(LIBMNL_PATH)/src/.libs" PKG_CONFIG_LIBDIR="$(LIBMNL_PATH)" $(MAKE) -C $(IPROUTE2_PATH) PREFIX=/ misc/ss
-       $(STRIP) -s $(IPROUTE2_PATH)/misc/ss
+$(IPROUTE2_PATH)/misc/ss: | $(IPROUTE2_PATH)/.installed $(USERSPACE_DEPS)
+       $(MAKE) -C $(IPROUTE2_PATH) PREFIX=/ misc/ss
+       $(STRIP) -s $@
 
 $(IPTABLES_PATH)/.installed: $(IPTABLES_TAR)
        mkdir -p $(BUILD_PATH)
@@ -358,8 +348,8 @@ $(IPTABLES_PATH)/.installed: $(IPTABLES_TAR)
        sed -i -e "/nfnetlink=[01]/s:=[01]:=0:" -e "/nfconntrack=[01]/s:=[01]:=0:" $(IPTABLES_PATH)/configure
        touch $@
 
-$(IPTABLES_PATH)/iptables/xtables-legacy-multi: | $(IPTABLES_PATH)/.installed $(LIBMNL_PATH)/src/.libs/libmnl.a $(USERSPACE_DEPS)
-       cd $(IPTABLES_PATH) && PKG_CONFIG_LIBDIR="$(LIBMNL_PATH)" ./configure --prefix=/ $(CROSS_COMPILE_FLAG) --enable-static --disable-shared --disable-nftables --disable-bpf-compiler --disable-nfsynproxy --disable-libipq --with-kernel=$(BUILD_PATH)/include
+$(IPTABLES_PATH)/iptables/xtables-legacy-multi: | $(IPTABLES_PATH)/.installed $(USERSPACE_DEPS)
+       cd $(IPTABLES_PATH) && ./configure --prefix=/ $(CROSS_COMPILE_FLAG) --enable-static --disable-shared --disable-nftables --disable-bpf-compiler --disable-nfsynproxy --disable-libipq --disable-connlabel --with-kernel=$(BUILD_PATH)/include
        $(MAKE) -C $(IPTABLES_PATH)
        $(STRIP) -s $@