Merge branch 'ras/urgent' into ras/core
authorThomas Gleixner <tglx@linutronix.de>
Sat, 19 May 2018 13:20:49 +0000 (15:20 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Sat, 19 May 2018 13:20:49 +0000 (15:20 +0200)
Pick up urgent fix as pending patch depends on it.

407 files changed:
Documentation/ABI/testing/sysfs-class-cxl
Documentation/admin-guide/pm/intel_pstate.rst
Documentation/admin-guide/pm/sleep-states.rst
Documentation/device-mapper/thin-provisioning.txt
Documentation/devicetree/bindings/ata/ahci-platform.txt
Documentation/devicetree/bindings/display/panel/panel-common.txt
Documentation/devicetree/bindings/dma/renesas,rcar-dmac.txt
Documentation/devicetree/bindings/net/can/rcar_canfd.txt
Documentation/devicetree/bindings/net/renesas,ravb.txt
Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/devicetree/overlay-notes.txt
Documentation/virtual/kvm/cpuid.txt
MAINTAINERS
Makefile
arch/Kconfig
arch/arm/boot/dts/imx35.dtsi
arch/arm/boot/dts/imx53.dtsi
arch/arm/include/asm/kvm_mmu.h
arch/arm64/include/asm/cputype.h
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c
arch/arm64/mm/init.c
arch/powerpc/include/asm/ftrace.h
arch/powerpc/include/asm/paca.h
arch/powerpc/include/asm/topology.h
arch/powerpc/platforms/powernv/opal-nvram.c
arch/s390/configs/debug_defconfig
arch/s390/configs/performance_defconfig
arch/s390/crypto/crc32be-vx.S
arch/s390/crypto/crc32le-vx.S
arch/s390/include/asm/nospec-insn.h [new file with mode: 0644]
arch/s390/include/asm/purgatory.h
arch/s390/kernel/Makefile
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/base.S
arch/s390/kernel/entry.S
arch/s390/kernel/irq.c
arch/s390/kernel/mcount.S
arch/s390/kernel/nospec-branch.c
arch/s390/kernel/nospec-sysfs.c [new file with mode: 0644]
arch/s390/kernel/perf_cpum_sf.c
arch/s390/kernel/reipl.S
arch/s390/kernel/swsusp.S
arch/s390/lib/mem.S
arch/s390/net/bpf_jit.S
arch/s390/net/bpf_jit_comp.c
arch/sh/Kconfig
arch/sh/kernel/cpu/sh2/probe.c
arch/sh/kernel/setup.c
arch/sh/mm/consistent.c
arch/sh/mm/init.c
arch/sh/mm/numa.c
arch/x86/entry/vdso/vdso32/vdso-fakesections.c [deleted file]
arch/x86/events/core.c
arch/x86/events/intel/cstate.c
arch/x86/events/msr.c
arch/x86/include/uapi/asm/kvm_para.h
arch/x86/kernel/amd_nb.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/kvm.c
arch/x86/kernel/tsc.c
arch/x86/kvm/hyperv.c
arch/x86/kvm/lapic.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/xen/enlighten_hvm.c
arch/x86/xen/mmu.c
arch/x86/xen/mmu_pv.c
drivers/acpi/acpica/acnamesp.h
drivers/acpi/acpica/exconfig.c
drivers/acpi/acpica/nsinit.c
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/ahci_mvebu.c
drivers/ata/ahci_qoriq.c
drivers/ata/ahci_xgene.c
drivers/ata/libahci.c
drivers/ata/libahci_platform.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/sata_highbank.c
drivers/ata/sata_sil24.c
drivers/atm/firestream.c
drivers/atm/zatm.c
drivers/block/rbd.c
drivers/bluetooth/btusb.c
drivers/char/agp/uninorth-agp.c
drivers/clk/Kconfig
drivers/clk/imx/clk-imx6ul.c
drivers/cpufreq/Kconfig.arm
drivers/gpio/gpio-aspeed.c
drivers/gpio/gpio-pci-idio-16.c
drivers/gpio/gpio-pcie-idio-24.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
drivers/gpu/drm/amd/display/dc/core/dc_surface.c
drivers/gpu/drm/amd/display/dc/inc/dc_link_ddc.h
drivers/gpu/drm/amd/display/include/dal_asic_id.h
drivers/gpu/drm/amd/display/modules/color/color_gamma.c
drivers/gpu/drm/amd/include/atomfirmware.h
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c
drivers/gpu/drm/bridge/Kconfig
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_dumb_buffers.c
drivers/gpu/drm/drm_file.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/exynos/regs-mixer.h
drivers/gpu/drm/i915/i915_gem_userptr.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_cdclk.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_engine_cs.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_bo.h
drivers/gpu/drm/nouveau/nouveau_ttm.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/omapdrm/dss/dispc.c
drivers/gpu/drm/omapdrm/dss/hdmi4.c
drivers/gpu/drm/omapdrm/dss/hdmi4_core.c
drivers/gpu/drm/omapdrm/dss/hdmi5.c
drivers/gpu/drm/omapdrm/omap_connector.c
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
drivers/gpu/drm/omapdrm/tcm-sita.c
drivers/gpu/drm/ttm/ttm_page_alloc.c
drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
drivers/gpu/drm/vc4/vc4_dpi.c
drivers/gpu/drm/vc4/vc4_drv.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
drivers/hid/Kconfig
drivers/hid/hid-ids.h
drivers/hid/hid-lenovo.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/intel-ish-hid/ishtp-hid-client.c
drivers/hid/intel-ish-hid/ishtp/bus.c
drivers/hid/wacom_sys.c
drivers/hwmon/Kconfig
drivers/hwmon/k10temp.c
drivers/i2c/busses/i2c-designware-master.c
drivers/i2c/busses/i2c-pmcmsp.c
drivers/i2c/busses/i2c-viperboard.c
drivers/i2c/i2c-core-acpi.c
drivers/iommu/amd_iommu.c
drivers/iommu/dma-iommu.c
drivers/iommu/dmar.c
drivers/iommu/intel_irq_remapping.c
drivers/iommu/rockchip-iommu.c
drivers/irqchip/qcom-irq-combiner.c
drivers/md/bcache/debug.c
drivers/md/dm-bufio.c
drivers/md/dm-cache-background-tracker.c
drivers/md/dm-integrity.c
drivers/md/dm-raid1.c
drivers/md/dm.c
drivers/misc/cxl/cxl.h
drivers/misc/cxl/pci.c
drivers/misc/cxl/sysfs.c
drivers/misc/eeprom/at24.c
drivers/mtd/nand/onenand/omap2.c
drivers/mtd/nand/raw/marvell_nand.c
drivers/mtd/nand/raw/nand_base.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_main.c
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/can/spi/hi311x.c
drivers/net/can/usb/kvaser_usb.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/chip.h
drivers/net/dsa/mv88e6xxx/global2.c
drivers/net/ethernet/aquantia/atlantic/aq_nic.c
drivers/net/ethernet/aquantia/atlantic/aq_nic.h
drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/intel/ice/ice_controlq.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/netronome/nfp/flower/main.c
drivers/net/ethernet/ni/nixge.c
drivers/net/ethernet/qlogic/qed/qed_l2.c
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qede/qede_rdma.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/sun/niu.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c
drivers/net/ieee802154/atusb.c
drivers/net/ieee802154/mcr20a.c
drivers/net/phy/broadcom.c
drivers/net/phy/sfp-bus.c
drivers/net/wireless/mac80211_hwsim.c
drivers/nvme/host/core.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/of/overlay.c
drivers/pci/pci.c
drivers/pinctrl/intel/pinctrl-cherryview.c
drivers/pinctrl/intel/pinctrl-sunrisepoint.c
drivers/pinctrl/meson/pinctrl-meson-axg.c
drivers/platform/x86/Kconfig
drivers/s390/cio/qdio_setup.c
drivers/s390/cio/vfio_ccw_cp.c
drivers/scsi/aacraid/commsup.c
drivers/scsi/vmw_pvscsi.c
drivers/spi/spi-bcm-qspi.c
drivers/spi/spi-bcm2835aux.c
drivers/spi/spi-cadence.c
drivers/spi/spi-imx.c
drivers/spi/spi-pxa2xx.h
drivers/spi/spi-sh-msiof.c
drivers/thermal/int340x_thermal/int3403_thermal.c
drivers/thermal/samsung/exynos_tmu.c
drivers/usb/host/xhci-hub.c
drivers/usb/musb/musb_host.c
drivers/usb/musb/musb_host.h
drivers/usb/musb/musb_virthub.c
drivers/usb/usbip/stub.h
drivers/usb/usbip/stub_dev.c
drivers/usb/usbip/stub_main.c
fs/afs/addr_list.c
fs/afs/callback.c
fs/afs/cmservice.c
fs/afs/dir.c
fs/afs/file.c
fs/afs/flock.c
fs/afs/fsclient.c
fs/afs/inode.c
fs/afs/internal.h
fs/afs/rotate.c
fs/afs/rxrpc.c
fs/afs/security.c
fs/afs/server.c
fs/afs/server_list.c
fs/afs/super.c
fs/afs/write.c
fs/ceph/file.c
fs/cifs/cifsfs.c
fs/cifs/connect.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/hfsplus/super.c
fs/ocfs2/refcounttree.c
fs/proc/base.c
fs/proc/kcore.c
include/kvm/arm_vgic.h
include/linux/brcmphy.h
include/linux/ceph/osd_client.h
include/linux/kthread.h
include/linux/kvm_host.h
include/linux/mm.h
include/linux/mtd/map.h
include/linux/mtd/rawnand.h
include/linux/oom.h
include/linux/rbtree_augmented.h
include/linux/rbtree_latch.h
include/linux/sched.h
include/linux/sched/signal.h
include/net/bonding.h
include/net/flow_dissector.h
include/net/mac80211.h
include/net/xfrm.h
include/trace/events/afs.h
include/trace/events/rxrpc.h
include/trace/events/sunrpc.h
include/trace/events/xen.h
include/uapi/linux/nl80211.h
init/main.c
kernel/bpf/syscall.c
kernel/compat.c
kernel/events/ring_buffer.c
kernel/kthread.c
kernel/module.c
kernel/sched/autogroup.c
kernel/sched/core.c
kernel/sched/cpufreq_schedutil.c
kernel/sched/fair.c
kernel/signal.c
kernel/stop_machine.c
kernel/time/clocksource.c
kernel/trace/trace_events_filter.c
lib/find_bit_benchmark.c
lib/radix-tree.c
lib/swiotlb.c
lib/test_bitmap.c
lib/vsprintf.c
mm/Kconfig
mm/gup.c
mm/migrate.c
mm/mmap.c
mm/oom_kill.c
mm/sparse.c
mm/vmstat.c
mm/z3fold.c
net/9p/trans_common.c
net/9p/trans_fd.c
net/9p/trans_rdma.c
net/9p/trans_virtio.c
net/9p/trans_xen.c
net/atm/lec.c
net/ceph/osd_client.c
net/ieee802154/6lowpan/6lowpan_i.h
net/ieee802154/6lowpan/reassembly.c
net/ipv4/ping.c
net/ipv4/route.c
net/ipv4/udp.c
net/ipv6/Kconfig
net/ipv6/ip6_vti.c
net/ipv6/udp.c
net/ipv6/xfrm6_tunnel.c
net/key/af_key.c
net/llc/af_llc.c
net/mac80211/agg-tx.c
net/mac80211/mlme.c
net/mac80211/tx.c
net/netlink/af_netlink.c
net/nsh/nsh.c
net/openvswitch/flow_netlink.c
net/rfkill/rfkill-gpio.c
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/conn_event.c
net/rxrpc/input.c
net/rxrpc/local_event.c
net/rxrpc/local_object.c
net/rxrpc/output.c
net/rxrpc/peer_event.c
net/rxrpc/rxkad.c
net/rxrpc/sendmsg.c
net/sched/act_skbedit.c
net/sched/act_skbmod.c
net/sched/cls_api.c
net/sctp/associola.c
net/sctp/sm_make_chunk.c
net/sctp/sm_statefuns.c
net/sctp/ulpevent.c
net/sunrpc/xprtrdma/fmr_ops.c
net/sunrpc/xprtrdma/frwr_ops.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtrdma/xprt_rdma.h
net/tipc/node.c
net/tipc/socket.c
net/tls/tls_main.c
net/wireless/core.c
net/wireless/nl80211.c
net/wireless/reg.c
net/xfrm/xfrm_state.c
scripts/dtc/checks.c
scripts/faddr2line
security/selinux/hooks.c
sound/core/control_compat.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/usb/mixer.c
sound/usb/stream.c
tools/arch/arm/include/uapi/asm/kvm.h
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/x86/include/asm/cpufeatures.h
tools/include/linux/spinlock.h
tools/include/uapi/linux/kvm.h
tools/perf/bench/numa.c
tools/perf/pmu-events/arch/x86/mapfile.csv
tools/perf/util/parse-events.y
tools/testing/radix-tree/Makefile
tools/testing/radix-tree/multiorder.c
tools/testing/radix-tree/test.c
tools/testing/radix-tree/test.h
tools/testing/selftests/kvm/Makefile
tools/testing/selftests/kvm/include/test_util.h
tools/testing/selftests/kvm/lib/kvm_util.c
tools/testing/selftests/kvm/sync_regs_test.c
tools/testing/selftests/kvm/vmx_tsc_adjust_test.c
tools/testing/selftests/net/Makefile
tools/testing/selftests/tc-testing/tc-tests/actions/bpf.json
virt/kvm/arm/vgic/vgic-debug.c
virt/kvm/arm/vgic/vgic-init.c
virt/kvm/arm/vgic/vgic-its.c
virt/kvm/arm/vgic/vgic-mmio.c
virt/kvm/arm/vgic/vgic-v2.c
virt/kvm/arm/vgic/vgic-v3.c
virt/kvm/arm/vgic/vgic.c
virt/kvm/arm/vgic/vgic.h

index 640f65e79ef1c00c94508b6b9f9fe8b63a1305a6..8e69345c37ccd9e1d74bd86f5858a45b1573f838 100644 (file)
@@ -244,3 +244,11 @@ Description:    read only
                 Returns 1 if the psl timebase register is synchronized
                 with the core timebase register, 0 otherwise.
 Users:          https://github.com/ibm-capi/libcxl
+
+What:           /sys/class/cxl/<card>/tunneled_ops_supported
+Date:           May 2018
+Contact:        linuxppc-dev@lists.ozlabs.org
+Description:    read only
+                Returns 1 if tunneled operations are supported in capi mode,
+                0 otherwise.
+Users:          https://github.com/ibm-capi/libcxl
index d2b6fda3d67b97eeeb44c0c045eb3e5963f9233f..ab2fe0eda1d7c317faefab52363ce96755ac64d5 100644 (file)
@@ -145,7 +145,7 @@ feature enabled.]
 
 In this mode ``intel_pstate`` registers utilization update callbacks with the
 CPU scheduler in order to run a P-state selection algorithm, either
-``powersave`` or ``performance``, depending on the ``scaling_cur_freq`` policy
+``powersave`` or ``performance``, depending on the ``scaling_governor`` policy
 setting in ``sysfs``.  The current CPU frequency information to be made
 available from the ``scaling_cur_freq`` policy attribute in ``sysfs`` is
 periodically updated by those utilization update callbacks too.
index 1e5c0f00cb2fee319032ea0b27e93a03eef8aee6..dbf5acd49f350de349bf228e9b7c824e2cfd04b1 100644 (file)
@@ -15,7 +15,7 @@ Sleep States That Can Be Supported
 ==================================
 
 Depending on its configuration and the capabilities of the platform it runs on,
-the Linux kernel can support up to four system sleep states, includig
+the Linux kernel can support up to four system sleep states, including
 hibernation and up to three variants of system suspend.  The sleep states that
 can be supported by the kernel are listed below.
 
index 4bcd4b7f79f9437077b5c0b5dc0e9b8e119fb9ac..3d01948ea0611f56e4cf603dd2df14548b42471c 100644 (file)
@@ -264,7 +264,10 @@ i) Constructor
                           data device, but just remove the mapping.
 
       read_only: Don't allow any changes to be made to the pool
-                metadata.
+                metadata.  This mode is only available after the
+                thin-pool has been created and first used in full
+                read/write mode.  It cannot be specified on initial
+                thin-pool creation.
 
       error_if_no_space: Error IOs, instead of queueing, if no space.
 
index f4006d3c9fdf444df5a6b730a5f9542968c95c85..c760ecb8138136085eead51ab07c38074d989c4a 100644 (file)
@@ -30,7 +30,6 @@ compatible:
 Optional properties:
 - dma-coherent      : Present if dma operations are coherent
 - clocks            : a list of phandle + clock specifier pairs
-- resets            : a list of phandle + reset specifier pairs
 - target-supply     : regulator for SATA target power
 - phys              : reference to the SATA PHY node
 - phy-names         : must be "sata-phy"
index 557fa765adcb9450c4003555d1211978e73a9703..5d2519af4bb5ca5e33f59b3b5a42e8c9242345a2 100644 (file)
@@ -38,7 +38,7 @@ Display Timings
   require specific display timings. The panel-timing subnode expresses those
   timings as specified in the timing subnode section of the display timing
   bindings defined in
-  Documentation/devicetree/bindings/display/display-timing.txt.
+  Documentation/devicetree/bindings/display/panel/display-timing.txt.
 
 
 Connectivity
index aadfb236d53abdd12fc69cf36cd1940303441deb..61315eaa76606d777a05d61a3caa3dbf845bd81a 100644 (file)
@@ -26,6 +26,7 @@ Required Properties:
                - "renesas,dmac-r8a7794" (R-Car E2)
                - "renesas,dmac-r8a7795" (R-Car H3)
                - "renesas,dmac-r8a7796" (R-Car M3-W)
+               - "renesas,dmac-r8a77965" (R-Car M3-N)
                - "renesas,dmac-r8a77970" (R-Car V3M)
                - "renesas,dmac-r8a77980" (R-Car V3H)
 
index 93c3a6ae32f995e92bbfedb4ba710004c1c0a0b0..ac71daa4619505030ac1373e678ca13241727f82 100644 (file)
@@ -5,7 +5,9 @@ Required properties:
 - compatible: Must contain one or more of the following:
   - "renesas,rcar-gen3-canfd" for R-Car Gen3 compatible controller.
   - "renesas,r8a7795-canfd" for R8A7795 (R-Car H3) compatible controller.
-  - "renesas,r8a7796-canfd" for R8A7796 (R-Car M3) compatible controller.
+  - "renesas,r8a7796-canfd" for R8A7796 (R-Car M3-W) compatible controller.
+  - "renesas,r8a77970-canfd" for R8A77970 (R-Car V3M) compatible controller.
+  - "renesas,r8a77980-canfd" for R8A77980 (R-Car V3H) compatible controller.
 
   When compatible with the generic version, nodes must list the
   SoC-specific version corresponding to the platform first, followed by the
index c306f55d335b15e322a05aaed4cc09b7ae522fb4..890526dbfc26478f623a8e0b7f78d966509171e7 100644 (file)
@@ -18,6 +18,7 @@ Required properties:
 
       - "renesas,etheravb-r8a7795" for the R8A7795 SoC.
       - "renesas,etheravb-r8a7796" for the R8A7796 SoC.
+      - "renesas,etheravb-r8a77965" for the R8A77965 SoC.
       - "renesas,etheravb-r8a77970" for the R8A77970 SoC.
       - "renesas,etheravb-r8a77980" for the R8A77980 SoC.
       - "renesas,etheravb-r8a77995" for the R8A77995 SoC.
index ed5eb547afc81da53cb951506226341bbdfcf6ec..64bc5c2a76da613609b3c4db8f3bc00bf9a38107 100644 (file)
@@ -56,9 +56,9 @@ pins it needs, and how they should be configured, with regard to muxer
 configuration, drive strength and pullups. If one of these options is
 not set, its actual value will be unspecified.
 
-This driver supports the generic pin multiplexing and configuration
-bindings. For details on each properties, you can refer to
-./pinctrl-bindings.txt.
+Allwinner A1X Pin Controller supports the generic pin multiplexing and
+configuration bindings. For details on each properties, you can refer to
+ ./pinctrl-bindings.txt.
 
 Required sub-node properties:
   - pins
index a006ea4d065f7cdd0781ef2ef1ab1ee35827c5da..106808b55b6da64d97d8d727673b14445b45bbb5 100644 (file)
@@ -43,6 +43,8 @@ Required properties:
     - "renesas,hscif-r8a7795" for R8A7795 (R-Car H3) HSCIF compatible UART.
     - "renesas,scif-r8a7796" for R8A7796 (R-Car M3-W) SCIF compatible UART.
     - "renesas,hscif-r8a7796" for R8A7796 (R-Car M3-W) HSCIF compatible UART.
+    - "renesas,scif-r8a77965" for R8A77965 (R-Car M3-N) SCIF compatible UART.
+    - "renesas,hscif-r8a77965" for R8A77965 (R-Car M3-N) HSCIF compatible UART.
     - "renesas,scif-r8a77970" for R8A77970 (R-Car V3M) SCIF compatible UART.
     - "renesas,hscif-r8a77970" for R8A77970 (R-Car V3M) HSCIF compatible UART.
     - "renesas,scif-r8a77980" for R8A77980 (R-Car V3H) SCIF compatible UART.
index b5f978a4cac67471a7398d24a388fd04b88702ff..a38d8bfae19c3a7897032d1b80c83622ba92da5d 100644 (file)
@@ -182,6 +182,7 @@ karo        Ka-Ro electronics GmbH
 keithkoep      Keith & Koep GmbH
 keymile        Keymile GmbH
 khadas Khadas
+kiebackpeter    Kieback & Peter GmbH
 kinetic Kinetic Technologies
 kingnovel      Kingnovel Technology Co., Ltd.
 kosagi Sutajio Ko-Usagi PTE Ltd.
index a4feb6dde8cd08e83b7b9672c90f863311dc9d75..725fb8d255c16a8ae722a4c4d47d1492900d724a 100644 (file)
@@ -98,6 +98,14 @@ Finally, if you need to remove all overlays in one-go, just call
 of_overlay_remove_all() which will remove every single one in the correct
 order.
 
+In addition, there is the option to register notifiers that get called on
+overlay operations. See of_overlay_notifier_register/unregister and
+enum of_overlay_notify_action for details.
+
+Note that a notifier callback is not supposed to store pointers to a device
+tree node or its content beyond OF_OVERLAY_POST_REMOVE corresponding to the
+respective node it received.
+
 Overlay DTS Format
 ------------------
 
index d4f33eb805dd228a8d8aff796bd77327334aa24b..ab022dcd09117571d215294ed51c5675543165f1 100644 (file)
@@ -72,8 +72,8 @@ KVM_FEATURE_CLOCKSOURCE_STABLE_BIT ||    24 || host will warn if no guest-side
 
 flag                               || value || meaning
 ==================================================================================
-KVM_HINTS_DEDICATED                ||     0 || guest checks this feature bit to
-                                   ||       || determine if there is vCPU pinning
-                                   ||       || and there is no vCPU over-commitment,
+KVM_HINTS_REALTIME                 ||     0 || guest checks this feature bit to
+                                   ||       || determine that vCPUs are never
+                                   ||       || preempted for an unlimited time,
                                    ||       || allowing optimizations
 ----------------------------------------------------------------------------------
index df6e9bb2559afd3e77ff91d2032ed1af8541ad16..d155d1e0dbc29a009def28121bcef5acbb4196d8 100644 (file)
@@ -137,9 +137,9 @@ Maintainers List (try to look for most precise areas first)
                -----------------------------------
 
 3C59X NETWORK DRIVER
-M:     Steffen Klassert <klassert@mathematik.tu-chemnitz.de>
+M:     Steffen Klassert <klassert@kernel.org>
 L:     netdev@vger.kernel.org
-S:     Maintained
+S:     Odd Fixes
 F:     Documentation/networking/vortex.txt
 F:     drivers/net/ethernet/3com/3c59x.c
 
@@ -3691,7 +3691,6 @@ F:        drivers/cpufreq/arm_big_little_dt.c
 
 CPU POWER MONITORING SUBSYSTEM
 M:     Thomas Renninger <trenn@suse.com>
-M:     Shuah Khan <shuahkh@osg.samsung.com>
 M:     Shuah Khan <shuah@kernel.org>
 L:     linux-pm@vger.kernel.org
 S:     Maintained
@@ -7696,10 +7695,10 @@ F:      include/linux/sunrpc/
 F:     include/uapi/linux/sunrpc/
 
 KERNEL SELFTEST FRAMEWORK
-M:     Shuah Khan <shuahkh@osg.samsung.com>
 M:     Shuah Khan <shuah@kernel.org>
 L:     linux-kselftest@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git
+Q:     https://patchwork.kernel.org/project/linux-kselftest/list/
 S:     Maintained
 F:     tools/testing/selftests/
 F:     Documentation/dev-tools/kselftest*
@@ -9873,7 +9872,7 @@ F:        include/linux/platform_data/nxp-nci.h
 F:     Documentation/devicetree/bindings/net/nfc/
 
 NFS, SUNRPC, AND LOCKD CLIENTS
-M:     Trond Myklebust <trond.myklebust@primarydata.com>
+M:     Trond Myklebust <trond.myklebust@hammerspace.com>
 M:     Anna Schumaker <anna.schumaker@netapp.com>
 L:     linux-nfs@vger.kernel.org
 W:     http://client.linux-nfs.org
@@ -12222,7 +12221,7 @@ F:      Documentation/s390/vfio-ccw.txt
 F:     include/uapi/linux/vfio_ccw.h
 
 S390 ZCRYPT DRIVER
-M:     Harald Freudenberger <freude@de.ibm.com>
+M:     Harald Freudenberger <freude@linux.ibm.com>
 L:     linux-s390@vger.kernel.org
 W:     http://www.ibm.com/developerworks/linux/linux390/
 S:     Supported
@@ -13266,6 +13265,12 @@ M:     Jan-Benedict Glaw <jbglaw@lug-owl.de>
 S:     Maintained
 F:     arch/alpha/kernel/srm_env.c
 
+ST STM32 I2C/SMBUS DRIVER
+M:     Pierre-Yves MORDRET <pierre-yves.mordret@st.com>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     drivers/i2c/busses/i2c-stm32*
+
 STABLE BRANCH
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     stable@vger.kernel.org
@@ -14650,7 +14655,6 @@ F:      drivers/usb/common/usb-otg-fsm.c
 
 USB OVER IP DRIVER
 M:     Valentina Manea <valentina.manea.m@gmail.com>
-M:     Shuah Khan <shuahkh@osg.samsung.com>
 M:     Shuah Khan <shuah@kernel.org>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
index 619a85ad716b43e2aafa080eb5e85da9516d5459..ba3106b3659783c563d84cf6683960d18a23bcf3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,8 +2,8 @@
 VERSION = 4
 PATCHLEVEL = 17
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
-NAME = Fearless Coyote
+EXTRAVERSION = -rc5
+NAME = Merciless Moray
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index 8e0d665c8d53d3c57c2c434939f93125472ff610..75dd23acf133b089384db7e9071a37980e98c5ea 100644 (file)
@@ -464,6 +464,10 @@ config GCC_PLUGIN_LATENT_ENTROPY
 config GCC_PLUGIN_STRUCTLEAK
        bool "Force initialization of variables containing userspace addresses"
        depends on GCC_PLUGINS
+       # Currently STRUCTLEAK inserts initialization out of live scope of
+       # variables from KASAN point of view. This leads to KASAN false
+       # positive reports. Prohibit this combination for now.
+       depends on !KASAN_EXTRA
        help
          This plugin zero-initializes any structures containing a
          __user attribute. This can prevent some classes of information
index bf343195697e8ccbfcbfe8ad0b2421c09d13015e..54111ed218b10ff964a721f325b7dc1cc4e98539 100644 (file)
                        };
 
                        can1: can@53fe4000 {
-                               compatible = "fsl,imx35-flexcan";
+                               compatible = "fsl,imx35-flexcan", "fsl,imx25-flexcan";
                                reg = <0x53fe4000 0x1000>;
                                clocks = <&clks 33>, <&clks 33>;
                                clock-names = "ipg", "per";
                        };
 
                        can2: can@53fe8000 {
-                               compatible = "fsl,imx35-flexcan";
+                               compatible = "fsl,imx35-flexcan", "fsl,imx25-flexcan";
                                reg = <0x53fe8000 0x1000>;
                                clocks = <&clks 34>, <&clks 34>;
                                clock-names = "ipg", "per";
index 7d647d043f528ab1194b0467a7552d34a3a7a9b7..3d65c0192f6931f6f5997e2de8e5cb1c2f2a8b6e 100644 (file)
                        };
 
                        can1: can@53fc8000 {
-                               compatible = "fsl,imx53-flexcan";
+                               compatible = "fsl,imx53-flexcan", "fsl,imx25-flexcan";
                                reg = <0x53fc8000 0x4000>;
                                interrupts = <82>;
                                clocks = <&clks IMX5_CLK_CAN1_IPG_GATE>,
                        };
 
                        can2: can@53fcc000 {
-                               compatible = "fsl,imx53-flexcan";
+                               compatible = "fsl,imx53-flexcan", "fsl,imx25-flexcan";
                                reg = <0x53fcc000 0x4000>;
                                interrupts = <83>;
                                clocks = <&clks IMX5_CLK_CAN2_IPG_GATE>,
index 707a1f06dc5d5e207f0d2c18e0b37844569ca199..f675162663f09a054253b8ad6d86361c74968618 100644 (file)
@@ -309,6 +309,22 @@ static inline unsigned int kvm_get_vmid_bits(void)
        return 8;
 }
 
+/*
+ * We are not in the kvm->srcu critical section most of the time, so we take
+ * the SRCU read lock here. Since we copy the data from the user page, we
+ * can immediately drop the lock again.
+ */
+static inline int kvm_read_guest_lock(struct kvm *kvm,
+                                     gpa_t gpa, void *data, unsigned long len)
+{
+       int srcu_idx = srcu_read_lock(&kvm->srcu);
+       int ret = kvm_read_guest(kvm, gpa, data, len);
+
+       srcu_read_unlock(&kvm->srcu, srcu_idx);
+
+       return ret;
+}
+
 static inline void *kvm_get_hyp_vector(void)
 {
        return kvm_ksym_ref(__kvm_hyp_vector);
index 30014a9f8f2b335f95193af0f6e45ed9cd59a48a..ea690b3562afb20773ce81cf3ea48f897f5998b1 100644 (file)
@@ -75,6 +75,7 @@
 #define ARM_CPU_IMP_CAVIUM             0x43
 #define ARM_CPU_IMP_BRCM               0x42
 #define ARM_CPU_IMP_QCOM               0x51
+#define ARM_CPU_IMP_NVIDIA             0x4E
 
 #define ARM_CPU_PART_AEM_V8            0xD0F
 #define ARM_CPU_PART_FOUNDATION                0xD00
 #define QCOM_CPU_PART_FALKOR           0xC00
 #define QCOM_CPU_PART_KRYO             0x200
 
+#define NVIDIA_CPU_PART_DENVER         0x003
+#define NVIDIA_CPU_PART_CARMEL         0x004
+
 #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
 #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
 #define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72)
 #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1)
 #define MIDR_QCOM_FALKOR MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR)
 #define MIDR_QCOM_KRYO MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_KRYO)
+#define MIDR_NVIDIA_DENVER MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_DENVER)
+#define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL)
 
 #ifndef __ASSEMBLY__
 
index 23b33e8ea03a6a56ab3066704c1090da9921e073..1dab3a9846082e5bfbf640dc04c3e8aa70ba24cc 100644 (file)
@@ -333,7 +333,7 @@ static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
        } else {
                u64 sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL1);
                sctlr |= (1 << 25);
-               vcpu_write_sys_reg(vcpu, SCTLR_EL1, sctlr);
+               vcpu_write_sys_reg(vcpu, sctlr, SCTLR_EL1);
        }
 }
 
index 082110993647b9b7e30cf18da5d9d447c58d362f..6128992c2ded6b7e1aa4ba835474f6f45f6fdc5e 100644 (file)
@@ -360,6 +360,22 @@ static inline unsigned int kvm_get_vmid_bits(void)
        return (cpuid_feature_extract_unsigned_field(reg, ID_AA64MMFR1_VMIDBITS_SHIFT) == 2) ? 16 : 8;
 }
 
+/*
+ * We are not in the kvm->srcu critical section most of the time, so we take
+ * the SRCU read lock here. Since we copy the data from the user page, we
+ * can immediately drop the lock again.
+ */
+static inline int kvm_read_guest_lock(struct kvm *kvm,
+                                     gpa_t gpa, void *data, unsigned long len)
+{
+       int srcu_idx = srcu_read_lock(&kvm->srcu);
+       int ret = kvm_read_guest(kvm, gpa, data, len);
+
+       srcu_read_unlock(&kvm->srcu, srcu_idx);
+
+       return ret;
+}
+
 #ifdef CONFIG_KVM_INDIRECT_VECTORS
 /*
  * EL2 vectors can be mapped and rerouted in a number of ways,
index a900befadfe84a0018112ad0e11d367fe896371f..e4a1182deff7f2ef24bce12082a0868f36715a1c 100644 (file)
@@ -316,6 +316,7 @@ static const struct midr_range arm64_bp_harden_smccc_cpus[] = {
        MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
        MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
        MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR),
+       MIDR_ALL_VERSIONS(MIDR_NVIDIA_DENVER),
        {},
 };
 
index 86801b6055d6dc714a1bb98640caee9985965092..39be799d04175fcb32428370e1f7a169751764a6 100644 (file)
 #include <linux/compiler.h>
 #include <linux/irqchip/arm-gic.h>
 #include <linux/kvm_host.h>
+#include <linux/swab.h>
 
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_hyp.h>
 #include <asm/kvm_mmu.h>
 
+static bool __hyp_text __is_be(struct kvm_vcpu *vcpu)
+{
+       if (vcpu_mode_is_32bit(vcpu))
+               return !!(read_sysreg_el2(spsr) & COMPAT_PSR_E_BIT);
+
+       return !!(read_sysreg(SCTLR_EL1) & SCTLR_ELx_EE);
+}
+
 /*
  * __vgic_v2_perform_cpuif_access -- perform a GICV access on behalf of the
  *                                  guest.
@@ -64,14 +73,19 @@ int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
        addr += fault_ipa - vgic->vgic_cpu_base;
 
        if (kvm_vcpu_dabt_iswrite(vcpu)) {
-               u32 data = vcpu_data_guest_to_host(vcpu,
-                                                  vcpu_get_reg(vcpu, rd),
-                                                  sizeof(u32));
+               u32 data = vcpu_get_reg(vcpu, rd);
+               if (__is_be(vcpu)) {
+                       /* guest pre-swabbed data, undo this for writel() */
+                       data = swab32(data);
+               }
                writel_relaxed(data, addr);
        } else {
                u32 data = readl_relaxed(addr);
-               vcpu_set_reg(vcpu, rd, vcpu_data_host_to_guest(vcpu, data,
-                                                              sizeof(u32)));
+               if (__is_be(vcpu)) {
+                       /* guest expects swabbed data */
+                       data = swab32(data);
+               }
+               vcpu_set_reg(vcpu, rd, data);
        }
 
        return 1;
index 9f3c47acf8ffb1170ad411985dcb1a288dfea2df..1b18b472242034b2cfe90ff91a27da8b850bcdaa 100644 (file)
@@ -646,8 +646,10 @@ static int keep_initrd __initdata;
 
 void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
-       if (!keep_initrd)
+       if (!keep_initrd) {
                free_reserved_area((void *)start, (void *)end, 0, "initrd");
+               memblock_free(__virt_to_phys(start), end - start);
+       }
 }
 
 static int __init keepinitrd_setup(char *__unused)
index 9abddde372abfbb11934f93da2e39924fe4116d3..b2dabd06659dd0b4cce575e0e00336f9d5f36cb6 100644 (file)
@@ -69,17 +69,30 @@ struct dyn_arch_ftrace {
 #endif
 
 #if defined(CONFIG_FTRACE_SYSCALLS) && !defined(__ASSEMBLY__)
-#ifdef PPC64_ELF_ABI_v1
+/*
+ * Some syscall entry functions on powerpc start with "ppc_" (fork and clone,
+ * for instance) or ppc32_/ppc64_. We should also match the sys_ variant with
+ * those.
+ */
 #define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
+#ifdef PPC64_ELF_ABI_v1
+static inline bool arch_syscall_match_sym_name(const char *sym, const char *name)
+{
+       /* We need to skip past the initial dot, and the __se_sys alias */
+       return !strcmp(sym + 1, name) ||
+               (!strncmp(sym, ".__se_sys", 9) && !strcmp(sym + 6, name)) ||
+               (!strncmp(sym, ".ppc_", 5) && !strcmp(sym + 5, name + 4)) ||
+               (!strncmp(sym, ".ppc32_", 7) && !strcmp(sym + 7, name + 4)) ||
+               (!strncmp(sym, ".ppc64_", 7) && !strcmp(sym + 7, name + 4));
+}
+#else
 static inline bool arch_syscall_match_sym_name(const char *sym, const char *name)
 {
-       /*
-        * Compare the symbol name with the system call name. Skip the .sys or .SyS
-        * prefix from the symbol name and the sys prefix from the system call name and
-        * just match the rest. This is only needed on ppc64 since symbol names on
-        * 32bit do not start with a period so the generic function will work.
-        */
-       return !strcmp(sym + 4, name + 3);
+       return !strcmp(sym, name) ||
+               (!strncmp(sym, "__se_sys", 8) && !strcmp(sym + 5, name)) ||
+               (!strncmp(sym, "ppc_", 4) && !strcmp(sym + 4, name + 4)) ||
+               (!strncmp(sym, "ppc32_", 6) && !strcmp(sym + 6, name + 4)) ||
+               (!strncmp(sym, "ppc64_", 6) && !strcmp(sym + 6, name + 4));
 }
 #endif
 #endif /* CONFIG_FTRACE_SYSCALLS && !__ASSEMBLY__ */
index 4185f1c9612501b51ffdafc2c8f125d1fa6ee1f3..3f109a3e3edb226578b37de27c8ffde14e9748e2 100644 (file)
@@ -165,7 +165,6 @@ struct paca_struct {
        u64 saved_msr;                  /* MSR saved here by enter_rtas */
        u16 trap_save;                  /* Used when bad stack is encountered */
        u8 irq_soft_mask;               /* mask for irq soft masking */
-       u8 soft_enabled;                /* irq soft-enable flag */
        u8 irq_happened;                /* irq happened while soft-disabled */
        u8 io_sync;                     /* writel() needs spin_unlock sync */
        u8 irq_work_pending;            /* IRQ_WORK interrupt while soft-disable */
index 9f421641a35c8240cbacf192f6a1b22b4f33c63c..16b077801a5f97125f48cc9d597580cef7f8f65d 100644 (file)
@@ -91,6 +91,7 @@ extern int start_topology_update(void);
 extern int stop_topology_update(void);
 extern int prrn_is_enabled(void);
 extern int find_and_online_cpu_nid(int cpu);
+extern int timed_topology_update(int nsecs);
 #else
 static inline int start_topology_update(void)
 {
@@ -108,16 +109,12 @@ static inline int find_and_online_cpu_nid(int cpu)
 {
        return 0;
 }
+static inline int timed_topology_update(int nsecs)
+{
+       return 0;
+}
 #endif /* CONFIG_NUMA && CONFIG_PPC_SPLPAR */
 
-#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_NEED_MULTIPLE_NODES)
-#if defined(CONFIG_PPC_SPLPAR)
-extern int timed_topology_update(int nsecs);
-#else
-#define        timed_topology_update(nsecs)
-#endif /* CONFIG_PPC_SPLPAR */
-#endif /* CONFIG_HOTPLUG_CPU || CONFIG_NEED_MULTIPLE_NODES */
-
 #include <asm-generic/topology.h>
 
 #ifdef CONFIG_SMP
index 1bceb95f422d0f828017128580695c0d4c87ba47..5584247f502929de6e13df0ca5127a1ab92cdbe8 100644 (file)
@@ -44,6 +44,10 @@ static ssize_t opal_nvram_read(char *buf, size_t count, loff_t *index)
        return count;
 }
 
+/*
+ * This can be called in the panic path with interrupts off, so use
+ * mdelay in that case.
+ */
 static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
 {
        s64 rc = OPAL_BUSY;
@@ -58,10 +62,16 @@ static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
        while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
                rc = opal_write_nvram(__pa(buf), count, off);
                if (rc == OPAL_BUSY_EVENT) {
-                       msleep(OPAL_BUSY_DELAY_MS);
+                       if (in_interrupt() || irqs_disabled())
+                               mdelay(OPAL_BUSY_DELAY_MS);
+                       else
+                               msleep(OPAL_BUSY_DELAY_MS);
                        opal_poll_events(NULL);
                } else if (rc == OPAL_BUSY) {
-                       msleep(OPAL_BUSY_DELAY_MS);
+                       if (in_interrupt() || irqs_disabled())
+                               mdelay(OPAL_BUSY_DELAY_MS);
+                       else
+                               msleep(OPAL_BUSY_DELAY_MS);
                }
        }
 
index 6176fe9795caf995daeb986948ee2c1375d8ee10..941d8cc6c9f5990ffe5aa39aa16bd79ff70ed9fc 100644 (file)
@@ -261,9 +261,9 @@ CONFIG_IP_VS_NQ=m
 CONFIG_IP_VS_FTP=m
 CONFIG_IP_VS_PE_SIP=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
+CONFIG_NF_TABLES_IPV4=y
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
-CONFIG_NF_TABLES_ARP=m
+CONFIG_NF_TABLES_ARP=y
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
@@ -284,7 +284,7 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
+CONFIG_NF_TABLES_IPV6=y
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -305,7 +305,7 @@ CONFIG_IP6_NF_RAW=m
 CONFIG_IP6_NF_SECURITY=m
 CONFIG_IP6_NF_NAT=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
-CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NF_TABLES_BRIDGE=y
 CONFIG_RDS=m
 CONFIG_RDS_RDMA=m
 CONFIG_RDS_TCP=m
@@ -604,7 +604,6 @@ CONFIG_DETECT_HUNG_TASK=y
 CONFIG_WQ_WATCHDOG=y
 CONFIG_PANIC_ON_OOPS=y
 CONFIG_DEBUG_TIMEKEEPING=y
-CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
 CONFIG_PROVE_LOCKING=y
 CONFIG_LOCK_STAT=y
 CONFIG_DEBUG_LOCKDEP=y
index c105bcc6d7a6fc0f932ba7537f85fe6e1a171b1a..eb6f75f242089b6f67115bbbd74c7e8a4f2fbeac 100644 (file)
@@ -259,9 +259,9 @@ CONFIG_IP_VS_NQ=m
 CONFIG_IP_VS_FTP=m
 CONFIG_IP_VS_PE_SIP=m
 CONFIG_NF_CONNTRACK_IPV4=m
-CONFIG_NF_TABLES_IPV4=m
+CONFIG_NF_TABLES_IPV4=y
 CONFIG_NFT_CHAIN_ROUTE_IPV4=m
-CONFIG_NF_TABLES_ARP=m
+CONFIG_NF_TABLES_ARP=y
 CONFIG_NFT_CHAIN_NAT_IPV4=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_AH=m
@@ -282,7 +282,7 @@ CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_NF_CONNTRACK_IPV6=m
-CONFIG_NF_TABLES_IPV6=m
+CONFIG_NF_TABLES_IPV6=y
 CONFIG_NFT_CHAIN_ROUTE_IPV6=m
 CONFIG_NFT_CHAIN_NAT_IPV6=m
 CONFIG_IP6_NF_IPTABLES=m
@@ -303,7 +303,7 @@ CONFIG_IP6_NF_RAW=m
 CONFIG_IP6_NF_SECURITY=m
 CONFIG_IP6_NF_NAT=m
 CONFIG_IP6_NF_TARGET_MASQUERADE=m
-CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NF_TABLES_BRIDGE=y
 CONFIG_RDS=m
 CONFIG_RDS_RDMA=m
 CONFIG_RDS_TCP=m
index e8077f0971f89f1695d5b5637d9c89126cf1e9cc..2bf01ba44107cd678e1fd38b31e5be18080f80b0 100644 (file)
@@ -13,6 +13,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/nospec-insn.h>
 #include <asm/vx-insn.h>
 
 /* Vector register range containing CRC-32 constants */
@@ -67,6 +68,8 @@
 
 .previous
 
+       GEN_BR_THUNK %r14
+
 .text
 /*
  * The CRC-32 function(s) use these calling conventions:
@@ -203,6 +206,6 @@ ENTRY(crc32_be_vgfm_16)
 
 .Ldone:
        VLGVF   %r2,%v2,3
-       br      %r14
+       BR_EX   %r14
 
 .previous
index d8c67a58c0c53b620c4a8f1837ce9bf3c0db5207..7d6f568bd3ad1fe19586e7597ae127b519c7709f 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/nospec-insn.h>
 #include <asm/vx-insn.h>
 
 /* Vector register range containing CRC-32 constants */
@@ -76,6 +77,7 @@
 
 .previous
 
+       GEN_BR_THUNK %r14
 
 .text
 
@@ -264,6 +266,6 @@ crc32_le_vgfm_generic:
 
 .Ldone:
        VLGVF   %r2,%v2,2
-       br      %r14
+       BR_EX   %r14
 
 .previous
diff --git a/arch/s390/include/asm/nospec-insn.h b/arch/s390/include/asm/nospec-insn.h
new file mode 100644 (file)
index 0000000..a01f811
--- /dev/null
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_S390_NOSPEC_ASM_H
+#define _ASM_S390_NOSPEC_ASM_H
+
+#include <asm/alternative-asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/dwarf.h>
+
+#ifdef __ASSEMBLY__
+
+#ifdef CONFIG_EXPOLINE
+
+_LC_BR_R1 = __LC_BR_R1
+
+/*
+ * The expoline macros are used to create thunks in the same format
+ * as gcc generates them. The 'comdat' section flag makes sure that
+ * the various thunks are merged into a single copy.
+ */
+       .macro __THUNK_PROLOG_NAME name
+       .pushsection .text.\name,"axG",@progbits,\name,comdat
+       .globl \name
+       .hidden \name
+       .type \name,@function
+\name:
+       CFI_STARTPROC
+       .endm
+
+       .macro __THUNK_EPILOG
+       CFI_ENDPROC
+       .popsection
+       .endm
+
+       .macro __THUNK_PROLOG_BR r1,r2
+       __THUNK_PROLOG_NAME __s390x_indirect_jump_r\r2\()use_r\r1
+       .endm
+
+       .macro __THUNK_PROLOG_BC d0,r1,r2
+       __THUNK_PROLOG_NAME __s390x_indirect_branch_\d0\()_\r2\()use_\r1
+       .endm
+
+       .macro __THUNK_BR r1,r2
+       jg      __s390x_indirect_jump_r\r2\()use_r\r1
+       .endm
+
+       .macro __THUNK_BC d0,r1,r2
+       jg      __s390x_indirect_branch_\d0\()_\r2\()use_\r1
+       .endm
+
+       .macro __THUNK_BRASL r1,r2,r3
+       brasl   \r1,__s390x_indirect_jump_r\r3\()use_r\r2
+       .endm
+
+       .macro  __DECODE_RR expand,reg,ruse
+       .set __decode_fail,1
+       .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+       .ifc \reg,%r\r1
+       .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+       .ifc \ruse,%r\r2
+       \expand \r1,\r2
+       .set __decode_fail,0
+       .endif
+       .endr
+       .endif
+       .endr
+       .if __decode_fail == 1
+       .error "__DECODE_RR failed"
+       .endif
+       .endm
+
+       .macro  __DECODE_RRR expand,rsave,rtarget,ruse
+       .set __decode_fail,1
+       .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+       .ifc \rsave,%r\r1
+       .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+       .ifc \rtarget,%r\r2
+       .irp r3,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+       .ifc \ruse,%r\r3
+       \expand \r1,\r2,\r3
+       .set __decode_fail,0
+       .endif
+       .endr
+       .endif
+       .endr
+       .endif
+       .endr
+       .if __decode_fail == 1
+       .error "__DECODE_RRR failed"
+       .endif
+       .endm
+
+       .macro  __DECODE_DRR expand,disp,reg,ruse
+       .set __decode_fail,1
+       .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+       .ifc \reg,%r\r1
+       .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+       .ifc \ruse,%r\r2
+       \expand \disp,\r1,\r2
+       .set __decode_fail,0
+       .endif
+       .endr
+       .endif
+       .endr
+       .if __decode_fail == 1
+       .error "__DECODE_DRR failed"
+       .endif
+       .endm
+
+       .macro __THUNK_EX_BR reg,ruse
+       # Be very careful when adding instructions to this macro!
+       # The ALTERNATIVE replacement code has a .+10 which targets
+       # the "br \reg" after the code has been patched.
+#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
+       exrl    0,555f
+       j       .
+#else
+       .ifc \reg,%r1
+       ALTERNATIVE "ex %r0,_LC_BR_R1", ".insn ril,0xc60000000000,0,.+10", 35
+       j       .
+       .else
+       larl    \ruse,555f
+       ex      0,0(\ruse)
+       j       .
+       .endif
+#endif
+555:   br      \reg
+       .endm
+
+       .macro __THUNK_EX_BC disp,reg,ruse
+#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
+       exrl    0,556f
+       j       .
+#else
+       larl    \ruse,556f
+       ex      0,0(\ruse)
+       j       .
+#endif
+556:   b       \disp(\reg)
+       .endm
+
+       .macro GEN_BR_THUNK reg,ruse=%r1
+       __DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse
+       __THUNK_EX_BR \reg,\ruse
+       __THUNK_EPILOG
+       .endm
+
+       .macro GEN_B_THUNK disp,reg,ruse=%r1
+       __DECODE_DRR __THUNK_PROLOG_BC,\disp,\reg,\ruse
+       __THUNK_EX_BC \disp,\reg,\ruse
+       __THUNK_EPILOG
+       .endm
+
+       .macro BR_EX reg,ruse=%r1
+557:   __DECODE_RR __THUNK_BR,\reg,\ruse
+       .pushsection .s390_indirect_branches,"a",@progbits
+       .long   557b-.
+       .popsection
+       .endm
+
+        .macro B_EX disp,reg,ruse=%r1
+558:   __DECODE_DRR __THUNK_BC,\disp,\reg,\ruse
+       .pushsection .s390_indirect_branches,"a",@progbits
+       .long   558b-.
+       .popsection
+       .endm
+
+       .macro BASR_EX rsave,rtarget,ruse=%r1
+559:   __DECODE_RRR __THUNK_BRASL,\rsave,\rtarget,\ruse
+       .pushsection .s390_indirect_branches,"a",@progbits
+       .long   559b-.
+       .popsection
+       .endm
+
+#else
+       .macro GEN_BR_THUNK reg,ruse=%r1
+       .endm
+
+       .macro GEN_B_THUNK disp,reg,ruse=%r1
+       .endm
+
+        .macro BR_EX reg,ruse=%r1
+       br      \reg
+       .endm
+
+        .macro B_EX disp,reg,ruse=%r1
+       b       \disp(\reg)
+       .endm
+
+       .macro BASR_EX rsave,rtarget,ruse=%r1
+       basr    \rsave,\rtarget
+       .endm
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_S390_NOSPEC_ASM_H */
index e297bcfc476f65d0c41e591b9df9f43754b03aa7..6090670df51fcee21b2523fc388ba93ca5510cb0 100644 (file)
 
 int verify_sha256_digest(void);
 
+extern u64 kernel_entry;
+extern u64 kernel_type;
+
+extern u64 crash_start;
+extern u64 crash_size;
+
 #endif /* __ASSEMBLY__ */
 #endif /* _S390_PURGATORY_H_ */
index 84ea6225efb4be999ca6c92343d69f0b138447d6..f92dd8ed3884ae4dbd4bc2f47d30248e794241e1 100644 (file)
@@ -65,6 +65,7 @@ obj-y += nospec-branch.o
 
 extra-y                                += head.o head64.o vmlinux.lds
 
+obj-$(CONFIG_SYSFS)            += nospec-sysfs.o
 CFLAGS_REMOVE_nospec-branch.o  += $(CC_FLAGS_EXPOLINE)
 
 obj-$(CONFIG_MODULES)          += module.o
index eb2a5c0443cd9c4fb6e0cfd4aa71ebdf14e163fa..11aea745a2a6ebce7ea29a894b822d3bcc560c7b 100644 (file)
@@ -181,6 +181,7 @@ int main(void)
        OFFSET(__LC_MACHINE_FLAGS, lowcore, machine_flags);
        OFFSET(__LC_PREEMPT_COUNT, lowcore, preempt_count);
        OFFSET(__LC_GMAP, lowcore, gmap);
+       OFFSET(__LC_BR_R1, lowcore, br_r1_trampoline);
        /* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */
        OFFSET(__LC_DUMP_REIPL, lowcore, ipib);
        /* hardware defined lowcore locations 0x1000 - 0x18ff */
index f6c56009e822473d701cecbc896d3693b080d6c2..b65874b0b412e40ea1baea814fb1169d04f02104 100644 (file)
@@ -9,18 +9,22 @@
 
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
+#include <asm/nospec-insn.h>
 #include <asm/ptrace.h>
 #include <asm/sigp.h>
 
+       GEN_BR_THUNK %r9
+       GEN_BR_THUNK %r14
+
 ENTRY(s390_base_mcck_handler)
        basr    %r13,0
 0:     lg      %r15,__LC_PANIC_STACK   # load panic stack
        aghi    %r15,-STACK_FRAME_OVERHEAD
        larl    %r1,s390_base_mcck_handler_fn
-       lg      %r1,0(%r1)
-       ltgr    %r1,%r1
+       lg      %r9,0(%r1)
+       ltgr    %r9,%r9
        jz      1f
-       basr    %r14,%r1
+       BASR_EX %r14,%r9
 1:     la      %r1,4095
        lmg     %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
        lpswe   __LC_MCK_OLD_PSW
@@ -37,10 +41,10 @@ ENTRY(s390_base_ext_handler)
        basr    %r13,0
 0:     aghi    %r15,-STACK_FRAME_OVERHEAD
        larl    %r1,s390_base_ext_handler_fn
-       lg      %r1,0(%r1)
-       ltgr    %r1,%r1
+       lg      %r9,0(%r1)
+       ltgr    %r9,%r9
        jz      1f
-       basr    %r14,%r1
+       BASR_EX %r14,%r9
 1:     lmg     %r0,%r15,__LC_SAVE_AREA_ASYNC
        ni      __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit
        lpswe   __LC_EXT_OLD_PSW
@@ -57,10 +61,10 @@ ENTRY(s390_base_pgm_handler)
        basr    %r13,0
 0:     aghi    %r15,-STACK_FRAME_OVERHEAD
        larl    %r1,s390_base_pgm_handler_fn
-       lg      %r1,0(%r1)
-       ltgr    %r1,%r1
+       lg      %r9,0(%r1)
+       ltgr    %r9,%r9
        jz      1f
-       basr    %r14,%r1
+       BASR_EX %r14,%r9
        lmg     %r0,%r15,__LC_SAVE_AREA_SYNC
        lpswe   __LC_PGM_OLD_PSW
 1:     lpswe   disabled_wait_psw-0b(%r13)
@@ -117,7 +121,7 @@ ENTRY(diag308_reset)
        larl    %r4,.Lcontinue_psw      # Restore PSW flags
        lpswe   0(%r4)
 .Lcontinue:
-       br      %r14
+       BR_EX   %r14
 .align 16
 .Lrestart_psw:
        .long   0x00080000,0x80000000 + .Lrestart_part2
index 3f22f139a0413f6880118998bbbb48f280bdad5f..f03402efab4b414eefdfd59135f4ee89dda68e8a 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/setup.h>
 #include <asm/nmi.h>
 #include <asm/export.h>
+#include <asm/nospec-insn.h>
 
 __PT_R0      = __PT_GPRS
 __PT_R1      = __PT_GPRS + 8
@@ -183,67 +184,9 @@ _LPP_OFFSET        = __LC_LPP
                    "jnz .+8; .long 0xb2e8d000", 82
        .endm
 
-#ifdef CONFIG_EXPOLINE
-
-       .macro GEN_BR_THUNK name,reg,tmp
-       .section .text.\name,"axG",@progbits,\name,comdat
-       .globl \name
-       .hidden \name
-       .type \name,@function
-\name:
-       CFI_STARTPROC
-#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
-       exrl    0,0f
-#else
-       larl    \tmp,0f
-       ex      0,0(\tmp)
-#endif
-       j       .
-0:     br      \reg
-       CFI_ENDPROC
-       .endm
-
-       GEN_BR_THUNK __s390x_indirect_jump_r1use_r9,%r9,%r1
-       GEN_BR_THUNK __s390x_indirect_jump_r1use_r14,%r14,%r1
-       GEN_BR_THUNK __s390x_indirect_jump_r11use_r14,%r14,%r11
-
-       .macro BASR_R14_R9
-0:     brasl   %r14,__s390x_indirect_jump_r1use_r9
-       .pushsection .s390_indirect_branches,"a",@progbits
-       .long   0b-.
-       .popsection
-       .endm
-
-       .macro BR_R1USE_R14
-0:     jg      __s390x_indirect_jump_r1use_r14
-       .pushsection .s390_indirect_branches,"a",@progbits
-       .long   0b-.
-       .popsection
-       .endm
-
-       .macro BR_R11USE_R14
-0:     jg      __s390x_indirect_jump_r11use_r14
-       .pushsection .s390_indirect_branches,"a",@progbits
-       .long   0b-.
-       .popsection
-       .endm
-
-#else  /* CONFIG_EXPOLINE */
-
-       .macro BASR_R14_R9
-       basr    %r14,%r9
-       .endm
-
-       .macro BR_R1USE_R14
-       br      %r14
-       .endm
-
-       .macro BR_R11USE_R14
-       br      %r14
-       .endm
-
-#endif /* CONFIG_EXPOLINE */
-
+       GEN_BR_THUNK %r9
+       GEN_BR_THUNK %r14
+       GEN_BR_THUNK %r14,%r11
 
        .section .kprobes.text, "ax"
 .Ldummy:
@@ -260,7 +203,7 @@ _LPP_OFFSET = __LC_LPP
 ENTRY(__bpon)
        .globl __bpon
        BPON
-       BR_R1USE_R14
+       BR_EX   %r14
 
 /*
  * Scheduler resume function, called by switch_to
@@ -284,7 +227,7 @@ ENTRY(__switch_to)
        mvc     __LC_CURRENT_PID(4,%r0),0(%r3)  # store pid of next
        lmg     %r6,%r15,__SF_GPRS(%r15)        # load gprs of next task
        ALTERNATIVE "", ".insn s,0xb2800000,_LPP_OFFSET", 40
-       BR_R1USE_R14
+       BR_EX   %r14
 
 .L__critical_start:
 
@@ -351,7 +294,7 @@ sie_exit:
        xgr     %r5,%r5
        lmg     %r6,%r14,__SF_GPRS(%r15)        # restore kernel registers
        lg      %r2,__SF_SIE_REASON(%r15)       # return exit reason code
-       BR_R1USE_R14
+       BR_EX   %r14
 .Lsie_fault:
        lghi    %r14,-EFAULT
        stg     %r14,__SF_SIE_REASON(%r15)      # set exit reason code
@@ -410,7 +353,7 @@ ENTRY(system_call)
        lgf     %r9,0(%r8,%r10)                 # get system call add.
        TSTMSK  __TI_flags(%r12),_TIF_TRACE
        jnz     .Lsysc_tracesys
-       BASR_R14_R9                             # call sys_xxxx
+       BASR_EX %r14,%r9                        # call sys_xxxx
        stg     %r2,__PT_R2(%r11)               # store return value
 
 .Lsysc_return:
@@ -595,7 +538,7 @@ ENTRY(system_call)
        lmg     %r3,%r7,__PT_R3(%r11)
        stg     %r7,STACK_FRAME_OVERHEAD(%r15)
        lg      %r2,__PT_ORIG_GPR2(%r11)
-       BASR_R14_R9                     # call sys_xxx
+       BASR_EX %r14,%r9                # call sys_xxx
        stg     %r2,__PT_R2(%r11)       # store return value
 .Lsysc_tracenogo:
        TSTMSK  __TI_flags(%r12),_TIF_TRACE
@@ -619,7 +562,7 @@ ENTRY(ret_from_fork)
        lmg     %r9,%r10,__PT_R9(%r11)  # load gprs
 ENTRY(kernel_thread_starter)
        la      %r2,0(%r10)
-       BASR_R14_R9
+       BASR_EX %r14,%r9
        j       .Lsysc_tracenogo
 
 /*
@@ -701,7 +644,7 @@ ENTRY(pgm_check_handler)
        je      .Lpgm_return
        lgf     %r9,0(%r10,%r1)         # load address of handler routine
        lgr     %r2,%r11                # pass pointer to pt_regs
-       BASR_R14_R9                     # branch to interrupt-handler
+       BASR_EX %r14,%r9                # branch to interrupt-handler
 .Lpgm_return:
        LOCKDEP_SYS_EXIT
        tm      __PT_PSW+1(%r11),0x01   # returning to user ?
@@ -1019,7 +962,7 @@ ENTRY(psw_idle)
        stpt    __TIMER_IDLE_ENTER(%r2)
 .Lpsw_idle_lpsw:
        lpswe   __SF_EMPTY(%r15)
-       BR_R1USE_R14
+       BR_EX   %r14
 .Lpsw_idle_end:
 
 /*
@@ -1061,7 +1004,7 @@ ENTRY(save_fpu_regs)
 .Lsave_fpu_regs_done:
        oi      __LC_CPU_FLAGS+7,_CIF_FPU
 .Lsave_fpu_regs_exit:
-       BR_R1USE_R14
+       BR_EX   %r14
 .Lsave_fpu_regs_end:
 EXPORT_SYMBOL(save_fpu_regs)
 
@@ -1107,7 +1050,7 @@ load_fpu_regs:
 .Lload_fpu_regs_done:
        ni      __LC_CPU_FLAGS+7,255-_CIF_FPU
 .Lload_fpu_regs_exit:
-       BR_R1USE_R14
+       BR_EX   %r14
 .Lload_fpu_regs_end:
 
 .L__critical_end:
@@ -1322,7 +1265,7 @@ cleanup_critical:
        jl      0f
        clg     %r9,BASED(.Lcleanup_table+104)  # .Lload_fpu_regs_end
        jl      .Lcleanup_load_fpu_regs
-0:     BR_R11USE_R14
+0:     BR_EX   %r14
 
        .align  8
 .Lcleanup_table:
@@ -1358,7 +1301,7 @@ cleanup_critical:
        ni      __SIE_PROG0C+3(%r9),0xfe        # no longer in SIE
        lctlg   %c1,%c1,__LC_USER_ASCE          # load primary asce
        larl    %r9,sie_exit                    # skip forward to sie_exit
-       BR_R11USE_R14
+       BR_EX   %r14
 #endif
 
 .Lcleanup_system_call:
@@ -1412,7 +1355,7 @@ cleanup_critical:
        stg     %r15,56(%r11)           # r15 stack pointer
        # set new psw address and exit
        larl    %r9,.Lsysc_do_svc
-       BR_R11USE_R14
+       BR_EX   %r14,%r11
 .Lcleanup_system_call_insn:
        .quad   system_call
        .quad   .Lsysc_stmg
@@ -1424,7 +1367,7 @@ cleanup_critical:
 
 .Lcleanup_sysc_tif:
        larl    %r9,.Lsysc_tif
-       BR_R11USE_R14
+       BR_EX   %r14,%r11
 
 .Lcleanup_sysc_restore:
        # check if stpt has been executed
@@ -1441,14 +1384,14 @@ cleanup_critical:
        mvc     0(64,%r11),__PT_R8(%r9)
        lmg     %r0,%r7,__PT_R0(%r9)
 1:     lmg     %r8,%r9,__LC_RETURN_PSW
-       BR_R11USE_R14
+       BR_EX   %r14,%r11
 .Lcleanup_sysc_restore_insn:
        .quad   .Lsysc_exit_timer
        .quad   .Lsysc_done - 4
 
 .Lcleanup_io_tif:
        larl    %r9,.Lio_tif
-       BR_R11USE_R14
+       BR_EX   %r14,%r11
 
 .Lcleanup_io_restore:
        # check if stpt has been executed
@@ -1462,7 +1405,7 @@ cleanup_critical:
        mvc     0(64,%r11),__PT_R8(%r9)
        lmg     %r0,%r7,__PT_R0(%r9)
 1:     lmg     %r8,%r9,__LC_RETURN_PSW
-       BR_R11USE_R14
+       BR_EX   %r14,%r11
 .Lcleanup_io_restore_insn:
        .quad   .Lio_exit_timer
        .quad   .Lio_done - 4
@@ -1515,17 +1458,17 @@ cleanup_critical:
        # prepare return psw
        nihh    %r8,0xfcfd              # clear irq & wait state bits
        lg      %r9,48(%r11)            # return from psw_idle
-       BR_R11USE_R14
+       BR_EX   %r14,%r11
 .Lcleanup_idle_insn:
        .quad   .Lpsw_idle_lpsw
 
 .Lcleanup_save_fpu_regs:
        larl    %r9,save_fpu_regs
-       BR_R11USE_R14
+       BR_EX   %r14,%r11
 
 .Lcleanup_load_fpu_regs:
        larl    %r9,load_fpu_regs
-       BR_R11USE_R14
+       BR_EX   %r14,%r11
 
 /*
  * Integer constants
index 94f2099bceb04cbfdc73d8f498a42e777a4b4e07..3d17c41074ca55d59fbe156c5967605912af9734 100644 (file)
@@ -176,10 +176,9 @@ void do_softirq_own_stack(void)
                new -= STACK_FRAME_OVERHEAD;
                ((struct stack_frame *) new)->back_chain = old;
                asm volatile("   la    15,0(%0)\n"
-                            "   basr  14,%2\n"
+                            "   brasl 14,__do_softirq\n"
                             "   la    15,0(%1)\n"
-                            : : "a" (new), "a" (old),
-                                "a" (__do_softirq)
+                            : : "a" (new), "a" (old)
                             : "0", "1", "2", "3", "4", "5", "14",
                               "cc", "memory" );
        } else {
index 82df7d80fab22090cb943e1d54562ee00acfaec2..27110f3294edcdf30935048d5553f712caf44116 100644 (file)
@@ -9,13 +9,17 @@
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/ftrace.h>
+#include <asm/nospec-insn.h>
 #include <asm/ptrace.h>
 #include <asm/export.h>
 
+       GEN_BR_THUNK %r1
+       GEN_BR_THUNK %r14
+
        .section .kprobes.text, "ax"
 
 ENTRY(ftrace_stub)
-       br      %r14
+       BR_EX   %r14
 
 #define STACK_FRAME_SIZE  (STACK_FRAME_OVERHEAD + __PT_SIZE)
 #define STACK_PTREGS     (STACK_FRAME_OVERHEAD)
@@ -23,7 +27,7 @@ ENTRY(ftrace_stub)
 #define STACK_PTREGS_PSW  (STACK_PTREGS + __PT_PSW)
 
 ENTRY(_mcount)
-       br      %r14
+       BR_EX   %r14
 
 EXPORT_SYMBOL(_mcount)
 
@@ -53,7 +57,7 @@ ENTRY(ftrace_caller)
 #endif
        lgr     %r3,%r14
        la      %r5,STACK_PTREGS(%r15)
-       basr    %r14,%r1
+       BASR_EX %r14,%r1
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 # The j instruction gets runtime patched to a nop instruction.
 # See ftrace_enable_ftrace_graph_caller.
@@ -68,7 +72,7 @@ ftrace_graph_caller_end:
 #endif
        lg      %r1,(STACK_PTREGS_PSW+8)(%r15)
        lmg     %r2,%r15,(STACK_PTREGS_GPRS+2*8)(%r15)
-       br      %r1
+       BR_EX   %r1
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 
@@ -81,6 +85,6 @@ ENTRY(return_to_handler)
        aghi    %r15,STACK_FRAME_OVERHEAD
        lgr     %r14,%r2
        lmg     %r2,%r5,32(%r15)
-       br      %r14
+       BR_EX   %r14
 
 #endif
index 46d49a11663f5915753c42ece6c0f56870889b80..8ad6a7128b3a5eba73345e2365613284466e7489 100644 (file)
@@ -1,7 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/module.h>
 #include <linux/device.h>
-#include <linux/cpu.h>
 #include <asm/nospec-branch.h>
 
 static int __init nobp_setup_early(char *str)
@@ -44,24 +43,6 @@ static int __init nospec_report(void)
 }
 arch_initcall(nospec_report);
 
-#ifdef CONFIG_SYSFS
-ssize_t cpu_show_spectre_v1(struct device *dev,
-                           struct device_attribute *attr, char *buf)
-{
-       return sprintf(buf, "Mitigation: __user pointer sanitization\n");
-}
-
-ssize_t cpu_show_spectre_v2(struct device *dev,
-                           struct device_attribute *attr, char *buf)
-{
-       if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
-               return sprintf(buf, "Mitigation: execute trampolines\n");
-       if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
-               return sprintf(buf, "Mitigation: limited branch prediction.\n");
-       return sprintf(buf, "Vulnerable\n");
-}
-#endif
-
 #ifdef CONFIG_EXPOLINE
 
 int nospec_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF);
@@ -112,7 +93,6 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end)
        s32 *epo;
 
        /* Second part of the instruction replace is always a nop */
-       memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x00, 0x00 }, 4);
        for (epo = start; epo < end; epo++) {
                instr = (u8 *) epo + *epo;
                if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x04)
@@ -133,18 +113,34 @@ static void __init_or_module __nospec_revert(s32 *start, s32 *end)
                        br = thunk + (*(int *)(thunk + 2)) * 2;
                else
                        continue;
-               if (br[0] != 0x07 || (br[1] & 0xf0) != 0xf0)
+               /* Check for unconditional branch 0x07f? or 0x47f???? */
+               if ((br[0] & 0xbf) != 0x07 || (br[1] & 0xf0) != 0xf0)
                        continue;
+
+               memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x07, 0x00 }, 4);
                switch (type) {
                case BRCL_EXPOLINE:
-                       /* brcl to thunk, replace with br + nop */
                        insnbuf[0] = br[0];
                        insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
+                       if (br[0] == 0x47) {
+                               /* brcl to b, replace with bc + nopr */
+                               insnbuf[2] = br[2];
+                               insnbuf[3] = br[3];
+                       } else {
+                               /* brcl to br, replace with bcr + nop */
+                       }
                        break;
                case BRASL_EXPOLINE:
-                       /* brasl to thunk, replace with basr + nop */
-                       insnbuf[0] = 0x0d;
                        insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
+                       if (br[0] == 0x47) {
+                               /* brasl to b, replace with bas + nopr */
+                               insnbuf[0] = 0x4d;
+                               insnbuf[2] = br[2];
+                               insnbuf[3] = br[3];
+                       } else {
+                               /* brasl to br, replace with basr + nop */
+                               insnbuf[0] = 0x0d;
+                       }
                        break;
                }
 
diff --git a/arch/s390/kernel/nospec-sysfs.c b/arch/s390/kernel/nospec-sysfs.c
new file mode 100644 (file)
index 0000000..8affad5
--- /dev/null
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/device.h>
+#include <linux/cpu.h>
+#include <asm/facility.h>
+#include <asm/nospec-branch.h>
+
+ssize_t cpu_show_spectre_v1(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "Mitigation: __user pointer sanitization\n");
+}
+
+ssize_t cpu_show_spectre_v2(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
+               return sprintf(buf, "Mitigation: execute trampolines\n");
+       if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
+               return sprintf(buf, "Mitigation: limited branch prediction\n");
+       return sprintf(buf, "Vulnerable\n");
+}
index 1c9ddd7aa5ec8fd32ee626d036a3c3ea6ed79362..0292d68e7dded707496b7090c9b2d7377aab8b2b 100644 (file)
@@ -753,6 +753,10 @@ static int __hw_perf_event_init(struct perf_event *event)
         */
        rate = 0;
        if (attr->freq) {
+               if (!attr->sample_freq) {
+                       err = -EINVAL;
+                       goto out;
+               }
                rate = freq_to_sample_rate(&si, attr->sample_freq);
                rate = hw_limit_rate(&si, rate);
                attr->freq = 0;
index 73cc3750f0d3414c56c464585866dbcf738d88f7..7f14adf512c6d229cd4d68dac2c51c8c3f1fe643 100644 (file)
@@ -7,8 +7,11 @@
 
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
+#include <asm/nospec-insn.h>
 #include <asm/sigp.h>
 
+       GEN_BR_THUNK %r9
+
 #
 # Issue "store status" for the current CPU to its prefix page
 # and call passed function afterwards
@@ -67,9 +70,9 @@ ENTRY(store_status)
        st      %r4,0(%r1)
        st      %r5,4(%r1)
        stg     %r2,8(%r1)
-       lgr     %r1,%r2
+       lgr     %r9,%r2
        lgr     %r2,%r3
-       br      %r1
+       BR_EX   %r9
 
        .section .bss
        .align  8
index e99187149f1717f1ec81c94ea12cc77fa964c2fd..a049a7b9d6e893801a1ecd79d9332d3faea8d0ba 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
 #include <asm/asm-offsets.h>
+#include <asm/nospec-insn.h>
 #include <asm/sigp.h>
 
 /*
@@ -24,6 +25,8 @@
  * (see below) in the resume process.
  * This function runs with disabled interrupts.
  */
+       GEN_BR_THUNK %r14
+
        .section .text
 ENTRY(swsusp_arch_suspend)
        stmg    %r6,%r15,__SF_GPRS(%r15)
@@ -103,7 +106,7 @@ ENTRY(swsusp_arch_suspend)
        spx     0x318(%r1)
        lmg     %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
        lghi    %r2,0
-       br      %r14
+       BR_EX   %r14
 
 /*
  * Restore saved memory image to correct place and restore register context.
@@ -197,11 +200,10 @@ pgm_check_entry:
        larl    %r15,init_thread_union
        ahi     %r15,1<<(PAGE_SHIFT+THREAD_SIZE_ORDER)
        larl    %r2,.Lpanic_string
-       larl    %r3,sclp_early_printk
        lghi    %r1,0
        sam31
        sigp    %r1,%r0,SIGP_SET_ARCHITECTURE
-       basr    %r14,%r3
+       brasl   %r14,sclp_early_printk
        larl    %r3,.Ldisabled_wait_31
        lpsw    0(%r3)
 4:
@@ -267,7 +269,7 @@ restore_registers:
        /* Return 0 */
        lmg     %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
        lghi    %r2,0
-       br      %r14
+       BR_EX   %r14
 
        .section .data..nosave,"aw",@progbits
        .align  8
index 495c9c4bacc7b34bcfe4d966adeb28431b1dc032..2311f15be9cf04b3bad1f766453e6ff970d53a83 100644 (file)
@@ -7,6 +7,9 @@
 
 #include <linux/linkage.h>
 #include <asm/export.h>
+#include <asm/nospec-insn.h>
+
+       GEN_BR_THUNK %r14
 
 /*
  * void *memmove(void *dest, const void *src, size_t n)
@@ -33,14 +36,14 @@ ENTRY(memmove)
 .Lmemmove_forward_remainder:
        larl    %r5,.Lmemmove_mvc
        ex      %r4,0(%r5)
-       br      %r14
+       BR_EX   %r14
 .Lmemmove_reverse:
        ic      %r0,0(%r4,%r3)
        stc     %r0,0(%r4,%r1)
        brctg   %r4,.Lmemmove_reverse
        ic      %r0,0(%r4,%r3)
        stc     %r0,0(%r4,%r1)
-       br      %r14
+       BR_EX   %r14
 .Lmemmove_mvc:
        mvc     0(1,%r1),0(%r3)
 EXPORT_SYMBOL(memmove)
@@ -77,7 +80,7 @@ ENTRY(memset)
 .Lmemset_clear_remainder:
        larl    %r3,.Lmemset_xc
        ex      %r4,0(%r3)
-       br      %r14
+       BR_EX   %r14
 .Lmemset_fill:
        cghi    %r4,1
        lgr     %r1,%r2
@@ -95,10 +98,10 @@ ENTRY(memset)
        stc     %r3,0(%r1)
        larl    %r5,.Lmemset_mvc
        ex      %r4,0(%r5)
-       br      %r14
+       BR_EX   %r14
 .Lmemset_fill_exit:
        stc     %r3,0(%r1)
-       br      %r14
+       BR_EX   %r14
 .Lmemset_xc:
        xc      0(1,%r1),0(%r1)
 .Lmemset_mvc:
@@ -121,7 +124,7 @@ ENTRY(memcpy)
 .Lmemcpy_remainder:
        larl    %r5,.Lmemcpy_mvc
        ex      %r4,0(%r5)
-       br      %r14
+       BR_EX   %r14
 .Lmemcpy_loop:
        mvc     0(256,%r1),0(%r3)
        la      %r1,256(%r1)
@@ -159,10 +162,10 @@ ENTRY(__memset\bits)
        \insn   %r3,0(%r1)
        larl    %r5,.L__memset_mvc\bits
        ex      %r4,0(%r5)
-       br      %r14
+       BR_EX   %r14
 .L__memset_exit\bits:
        \insn   %r3,0(%r2)
-       br      %r14
+       BR_EX   %r14
 .L__memset_mvc\bits:
        mvc     \bytes(1,%r1),0(%r1)
 .endm
index 25bb4643c4f46cc3bcbf904e9fc257a3145f4221..9f794869c1b090a9a6589d573e77739562265cf5 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/nospec-insn.h>
 #include "bpf_jit.h"
 
 /*
@@ -54,7 +55,7 @@ ENTRY(sk_load_##NAME##_pos);                                          \
        clg     %r3,STK_OFF_HLEN(%r15); /* Offset + SIZE > hlen? */     \
        jh      sk_load_##NAME##_slow;                                  \
        LOAD    %r14,-SIZE(%r3,%r12);   /* Get data from skb */         \
-       b       OFF_OK(%r6);            /* Return */                    \
+       B_EX    OFF_OK,%r6;             /* Return */                    \
                                                                        \
 sk_load_##NAME##_slow:;                                                        \
        lgr     %r2,%r7;                /* Arg1 = skb pointer */        \
@@ -64,11 +65,14 @@ sk_load_##NAME##_slow:;                                                     \
        brasl   %r14,skb_copy_bits;     /* Get data from skb */         \
        LOAD    %r14,STK_OFF_TMP(%r15); /* Load from temp bufffer */    \
        ltgr    %r2,%r2;                /* Set cc to (%r2 != 0) */      \
-       br      %r6;                    /* Return */
+       BR_EX   %r6;                    /* Return */
 
 sk_load_common(word, 4, llgf)  /* r14 = *(u32 *) (skb->data+offset) */
 sk_load_common(half, 2, llgh)  /* r14 = *(u16 *) (skb->data+offset) */
 
+       GEN_BR_THUNK %r6
+       GEN_B_THUNK OFF_OK,%r6
+
 /*
  * Load 1 byte from SKB (optimized version)
  */
@@ -80,7 +84,7 @@ ENTRY(sk_load_byte_pos)
        clg     %r3,STK_OFF_HLEN(%r15)  # Offset >= hlen?
        jnl     sk_load_byte_slow
        llgc    %r14,0(%r3,%r12)        # Get byte from skb
-       b       OFF_OK(%r6)             # Return OK
+       B_EX    OFF_OK,%r6              # Return OK
 
 sk_load_byte_slow:
        lgr     %r2,%r7                 # Arg1 = skb pointer
@@ -90,7 +94,7 @@ sk_load_byte_slow:
        brasl   %r14,skb_copy_bits      # Get data from skb
        llgc    %r14,STK_OFF_TMP(%r15)  # Load result from temp buffer
        ltgr    %r2,%r2                 # Set cc to (%r2 != 0)
-       br      %r6                     # Return cc
+       BR_EX   %r6                     # Return cc
 
 #define sk_negative_common(NAME, SIZE, LOAD)                           \
 sk_load_##NAME##_slow_neg:;                                            \
@@ -104,7 +108,7 @@ sk_load_##NAME##_slow_neg:;                                         \
        jz      bpf_error;                                              \
        LOAD    %r14,0(%r2);            /* Get data from pointer */     \
        xr      %r3,%r3;                /* Set cc to zero */            \
-       br      %r6;                    /* Return cc */
+       BR_EX   %r6;                    /* Return cc */
 
 sk_negative_common(word, 4, llgf)
 sk_negative_common(half, 2, llgh)
@@ -113,4 +117,4 @@ sk_negative_common(byte, 1, llgc)
 bpf_error:
 # force a return 0 from jit handler
        ltgr    %r15,%r15       # Set condition code
-       br      %r6
+       BR_EX   %r6
index 78a19c93b3802ff48b4c27a90d6428100fc5566f..dd2bcf0e7d00d45406c83e1254879e4f16db36fb 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/bpf.h>
 #include <asm/cacheflush.h>
 #include <asm/dis.h>
+#include <asm/facility.h>
+#include <asm/nospec-branch.h>
 #include <asm/set_memory.h>
 #include "bpf_jit.h"
 
@@ -41,6 +43,8 @@ struct bpf_jit {
        int base_ip;            /* Base address for literal pool */
        int ret0_ip;            /* Address of return 0 */
        int exit_ip;            /* Address of exit */
+       int r1_thunk_ip;        /* Address of expoline thunk for 'br %r1' */
+       int r14_thunk_ip;       /* Address of expoline thunk for 'br %r14' */
        int tail_call_start;    /* Tail call start offset */
        int labels[1];          /* Labels for local jumps */
 };
@@ -250,6 +254,19 @@ static inline void reg_set_seen(struct bpf_jit *jit, u32 b1)
        REG_SET_SEEN(b2);                                       \
 })
 
+#define EMIT6_PCREL_RILB(op, b, target)                                \
+({                                                             \
+       int rel = (target - jit->prg) / 2;                      \
+       _EMIT6(op | reg_high(b) << 16 | rel >> 16, rel & 0xffff);       \
+       REG_SET_SEEN(b);                                        \
+})
+
+#define EMIT6_PCREL_RIL(op, target)                            \
+({                                                             \
+       int rel = (target - jit->prg) / 2;                      \
+       _EMIT6(op | rel >> 16, rel & 0xffff);                   \
+})
+
 #define _EMIT6_IMM(op, imm)                                    \
 ({                                                             \
        unsigned int __imm = (imm);                             \
@@ -469,8 +486,45 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth)
        EMIT4(0xb9040000, REG_2, BPF_REG_0);
        /* Restore registers */
        save_restore_regs(jit, REGS_RESTORE, stack_depth);
+       if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) {
+               jit->r14_thunk_ip = jit->prg;
+               /* Generate __s390_indirect_jump_r14 thunk */
+               if (test_facility(35)) {
+                       /* exrl %r0,.+10 */
+                       EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10);
+               } else {
+                       /* larl %r1,.+14 */
+                       EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14);
+                       /* ex 0,0(%r1) */
+                       EMIT4_DISP(0x44000000, REG_0, REG_1, 0);
+               }
+               /* j . */
+               EMIT4_PCREL(0xa7f40000, 0);
+       }
        /* br %r14 */
        _EMIT2(0x07fe);
+
+       if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable &&
+           (jit->seen & SEEN_FUNC)) {
+               jit->r1_thunk_ip = jit->prg;
+               /* Generate __s390_indirect_jump_r1 thunk */
+               if (test_facility(35)) {
+                       /* exrl %r0,.+10 */
+                       EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10);
+                       /* j . */
+                       EMIT4_PCREL(0xa7f40000, 0);
+                       /* br %r1 */
+                       _EMIT2(0x07f1);
+               } else {
+                       /* larl %r1,.+14 */
+                       EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14);
+                       /* ex 0,S390_lowcore.br_r1_tampoline */
+                       EMIT4_DISP(0x44000000, REG_0, REG_0,
+                                  offsetof(struct lowcore, br_r1_trampoline));
+                       /* j . */
+                       EMIT4_PCREL(0xa7f40000, 0);
+               }
+       }
 }
 
 /*
@@ -966,8 +1020,13 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i
                /* lg %w1,<d(imm)>(%l) */
                EMIT6_DISP_LH(0xe3000000, 0x0004, REG_W1, REG_0, REG_L,
                              EMIT_CONST_U64(func));
-               /* basr %r14,%w1 */
-               EMIT2(0x0d00, REG_14, REG_W1);
+               if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) {
+                       /* brasl %r14,__s390_indirect_jump_r1 */
+                       EMIT6_PCREL_RILB(0xc0050000, REG_14, jit->r1_thunk_ip);
+               } else {
+                       /* basr %r14,%w1 */
+                       EMIT2(0x0d00, REG_14, REG_W1);
+               }
                /* lgr %b0,%r2: load return value into %b0 */
                EMIT4(0xb9040000, BPF_REG_0, REG_2);
                if ((jit->seen & SEEN_SKB) &&
index 97fe2931647648329c1b4b0bb88e8c3ac81e885f..1851eaeee13179d24dd1c362aa4c4b3e4f6c38df 100644 (file)
@@ -9,6 +9,7 @@ config SUPERH
        select HAVE_IDE if HAS_IOPORT_MAP
        select HAVE_MEMBLOCK
        select HAVE_MEMBLOCK_NODE_MAP
+       select NO_BOOTMEM
        select ARCH_DISCARD_MEMBLOCK
        select HAVE_OPROFILE
        select HAVE_GENERIC_DMA_COHERENT
index 4205f6d42b6938cb5a65946932672c3daf19abd4..a5bd03642678906a21e1d5fc8f853b4264bfd2e8 100644 (file)
@@ -43,7 +43,11 @@ void __ref cpu_probe(void)
 #endif
 
 #if defined(CONFIG_CPU_J2)
+#if defined(CONFIG_SMP)
        unsigned cpu = hard_smp_processor_id();
+#else
+       unsigned cpu = 0;
+#endif
        if (cpu == 0) of_scan_flat_dt(scan_cache, NULL);
        if (j2_ccr_base) __raw_writel(0x80000303, j2_ccr_base + 4*cpu);
        if (cpu != 0) return;
index d34e998b809f3461be121935359ba26e5613b8c7..c286cf5da6e770f5b7cbadcb4f815f986822e443 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/initrd.h>
-#include <linux/bootmem.h>
 #include <linux/console.h>
 #include <linux/root_dev.h>
 #include <linux/utsname.h>
index 8ce98691d82257fb61a99c3881506bb790e60217..f1b44697ad680253f2fe0a7236887a17eac9bae4 100644 (file)
@@ -59,7 +59,9 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size,
 
        split_page(pfn_to_page(virt_to_phys(ret) >> PAGE_SHIFT), order);
 
-       *dma_handle = virt_to_phys(ret) - PFN_PHYS(dev->dma_pfn_offset);
+       *dma_handle = virt_to_phys(ret);
+       if (!WARN_ON(!dev))
+               *dma_handle -= PFN_PHYS(dev->dma_pfn_offset);
 
        return ret_nocache;
 }
@@ -69,9 +71,12 @@ void dma_generic_free_coherent(struct device *dev, size_t size,
                               unsigned long attrs)
 {
        int order = get_order(size);
-       unsigned long pfn = (dma_handle >> PAGE_SHIFT) + dev->dma_pfn_offset;
+       unsigned long pfn = dma_handle >> PAGE_SHIFT;
        int k;
 
+       if (!WARN_ON(!dev))
+               pfn += dev->dma_pfn_offset;
+
        for (k = 0; k < (1 << order); k++)
                __free_pages(pfn_to_page(pfn + k), 0);
 
@@ -143,7 +148,7 @@ int __init platform_resource_setup_memory(struct platform_device *pdev,
        if (!memsize)
                return 0;
 
-       buf = dma_alloc_coherent(NULL, memsize, &dma_handle, GFP_KERNEL);
+       buf = dma_alloc_coherent(&pdev->dev, memsize, &dma_handle, GFP_KERNEL);
        if (!buf) {
                pr_warning("%s: unable to allocate memory\n", name);
                return -ENOMEM;
index ce0bbaa7e40403b37d0d6dbdf107693dd24a2613..4034035fbede8ae1f4101358b6703f28462f21d4 100644 (file)
@@ -211,59 +211,15 @@ void __init allocate_pgdat(unsigned int nid)
 
        NODE_DATA(nid) = __va(phys);
        memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
-
-       NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
 #endif
 
        NODE_DATA(nid)->node_start_pfn = start_pfn;
        NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
 }
 
-static void __init bootmem_init_one_node(unsigned int nid)
-{
-       unsigned long total_pages, paddr;
-       unsigned long end_pfn;
-       struct pglist_data *p;
-
-       p = NODE_DATA(nid);
-
-       /* Nothing to do.. */
-       if (!p->node_spanned_pages)
-               return;
-
-       end_pfn = pgdat_end_pfn(p);
-
-       total_pages = bootmem_bootmap_pages(p->node_spanned_pages);
-
-       paddr = memblock_alloc(total_pages << PAGE_SHIFT, PAGE_SIZE);
-       if (!paddr)
-               panic("Can't allocate bootmap for nid[%d]\n", nid);
-
-       init_bootmem_node(p, paddr >> PAGE_SHIFT, p->node_start_pfn, end_pfn);
-
-       free_bootmem_with_active_regions(nid, end_pfn);
-
-       /*
-        * XXX Handle initial reservations for the system memory node
-        * only for the moment, we'll refactor this later for handling
-        * reservations in other nodes.
-        */
-       if (nid == 0) {
-               struct memblock_region *reg;
-
-               /* Reserve the sections we're already using. */
-               for_each_memblock(reserved, reg) {
-                       reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
-               }
-       }
-
-       sparse_memory_present_with_active_regions(nid);
-}
-
 static void __init do_init_bootmem(void)
 {
        struct memblock_region *reg;
-       int i;
 
        /* Add active regions with valid PFNs. */
        for_each_memblock(memory, reg) {
@@ -279,9 +235,12 @@ static void __init do_init_bootmem(void)
 
        plat_mem_setup();
 
-       for_each_online_node(i)
-               bootmem_init_one_node(i);
+       for_each_memblock(memory, reg) {
+               int nid = memblock_get_region_node(reg);
 
+               memory_present(nid, memblock_region_memory_base_pfn(reg),
+                       memblock_region_memory_end_pfn(reg));
+       }
        sparse_init();
 }
 
@@ -322,7 +281,6 @@ void __init paging_init(void)
 {
        unsigned long max_zone_pfns[MAX_NR_ZONES];
        unsigned long vaddr, end;
-       int nid;
 
        sh_mv.mv_mem_init();
 
@@ -377,21 +335,7 @@ void __init paging_init(void)
        kmap_coherent_init();
 
        memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
-
-       for_each_online_node(nid) {
-               pg_data_t *pgdat = NODE_DATA(nid);
-               unsigned long low, start_pfn;
-
-               start_pfn = pgdat->bdata->node_min_pfn;
-               low = pgdat->bdata->node_low_pfn;
-
-               if (max_zone_pfns[ZONE_NORMAL] < low)
-                       max_zone_pfns[ZONE_NORMAL] = low;
-
-               printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n",
-                      nid, start_pfn, low);
-       }
-
+       max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
        free_area_init_nodes(max_zone_pfns);
 }
 
index 05713d190247c6842907a35c8f72b856ab1ce2dd..830e8b3684e4248417464934b8634e4d303f4a16 100644 (file)
@@ -8,7 +8,6 @@
  * for more details.
  */
 #include <linux/module.h>
-#include <linux/bootmem.h>
 #include <linux/memblock.h>
 #include <linux/mm.h>
 #include <linux/numa.h>
@@ -26,9 +25,7 @@ EXPORT_SYMBOL_GPL(node_data);
  */
 void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
 {
-       unsigned long bootmap_pages;
        unsigned long start_pfn, end_pfn;
-       unsigned long bootmem_paddr;
 
        /* Don't allow bogus node assignment */
        BUG_ON(nid >= MAX_NUMNODES || nid <= 0);
@@ -48,25 +45,9 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
                                             SMP_CACHE_BYTES, end));
        memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
 
-       NODE_DATA(nid)->bdata = &bootmem_node_data[nid];
        NODE_DATA(nid)->node_start_pfn = start_pfn;
        NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
 
-       /* Node-local bootmap */
-       bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
-       bootmem_paddr = memblock_alloc_base(bootmap_pages << PAGE_SHIFT,
-                                      PAGE_SIZE, end);
-       init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
-                         start_pfn, end_pfn);
-
-       free_bootmem_with_active_regions(nid, end_pfn);
-
-       /* Reserve the pgdat and bootmap space with the bootmem allocator */
-       reserve_bootmem_node(NODE_DATA(nid), start_pfn << PAGE_SHIFT,
-                            sizeof(struct pglist_data), BOOTMEM_DEFAULT);
-       reserve_bootmem_node(NODE_DATA(nid), bootmem_paddr,
-                            bootmap_pages << PAGE_SHIFT, BOOTMEM_DEFAULT);
-
        /* It's up */
        node_set_online(nid);
 
diff --git a/arch/x86/entry/vdso/vdso32/vdso-fakesections.c b/arch/x86/entry/vdso/vdso32/vdso-fakesections.c
deleted file mode 100644 (file)
index 541468e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include "../vdso-fakesections.c"
index a6006e7bb729a808d5a58829bb2524db98135c2f..45b2b1c93d042231979e621970167f583cb444f5 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/cpu.h>
 #include <linux/bitops.h>
 #include <linux/device.h>
+#include <linux/nospec.h>
 
 #include <asm/apic.h>
 #include <asm/stacktrace.h>
@@ -304,17 +305,20 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event *event)
 
        config = attr->config;
 
-       cache_type = (config >>  0) & 0xff;
+       cache_type = (config >> 0) & 0xff;
        if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
                return -EINVAL;
+       cache_type = array_index_nospec(cache_type, PERF_COUNT_HW_CACHE_MAX);
 
        cache_op = (config >>  8) & 0xff;
        if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
                return -EINVAL;
+       cache_op = array_index_nospec(cache_op, PERF_COUNT_HW_CACHE_OP_MAX);
 
        cache_result = (config >> 16) & 0xff;
        if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
                return -EINVAL;
+       cache_result = array_index_nospec(cache_result, PERF_COUNT_HW_CACHE_RESULT_MAX);
 
        val = hw_cache_event_ids[cache_type][cache_op][cache_result];
 
@@ -421,6 +425,8 @@ int x86_setup_perfctr(struct perf_event *event)
        if (attr->config >= x86_pmu.max_events)
                return -EINVAL;
 
+       attr->config = array_index_nospec((unsigned long)attr->config, x86_pmu.max_events);
+
        /*
         * The generic map:
         */
index 9aca448bb8e63323738147cbc1c6e95d62ecdd58..9f8084f18d58e440931f593d42cc825bbc00cfb8 100644 (file)
@@ -92,6 +92,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/perf_event.h>
+#include <linux/nospec.h>
 #include <asm/cpu_device_id.h>
 #include <asm/intel-family.h>
 #include "../perf_event.h"
@@ -302,6 +303,7 @@ static int cstate_pmu_event_init(struct perf_event *event)
        } else if (event->pmu == &cstate_pkg_pmu) {
                if (cfg >= PERF_CSTATE_PKG_EVENT_MAX)
                        return -EINVAL;
+               cfg = array_index_nospec((unsigned long)cfg, PERF_CSTATE_PKG_EVENT_MAX);
                if (!pkg_msr[cfg].attr)
                        return -EINVAL;
                event->hw.event_base = pkg_msr[cfg].msr;
index e7edf19e64c27c5ecb5eacfb06d139ea28b290f4..b4771a6ddbc1b6686549ee306d3299d68a8b2e3e 100644 (file)
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/perf_event.h>
+#include <linux/nospec.h>
 #include <asm/intel-family.h>
 
 enum perf_msr_id {
@@ -158,9 +159,6 @@ static int msr_event_init(struct perf_event *event)
        if (event->attr.type != event->pmu->type)
                return -ENOENT;
 
-       if (cfg >= PERF_MSR_EVENT_MAX)
-               return -EINVAL;
-
        /* unsupported modes and filters */
        if (event->attr.exclude_user   ||
            event->attr.exclude_kernel ||
@@ -171,6 +169,11 @@ static int msr_event_init(struct perf_event *event)
            event->attr.sample_period) /* no sampling */
                return -EINVAL;
 
+       if (cfg >= PERF_MSR_EVENT_MAX)
+               return -EINVAL;
+
+       cfg = array_index_nospec((unsigned long)cfg, PERF_MSR_EVENT_MAX);
+
        if (!msr[cfg].attr)
                return -EINVAL;
 
index 4c851ebb3cebd4654f9dabed1e9c19520b072c0d..0ede697c396119be61eb223a40607ff6e6e985ef 100644 (file)
@@ -29,7 +29,7 @@
 #define KVM_FEATURE_PV_TLB_FLUSH       9
 #define KVM_FEATURE_ASYNC_PF_VMEXIT    10
 
-#define KVM_HINTS_DEDICATED      0
+#define KVM_HINTS_REALTIME      0
 
 /* The last 8 bits are used to indicate how to interpret the flags field
  * in pvclock structure. If no bits are set, all flags are ignored.
index c88e0b127810f22b15b53eb150d11e9584201885..b481b95bd8f6b9e439c5d72e42af21b18d250af4 100644 (file)
 #include <asm/amd_nb.h>
 
 #define PCI_DEVICE_ID_AMD_17H_ROOT     0x1450
+#define PCI_DEVICE_ID_AMD_17H_M10H_ROOT        0x15d0
 #define PCI_DEVICE_ID_AMD_17H_DF_F3    0x1463
 #define PCI_DEVICE_ID_AMD_17H_DF_F4    0x1464
+#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F3 0x15eb
+#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F4 0x15ec
 
 /* Protect the PCI config register pairs used for SMN and DF indirect access. */
 static DEFINE_MUTEX(smn_mutex);
@@ -24,6 +27,7 @@ static u32 *flush_words;
 
 static const struct pci_device_id amd_root_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_ROOT) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_ROOT) },
        {}
 };
 
@@ -39,6 +43,7 @@ const struct pci_device_id amd_nb_misc_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
        {}
 };
@@ -51,6 +56,7 @@ static const struct pci_device_id amd_nb_link_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F4) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F4) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) },
        {}
 };
index 8a5b185735e1c5a49a1eafd19b74316d291efb7a..ce243f7d2d4e0879c9cbff297ff112e236a6802c 100644 (file)
@@ -848,6 +848,11 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
                c->x86_power = edx;
        }
 
+       if (c->extended_cpuid_level >= 0x80000008) {
+               cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
+               c->x86_capability[CPUID_8000_0008_EBX] = ebx;
+       }
+
        if (c->extended_cpuid_level >= 0x8000000a)
                c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a);
 
@@ -871,7 +876,6 @@ static void get_cpu_address_sizes(struct cpuinfo_x86 *c)
 
                c->x86_virt_bits = (eax >> 8) & 0xff;
                c->x86_phys_bits = eax & 0xff;
-               c->x86_capability[CPUID_8000_0008_EBX] = ebx;
        }
 #ifdef CONFIG_X86_32
        else if (cpu_has(c, X86_FEATURE_PAE) || cpu_has(c, X86_FEATURE_PSE36))
index f7666eef4a879b8e4b4da6a33ad941bc371babd4..c8e038800591674021c84bc66cae2fe4f02fcfc9 100644 (file)
@@ -94,6 +94,11 @@ static struct smca_bank_name smca_names[] = {
        [SMCA_SMU]      = { "smu",              "System Management Unit" },
 };
 
+static u32 smca_bank_addrs[MAX_NR_BANKS][NR_BLOCKS] __ro_after_init =
+{
+       [0 ... MAX_NR_BANKS - 1] = { [0 ... NR_BLOCKS - 1] = -1 }
+};
+
 const char *smca_get_name(enum smca_bank_types t)
 {
        if (t >= N_SMCA_BANK_TYPES)
@@ -443,20 +448,26 @@ static u32 smca_get_block_address(unsigned int cpu, unsigned int bank,
        if (!block)
                return MSR_AMD64_SMCA_MCx_MISC(bank);
 
+       /* Check our cache first: */
+       if (smca_bank_addrs[bank][block] != -1)
+               return smca_bank_addrs[bank][block];
+
        /*
         * For SMCA enabled processors, BLKPTR field of the first MISC register
         * (MCx_MISC0) indicates presence of additional MISC regs set (MISC1-4).
         */
        if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_CONFIG(bank), &low, &high))
-               return addr;
+               goto out;
 
        if (!(low & MCI_CONFIG_MCAX))
-               return addr;
+               goto out;
 
        if (!rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_MISC(bank), &low, &high) &&
            (low & MASK_BLKPTR_LO))
-               return MSR_AMD64_SMCA_MCx_MISCy(bank, block - 1);
+               addr = MSR_AMD64_SMCA_MCx_MISCy(bank, block - 1);
 
+out:
+       smca_bank_addrs[bank][block] = addr;
        return addr;
 }
 
@@ -468,18 +479,6 @@ static u32 get_block_address(unsigned int cpu, u32 current_addr, u32 low, u32 hi
        if ((bank >= mca_cfg.banks) || (block >= NR_BLOCKS))
                return addr;
 
-       /* Get address from already initialized block. */
-       if (per_cpu(threshold_banks, cpu)) {
-               struct threshold_bank *bankp = per_cpu(threshold_banks, cpu)[bank];
-
-               if (bankp && bankp->blocks) {
-                       struct threshold_block *blockp = &bankp->blocks[block];
-
-                       if (blockp)
-                               return blockp->address;
-               }
-       }
-
        if (mce_flags.smca)
                return smca_get_block_address(cpu, bank, block);
 
index 7867417cfaff2b59ee2c2531072a632a9e810f41..5b2300b818af9333f8d57f6b082f426b8556b606 100644 (file)
@@ -457,7 +457,7 @@ static void __init sev_map_percpu_data(void)
 static void __init kvm_smp_prepare_cpus(unsigned int max_cpus)
 {
        native_smp_prepare_cpus(max_cpus);
-       if (kvm_para_has_hint(KVM_HINTS_DEDICATED))
+       if (kvm_para_has_hint(KVM_HINTS_REALTIME))
                static_branch_disable(&virt_spin_lock_key);
 }
 
@@ -553,7 +553,7 @@ static void __init kvm_guest_init(void)
        }
 
        if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
-           !kvm_para_has_hint(KVM_HINTS_DEDICATED) &&
+           !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
            kvm_para_has_feature(KVM_FEATURE_STEAL_TIME))
                pv_mmu_ops.flush_tlb_others = kvm_flush_tlb_others;
 
@@ -649,7 +649,7 @@ static __init int kvm_setup_pv_tlb_flush(void)
        int cpu;
 
        if (kvm_para_has_feature(KVM_FEATURE_PV_TLB_FLUSH) &&
-           !kvm_para_has_hint(KVM_HINTS_DEDICATED) &&
+           !kvm_para_has_hint(KVM_HINTS_REALTIME) &&
            kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) {
                for_each_possible_cpu(cpu) {
                        zalloc_cpumask_var_node(per_cpu_ptr(&__pv_tlb_mask, cpu),
@@ -745,7 +745,7 @@ void __init kvm_spinlock_init(void)
        if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT))
                return;
 
-       if (kvm_para_has_hint(KVM_HINTS_DEDICATED))
+       if (kvm_para_has_hint(KVM_HINTS_REALTIME))
                return;
 
        __pv_init_lock_hash();
index 91e6da48cbb673a8fc373750d59f776e57c20ae4..74392d9d51e0a799a7f4fcb974a55e7989ed400a 100644 (file)
@@ -1067,6 +1067,7 @@ static struct clocksource clocksource_tsc_early = {
        .resume                 = tsc_resume,
        .mark_unstable          = tsc_cs_mark_unstable,
        .tick_stable            = tsc_cs_tick_stable,
+       .list                   = LIST_HEAD_INIT(clocksource_tsc_early.list),
 };
 
 /*
@@ -1086,6 +1087,7 @@ static struct clocksource clocksource_tsc = {
        .resume                 = tsc_resume,
        .mark_unstable          = tsc_cs_mark_unstable,
        .tick_stable            = tsc_cs_tick_stable,
+       .list                   = LIST_HEAD_INIT(clocksource_tsc.list),
 };
 
 void mark_tsc_unstable(char *reason)
@@ -1098,13 +1100,9 @@ void mark_tsc_unstable(char *reason)
                clear_sched_clock_stable();
        disable_sched_clock_irqtime();
        pr_info("Marking TSC unstable due to %s\n", reason);
-       /* Change only the rating, when not registered */
-       if (clocksource_tsc.mult) {
-               clocksource_mark_unstable(&clocksource_tsc);
-       } else {
-               clocksource_tsc.flags |= CLOCK_SOURCE_UNSTABLE;
-               clocksource_tsc.rating = 0;
-       }
+
+       clocksource_mark_unstable(&clocksource_tsc_early);
+       clocksource_mark_unstable(&clocksource_tsc);
 }
 
 EXPORT_SYMBOL_GPL(mark_tsc_unstable);
@@ -1244,7 +1242,7 @@ static void tsc_refine_calibration_work(struct work_struct *work)
 
        /* Don't bother refining TSC on unstable systems */
        if (tsc_unstable)
-               return;
+               goto unreg;
 
        /*
         * Since the work is started early in boot, we may be
@@ -1297,11 +1295,12 @@ static void tsc_refine_calibration_work(struct work_struct *work)
 
 out:
        if (tsc_unstable)
-               return;
+               goto unreg;
 
        if (boot_cpu_has(X86_FEATURE_ART))
                art_related_clocksource = &clocksource_tsc;
        clocksource_register_khz(&clocksource_tsc, tsc_khz);
+unreg:
        clocksource_unregister(&clocksource_tsc_early);
 }
 
@@ -1311,8 +1310,8 @@ static int __init init_tsc_clocksource(void)
        if (!boot_cpu_has(X86_FEATURE_TSC) || tsc_disabled > 0 || !tsc_khz)
                return 0;
 
-       if (check_tsc_unstable())
-               return 0;
+       if (tsc_unstable)
+               goto unreg;
 
        if (tsc_clocksource_reliable)
                clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
@@ -1328,6 +1327,7 @@ static int __init init_tsc_clocksource(void)
                if (boot_cpu_has(X86_FEATURE_ART))
                        art_related_clocksource = &clocksource_tsc;
                clocksource_register_khz(&clocksource_tsc, tsc_khz);
+unreg:
                clocksource_unregister(&clocksource_tsc_early);
                return 0;
        }
index 98618e397342297cdff01a94975147ee543419c0..5708e951a5c69664895a7b9a21ffe3c1bdc669bb 100644 (file)
@@ -1265,7 +1265,7 @@ static int kvm_hv_hypercall_complete_userspace(struct kvm_vcpu *vcpu)
        struct kvm_run *run = vcpu->run;
 
        kvm_hv_hypercall_set_result(vcpu, run->hyperv.u.hcall.result);
-       return 1;
+       return kvm_skip_emulated_instruction(vcpu);
 }
 
 static u16 kvm_hvcall_signal_event(struct kvm_vcpu *vcpu, bool fast, u64 param)
@@ -1296,8 +1296,10 @@ static u16 kvm_hvcall_signal_event(struct kvm_vcpu *vcpu, bool fast, u64 param)
        if (param & ~KVM_HYPERV_CONN_ID_MASK)
                return HV_STATUS_INVALID_HYPERCALL_INPUT;
 
-       /* conn_to_evt is protected by vcpu->kvm->srcu */
+       /* the eventfd is protected by vcpu->kvm->srcu, but conn_to_evt isn't */
+       rcu_read_lock();
        eventfd = idr_find(&vcpu->kvm->arch.hyperv.conn_to_evt, param);
+       rcu_read_unlock();
        if (!eventfd)
                return HV_STATUS_INVALID_PORT_ID;
 
index 70dcb554802289910382762f44e7a20b07d3317a..b74c9c1405b9978331653daa9093e95c36be0252 100644 (file)
@@ -1463,23 +1463,6 @@ static void start_sw_tscdeadline(struct kvm_lapic *apic)
        local_irq_restore(flags);
 }
 
-static void start_sw_period(struct kvm_lapic *apic)
-{
-       if (!apic->lapic_timer.period)
-               return;
-
-       if (apic_lvtt_oneshot(apic) &&
-           ktime_after(ktime_get(),
-                       apic->lapic_timer.target_expiration)) {
-               apic_timer_expired(apic);
-               return;
-       }
-
-       hrtimer_start(&apic->lapic_timer.timer,
-               apic->lapic_timer.target_expiration,
-               HRTIMER_MODE_ABS_PINNED);
-}
-
 static void update_target_expiration(struct kvm_lapic *apic, uint32_t old_divisor)
 {
        ktime_t now, remaining;
@@ -1546,6 +1529,26 @@ static void advance_periodic_target_expiration(struct kvm_lapic *apic)
                                apic->lapic_timer.period);
 }
 
+static void start_sw_period(struct kvm_lapic *apic)
+{
+       if (!apic->lapic_timer.period)
+               return;
+
+       if (ktime_after(ktime_get(),
+                       apic->lapic_timer.target_expiration)) {
+               apic_timer_expired(apic);
+
+               if (apic_lvtt_oneshot(apic))
+                       return;
+
+               advance_periodic_target_expiration(apic);
+       }
+
+       hrtimer_start(&apic->lapic_timer.timer,
+               apic->lapic_timer.target_expiration,
+               HRTIMER_MODE_ABS_PINNED);
+}
+
 bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu)
 {
        if (!lapic_in_kernel(vcpu))
index c7668806163fd5ac493f59b6d9f08823828c7758..3f1696570b41475848ae7684565da935888e6363 100644 (file)
@@ -1494,6 +1494,12 @@ static inline bool cpu_has_vmx_vmfunc(void)
                SECONDARY_EXEC_ENABLE_VMFUNC;
 }
 
+static bool vmx_umip_emulated(void)
+{
+       return vmcs_config.cpu_based_2nd_exec_ctrl &
+               SECONDARY_EXEC_DESC;
+}
+
 static inline bool report_flexpriority(void)
 {
        return flexpriority_enabled;
@@ -4761,14 +4767,16 @@ static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
        else
                hw_cr4 |= KVM_PMODE_VM_CR4_ALWAYS_ON;
 
-       if ((cr4 & X86_CR4_UMIP) && !boot_cpu_has(X86_FEATURE_UMIP)) {
-               vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
-                             SECONDARY_EXEC_DESC);
-               hw_cr4 &= ~X86_CR4_UMIP;
-       } else if (!is_guest_mode(vcpu) ||
-                  !nested_cpu_has2(get_vmcs12(vcpu), SECONDARY_EXEC_DESC))
-               vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL,
+       if (!boot_cpu_has(X86_FEATURE_UMIP) && vmx_umip_emulated()) {
+               if (cr4 & X86_CR4_UMIP) {
+                       vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
                                SECONDARY_EXEC_DESC);
+                       hw_cr4 &= ~X86_CR4_UMIP;
+               } else if (!is_guest_mode(vcpu) ||
+                       !nested_cpu_has2(get_vmcs12(vcpu), SECONDARY_EXEC_DESC))
+                       vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL,
+                                       SECONDARY_EXEC_DESC);
+       }
 
        if (cr4 & X86_CR4_VMXE) {
                /*
@@ -9497,12 +9505,6 @@ static bool vmx_xsaves_supported(void)
                SECONDARY_EXEC_XSAVES;
 }
 
-static bool vmx_umip_emulated(void)
-{
-       return vmcs_config.cpu_based_2nd_exec_ctrl &
-               SECONDARY_EXEC_DESC;
-}
-
 static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
 {
        u32 exit_intr_info;
index 51ecd381793b4f281563779b97a04e5063572fdf..59371de5d722d9687f72e39bd32161ddd75fa04d 100644 (file)
@@ -114,7 +114,7 @@ module_param(ignore_msrs, bool, S_IRUGO | S_IWUSR);
 static bool __read_mostly report_ignored_msrs = true;
 module_param(report_ignored_msrs, bool, S_IRUGO | S_IWUSR);
 
-unsigned int min_timer_period_us = 500;
+unsigned int min_timer_period_us = 200;
 module_param(min_timer_period_us, uint, S_IRUGO | S_IWUSR);
 
 static bool __read_mostly kvmclock_periodic_sync = true;
@@ -843,7 +843,10 @@ EXPORT_SYMBOL_GPL(kvm_set_cr4);
 int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
 #ifdef CONFIG_X86_64
-       cr3 &= ~CR3_PCID_INVD;
+       bool pcid_enabled = kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE);
+
+       if (pcid_enabled)
+               cr3 &= ~CR3_PCID_INVD;
 #endif
 
        if (cr3 == kvm_read_cr3(vcpu) && !pdptrs_changed(vcpu)) {
@@ -6671,12 +6674,13 @@ void kvm_vcpu_deactivate_apicv(struct kvm_vcpu *vcpu)
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
 {
        unsigned long nr, a0, a1, a2, a3, ret;
-       int op_64_bit, r;
-
-       r = kvm_skip_emulated_instruction(vcpu);
+       int op_64_bit;
 
-       if (kvm_hv_hypercall_enabled(vcpu->kvm))
-               return kvm_hv_hypercall(vcpu);
+       if (kvm_hv_hypercall_enabled(vcpu->kvm)) {
+               if (!kvm_hv_hypercall(vcpu))
+                       return 0;
+               goto out;
+       }
 
        nr = kvm_register_read(vcpu, VCPU_REGS_RAX);
        a0 = kvm_register_read(vcpu, VCPU_REGS_RBX);
@@ -6697,7 +6701,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
 
        if (kvm_x86_ops->get_cpl(vcpu) != 0) {
                ret = -KVM_EPERM;
-               goto out;
+               goto out_error;
        }
 
        switch (nr) {
@@ -6717,12 +6721,14 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
                ret = -KVM_ENOSYS;
                break;
        }
-out:
+out_error:
        if (!op_64_bit)
                ret = (u32)ret;
        kvm_register_write(vcpu, VCPU_REGS_RAX, ret);
+
+out:
        ++vcpu->stat.hypercalls;
-       return r;
+       return kvm_skip_emulated_instruction(vcpu);
 }
 EXPORT_SYMBOL_GPL(kvm_emulate_hypercall);
 
index 8268987010458489b386da80c09ed5164fff8b77..19c1ff54238758b34ad1ce828667528cb7ea7418 100644 (file)
@@ -65,6 +65,19 @@ static void __init xen_hvm_init_mem_mapping(void)
 {
        early_memunmap(HYPERVISOR_shared_info, PAGE_SIZE);
        HYPERVISOR_shared_info = __va(PFN_PHYS(shared_info_pfn));
+
+       /*
+        * The virtual address of the shared_info page has changed, so
+        * the vcpu_info pointer for VCPU 0 is now stale.
+        *
+        * The prepare_boot_cpu callback will re-initialize it via
+        * xen_vcpu_setup, but we can't rely on that to be called for
+        * old Xen versions (xen_have_vector_callback == 0).
+        *
+        * It is, in any case, bad to have a stale vcpu_info pointer
+        * so reset it now.
+        */
+       xen_vcpu_info_reset(0);
 }
 
 static void __init init_hvm_pv_info(void)
index d33e7dbe3129fc327fe7f24fb0fb84c802b11edf..2d76106788a31c5638459bc35306445e59f2c02d 100644 (file)
@@ -42,13 +42,11 @@ xmaddr_t arbitrary_virt_to_machine(void *vaddr)
 }
 EXPORT_SYMBOL_GPL(arbitrary_virt_to_machine);
 
-static void xen_flush_tlb_all(void)
+static noinline void xen_flush_tlb_all(void)
 {
        struct mmuext_op *op;
        struct multicall_space mcs;
 
-       trace_xen_mmu_flush_tlb_all(0);
-
        preempt_disable();
 
        mcs = xen_mc_entry(sizeof(*op));
index 486c0a34d00b2b75a27467aa46910142c108e373..2c30cabfda90fb94b36c88f5f35aef91d8f119d0 100644 (file)
@@ -1310,13 +1310,11 @@ unsigned long xen_read_cr2_direct(void)
        return this_cpu_read(xen_vcpu_info.arch.cr2);
 }
 
-static void xen_flush_tlb(void)
+static noinline void xen_flush_tlb(void)
 {
        struct mmuext_op *op;
        struct multicall_space mcs;
 
-       trace_xen_mmu_flush_tlb(0);
-
        preempt_disable();
 
        mcs = xen_mc_entry(sizeof(*op));
index 514aaf948ea900a584b0bb9293ac45b9f5759d04..3825df9234803a84cd5bc9ddd6892452eb87160f 100644 (file)
@@ -56,6 +56,10 @@ acpi_status acpi_ns_initialize_objects(void);
 
 acpi_status acpi_ns_initialize_devices(u32 flags);
 
+acpi_status
+acpi_ns_init_one_package(acpi_handle obj_handle,
+                        u32 level, void *context, void **return_value);
+
 /*
  * nsload -  Namespace loading
  */
index 99d92cb3280372bae6bb92d2077a90071a8cd9cb..f85c6f3271f64fb060fbf5029a4b41ee151389d5 100644 (file)
@@ -174,6 +174,13 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
                return_ACPI_STATUS(status);
        }
 
+       /* Complete the initialization/resolution of package objects */
+
+       status = acpi_ns_walk_namespace(ACPI_TYPE_PACKAGE, ACPI_ROOT_OBJECT,
+                                       ACPI_UINT32_MAX, 0,
+                                       acpi_ns_init_one_package, NULL, NULL,
+                                       NULL);
+
        /* Parameter Data (optional) */
 
        if (parameter_node) {
@@ -430,6 +437,13 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
                return_ACPI_STATUS(status);
        }
 
+       /* Complete the initialization/resolution of package objects */
+
+       status = acpi_ns_walk_namespace(ACPI_TYPE_PACKAGE, ACPI_ROOT_OBJECT,
+                                       ACPI_UINT32_MAX, 0,
+                                       acpi_ns_init_one_package, NULL, NULL,
+                                       NULL);
+
        /* Store the ddb_handle into the Target operand */
 
        status = acpi_ex_store(ddb_handle, target, walk_state);
index 77f2b5f4948ad3aa9d2567b010291549f1a81789..d77257d1c827b39f2efc0576ac8a08b433881d83 100644 (file)
@@ -240,6 +240,58 @@ error_exit:
        return_ACPI_STATUS(status);
 }
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_init_one_package
+ *
+ * PARAMETERS:  obj_handle      - Node
+ *              level           - Current nesting level
+ *              context         - Not used
+ *              return_value    - Not used
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every package
+ *              within the namespace. Used during dynamic load of an SSDT.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ns_init_one_package(acpi_handle obj_handle,
+                        u32 level, void *context, void **return_value)
+{
+       acpi_status status;
+       union acpi_operand_object *obj_desc;
+       struct acpi_namespace_node *node =
+           (struct acpi_namespace_node *)obj_handle;
+
+       obj_desc = acpi_ns_get_attached_object(node);
+       if (!obj_desc) {
+               return (AE_OK);
+       }
+
+       /* Exit if package is already initialized */
+
+       if (obj_desc->package.flags & AOPOBJ_DATA_VALID) {
+               return (AE_OK);
+       }
+
+       status = acpi_ds_get_package_arguments(obj_desc);
+       if (ACPI_FAILURE(status)) {
+               return (AE_OK);
+       }
+
+       status =
+           acpi_ut_walk_package_tree(obj_desc, NULL,
+                                     acpi_ds_init_package_element, NULL);
+       if (ACPI_FAILURE(status)) {
+               return (AE_OK);
+       }
+
+       obj_desc->package.flags |= AOPOBJ_DATA_VALID;
+       return (AE_OK);
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ns_init_one_object
@@ -360,27 +412,11 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
 
        case ACPI_TYPE_PACKAGE:
 
-               info->package_init++;
-               status = acpi_ds_get_package_arguments(obj_desc);
-               if (ACPI_FAILURE(status)) {
-                       break;
-               }
-
-               ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
-                                     "%s: Completing resolution of Package elements\n",
-                                     ACPI_GET_FUNCTION_NAME));
+               /* Complete the initialization/resolution of the package object */
 
-               /*
-                * Resolve all named references in package objects (and all
-                * sub-packages). This action has been deferred until the entire
-                * namespace has been loaded, in order to support external and
-                * forward references from individual package elements (05/2017).
-                */
-               status = acpi_ut_walk_package_tree(obj_desc, NULL,
-                                                  acpi_ds_init_package_element,
-                                                  NULL);
-
-               obj_desc->package.flags |= AOPOBJ_DATA_VALID;
+               info->package_init++;
+               status =
+                   acpi_ns_init_one_package(obj_handle, level, NULL, NULL);
                break;
 
        default:
index 1ff17799769d0b2372d2b9d385af57dab15acf10..6389c88b3500a0bb220b92efa85531cf564a974c 100644 (file)
@@ -698,7 +698,7 @@ static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
 
        DPRINTK("ENTER\n");
 
-       ahci_stop_engine(ap);
+       hpriv->stop_engine(ap);
 
        rc = sata_link_hardreset(link, sata_ehc_deb_timing(&link->eh_context),
                                 deadline, &online, NULL);
@@ -724,7 +724,7 @@ static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
        bool online;
        int rc;
 
-       ahci_stop_engine(ap);
+       hpriv->stop_engine(ap);
 
        /* clear D2H reception area to properly wait for D2H FIS */
        ata_tf_init(link->device, &tf);
@@ -788,7 +788,7 @@ static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
 
        DPRINTK("ENTER\n");
 
-       ahci_stop_engine(ap);
+       hpriv->stop_engine(ap);
 
        for (i = 0; i < 2; i++) {
                u16 val;
index 4356ef1d28a88f66be04f5e431e9c55d768bb866..824bd399f02ea4b350a85d004d2c3fefdf39d0ff 100644 (file)
@@ -350,7 +350,6 @@ struct ahci_host_priv {
        u32                     em_msg_type;    /* EM message type */
        bool                    got_runtime_pm; /* Did we do pm_runtime_get? */
        struct clk              *clks[AHCI_MAX_CLKS]; /* Optional */
-       struct reset_control    *rsts;          /* Optional */
        struct regulator        **target_pwrs;  /* Optional */
        /*
         * If platform uses PHYs. There is a 1:1 relation between the port number and
@@ -366,6 +365,13 @@ struct ahci_host_priv {
         * be overridden anytime before the host is activated.
         */
        void                    (*start_engine)(struct ata_port *ap);
+       /*
+        * Optional ahci_stop_engine override, if not set this gets set to the
+        * default ahci_stop_engine during ahci_save_initial_config, this can
+        * be overridden anytime before the host is activated.
+        */
+       int                     (*stop_engine)(struct ata_port *ap);
+
        irqreturn_t             (*irq_handler)(int irq, void *dev_instance);
 
        /* only required for per-port MSI(-X) support */
index de7128d81e9ccbc168627a02bb2a39d3e4f11c5c..0045dacd814b44ec21f87e4acceb07e69056f214 100644 (file)
@@ -62,6 +62,60 @@ static void ahci_mvebu_regret_option(struct ahci_host_priv *hpriv)
        writel(0x80, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
 }
 
+/**
+ * ahci_mvebu_stop_engine
+ *
+ * @ap:        Target ata port
+ *
+ * Errata Ref#226 - SATA Disk HOT swap issue when connected through
+ * Port Multiplier in FIS-based Switching mode.
+ *
+ * To avoid the issue, according to design, the bits[11:8, 0] of
+ * register PxFBS are cleared when Port Command and Status (0x18) bit[0]
+ * changes its value from 1 to 0, i.e. falling edge of Port
+ * Command and Status bit[0] sends PULSE that resets PxFBS
+ * bits[11:8; 0].
+ *
+ * This function is used to override function of "ahci_stop_engine"
+ * from libahci.c by adding the mvebu work around(WA) to save PxFBS
+ * value before the PxCMD ST write of 0, then restore PxFBS value.
+ *
+ * Return: 0 on success; Error code otherwise.
+ */
+int ahci_mvebu_stop_engine(struct ata_port *ap)
+{
+       void __iomem *port_mmio = ahci_port_base(ap);
+       u32 tmp, port_fbs;
+
+       tmp = readl(port_mmio + PORT_CMD);
+
+       /* check if the HBA is idle */
+       if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0)
+               return 0;
+
+       /* save the port PxFBS register for later restore */
+       port_fbs = readl(port_mmio + PORT_FBS);
+
+       /* setting HBA to idle */
+       tmp &= ~PORT_CMD_START;
+       writel(tmp, port_mmio + PORT_CMD);
+
+       /*
+        * bit #15 PxCMD signal doesn't clear PxFBS,
+        * restore the PxFBS register right after clearing the PxCMD ST,
+        * no need to wait for the PxCMD bit #15.
+        */
+       writel(port_fbs, port_mmio + PORT_FBS);
+
+       /* wait for engine to stop. This could be as long as 500 msec */
+       tmp = ata_wait_register(ap, port_mmio + PORT_CMD,
+                               PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500);
+       if (tmp & PORT_CMD_LIST_ON)
+               return -EIO;
+
+       return 0;
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int ahci_mvebu_suspend(struct platform_device *pdev, pm_message_t state)
 {
@@ -112,6 +166,8 @@ static int ahci_mvebu_probe(struct platform_device *pdev)
        if (rc)
                return rc;
 
+       hpriv->stop_engine = ahci_mvebu_stop_engine;
+
        if (of_device_is_compatible(pdev->dev.of_node,
                                    "marvell,armada-380-ahci")) {
                dram = mv_mbus_dram_info();
index 2685f28160f70764ee4013930239566031c9b058..cfdef4d44ae92cdf5a335c99a7d049df8a8cb5ae 100644 (file)
@@ -96,7 +96,7 @@ static int ahci_qoriq_hardreset(struct ata_link *link, unsigned int *class,
 
        DPRINTK("ENTER\n");
 
-       ahci_stop_engine(ap);
+       hpriv->stop_engine(ap);
 
        /*
         * There is a errata on ls1021a Rev1.0 and Rev2.0 which is:
index c2b5941d9184db2637604864baf4597d398c4911..ad58da7c9affd8e4ec381d8bb0fd7f23d6fa0310 100644 (file)
@@ -165,7 +165,7 @@ static int xgene_ahci_restart_engine(struct ata_port *ap)
                                    PORT_CMD_ISSUE, 0x0, 1, 100))
                  return -EBUSY;
 
-       ahci_stop_engine(ap);
+       hpriv->stop_engine(ap);
        ahci_start_fis_rx(ap);
 
        /*
@@ -421,7 +421,7 @@ static int xgene_ahci_hardreset(struct ata_link *link, unsigned int *class,
        portrxfis_saved = readl(port_mmio + PORT_FIS_ADDR);
        portrxfishi_saved = readl(port_mmio + PORT_FIS_ADDR_HI);
 
-       ahci_stop_engine(ap);
+       hpriv->stop_engine(ap);
 
        rc = xgene_ahci_do_hardreset(link, deadline, &online);
 
index 7adcf3caabd00abbb08ef76c0e4e604f0ba8c97c..e5d90977caec267084cf5eab7b18d8008f9047e2 100644 (file)
@@ -560,6 +560,9 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
        if (!hpriv->start_engine)
                hpriv->start_engine = ahci_start_engine;
 
+       if (!hpriv->stop_engine)
+               hpriv->stop_engine = ahci_stop_engine;
+
        if (!hpriv->irq_handler)
                hpriv->irq_handler = ahci_single_level_irq_intr;
 }
@@ -897,9 +900,10 @@ static void ahci_start_port(struct ata_port *ap)
 static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
 {
        int rc;
+       struct ahci_host_priv *hpriv = ap->host->private_data;
 
        /* disable DMA */
-       rc = ahci_stop_engine(ap);
+       rc = hpriv->stop_engine(ap);
        if (rc) {
                *emsg = "failed to stop engine";
                return rc;
@@ -1310,7 +1314,7 @@ int ahci_kick_engine(struct ata_port *ap)
        int busy, rc;
 
        /* stop engine */
-       rc = ahci_stop_engine(ap);
+       rc = hpriv->stop_engine(ap);
        if (rc)
                goto out_restart;
 
@@ -1549,7 +1553,7 @@ int ahci_do_hardreset(struct ata_link *link, unsigned int *class,
 
        DPRINTK("ENTER\n");
 
-       ahci_stop_engine(ap);
+       hpriv->stop_engine(ap);
 
        /* clear D2H reception area to properly wait for D2H FIS */
        ata_tf_init(link->device, &tf);
@@ -2075,14 +2079,14 @@ void ahci_error_handler(struct ata_port *ap)
 
        if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
                /* restart engine */
-               ahci_stop_engine(ap);
+               hpriv->stop_engine(ap);
                hpriv->start_engine(ap);
        }
 
        sata_pmp_error_handler(ap);
 
        if (!ata_dev_enabled(ap->link.device))
-               ahci_stop_engine(ap);
+               hpriv->stop_engine(ap);
 }
 EXPORT_SYMBOL_GPL(ahci_error_handler);
 
@@ -2129,7 +2133,7 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
                return;
 
        /* set DITO, MDAT, DETO and enable DevSlp, need to stop engine first */
-       rc = ahci_stop_engine(ap);
+       rc = hpriv->stop_engine(ap);
        if (rc)
                return;
 
@@ -2189,7 +2193,7 @@ static void ahci_enable_fbs(struct ata_port *ap)
                return;
        }
 
-       rc = ahci_stop_engine(ap);
+       rc = hpriv->stop_engine(ap);
        if (rc)
                return;
 
@@ -2222,7 +2226,7 @@ static void ahci_disable_fbs(struct ata_port *ap)
                return;
        }
 
-       rc = ahci_stop_engine(ap);
+       rc = hpriv->stop_engine(ap);
        if (rc)
                return;
 
index 46a762442dc512f0bd24392952414bf3582badde..30cc8f1a31e1299f3cc68659a5be959492249382 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/phy/phy.h>
 #include <linux/pm_runtime.h>
 #include <linux/of_platform.h>
-#include <linux/reset.h>
 #include "ahci.h"
 
 static void ahci_host_stop(struct ata_host *host);
@@ -196,8 +195,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_disable_regulators);
  * following order:
  * 1) Regulator
  * 2) Clocks (through ahci_platform_enable_clks)
- * 3) Resets
- * 4) Phys
+ * 3) Phys
  *
  * If resource enabling fails at any point the previous enabled resources
  * are disabled in reverse order.
@@ -217,19 +215,12 @@ int ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
        if (rc)
                goto disable_regulator;
 
-       rc = reset_control_deassert(hpriv->rsts);
-       if (rc)
-               goto disable_clks;
-
        rc = ahci_platform_enable_phys(hpriv);
        if (rc)
-               goto disable_resets;
+               goto disable_clks;
 
        return 0;
 
-disable_resets:
-       reset_control_assert(hpriv->rsts);
-
 disable_clks:
        ahci_platform_disable_clks(hpriv);
 
@@ -248,15 +239,12 @@ EXPORT_SYMBOL_GPL(ahci_platform_enable_resources);
  * following order:
  * 1) Phys
  * 2) Clocks (through ahci_platform_disable_clks)
- * 3) Resets
- * 4) Regulator
+ * 3) Regulator
  */
 void ahci_platform_disable_resources(struct ahci_host_priv *hpriv)
 {
        ahci_platform_disable_phys(hpriv);
 
-       reset_control_assert(hpriv->rsts);
-
        ahci_platform_disable_clks(hpriv);
 
        ahci_platform_disable_regulators(hpriv);
@@ -405,12 +393,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev)
                hpriv->clks[i] = clk;
        }
 
-       hpriv->rsts = devm_reset_control_array_get_optional_shared(dev);
-       if (IS_ERR(hpriv->rsts)) {
-               rc = PTR_ERR(hpriv->rsts);
-               goto err_out;
-       }
-
        hpriv->nports = child_nodes = of_get_child_count(dev->of_node);
 
        /*
index 8bc71ca61e7f836d44f6874660738974dd3c947b..68596bd4cf06c2362692f7ded557b669efc7f983 100644 (file)
@@ -4549,6 +4549,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
                                                ATA_HORKAGE_ZERO_AFTER_TRIM |
                                                ATA_HORKAGE_NOLPM, },
 
+       /* This specific Samsung model/firmware-rev does not handle LPM well */
+       { "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_HORKAGE_NOLPM, },
+
+       /* Sandisk devices which are known to not handle LPM well */
+       { "SanDisk SD7UB3Q*G1001",      NULL,   ATA_HORKAGE_NOLPM, },
+
        /* devices that don't properly handle queued TRIM commands */
        { "Micron_M500_*",              NULL,   ATA_HORKAGE_NO_NCQ_TRIM |
                                                ATA_HORKAGE_ZERO_AFTER_TRIM, },
index c016829a38fd21798e263cdc678517b3dbf728f7..513b260bcff1ef7cc74119b066ef8a7f8dd6c97f 100644 (file)
@@ -175,8 +175,8 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
 { }
 #endif /* CONFIG_PM */
 
-static void __ata_ehi_pushv_desc(struct ata_eh_info *ehi, const char *fmt,
-                                va_list args)
+static __printf(2, 0) void __ata_ehi_pushv_desc(struct ata_eh_info *ehi,
+                                const char *fmt, va_list args)
 {
        ehi->desc_len += vscnprintf(ehi->desc + ehi->desc_len,
                                     ATA_EH_DESC_LEN - ehi->desc_len,
index aafb8cc03523212dee4d8d3fe66434af2406ae76..e67815b896fcc40772ac45fdf8e8be7253cecafa 100644 (file)
@@ -410,7 +410,7 @@ static int ahci_highbank_hardreset(struct ata_link *link, unsigned int *class,
        int rc;
        int retry = 100;
 
-       ahci_stop_engine(ap);
+       hpriv->stop_engine(ap);
 
        /* clear D2H reception area to properly wait for D2H FIS */
        ata_tf_init(link->device, &tf);
index 4b1995e2d044ba7e4da5f6e36ec0c2d2dedafd50..010ca101d412380f7492ebb2c87eaca0ffce3e3b 100644 (file)
@@ -285,13 +285,13 @@ static const struct sil24_cerr_info {
        [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_RESET,
                                     "protocol mismatch" },
        [PORT_CERR_DIRECTION]   = { AC_ERR_HSM, ATA_EH_RESET,
-                                   "data directon mismatch" },
+                                   "data direction mismatch" },
        [PORT_CERR_UNDERRUN]    = { AC_ERR_HSM, ATA_EH_RESET,
                                    "ran out of SGEs while writing" },
        [PORT_CERR_OVERRUN]     = { AC_ERR_HSM, ATA_EH_RESET,
                                    "ran out of SGEs while reading" },
        [PORT_CERR_PKT_PROT]    = { AC_ERR_HSM, ATA_EH_RESET,
-                                   "invalid data directon for ATAPI CDB" },
+                                   "invalid data direction for ATAPI CDB" },
        [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_RESET,
                                     "SGT not on qword boundary" },
        [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
index d97c05690faa99363ac709fb237335a0678af4c0..4e46dc9e41ad01142ffdcfe1c38921df9db0ebda 100644 (file)
@@ -191,7 +191,7 @@ static char *res_strings[] = {
        "reserved 37",
        "reserved 38",
        "reserved 39",
-       "reseverd 40",
+       "reserved 40",
        "reserved 41", 
        "reserved 42", 
        "reserved 43", 
index 1ef67db03c8e618d7d2425a33e5d359e89f85607..9c9a229587176d560419c0c9c4df9562c1279a75 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/io.h>
 #include <linux/atomic.h>
 #include <linux/uaccess.h>
+#include <linux/nospec.h>
 
 #include "uPD98401.h"
 #include "uPD98402.h"
@@ -1458,6 +1459,8 @@ static int zatm_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg)
                                        return -EFAULT;
                                if (pool < 0 || pool > ZATM_LAST_POOL)
                                        return -EINVAL;
+                               pool = array_index_nospec(pool,
+                                                         ZATM_LAST_POOL + 1);
                                spin_lock_irqsave(&zatm_dev->lock, flags);
                                info = zatm_dev->pool_info[pool];
                                if (cmd == ZATM_GETPOOLZ) {
index 8e8b04cc569a44222c1e3f4ee4a3a188455ddf04..33b36fea1d73f0e957dcd7ef4b8107526e764893 100644 (file)
@@ -2366,7 +2366,9 @@ static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes)
        osd_req_op_cls_init(obj_req->osd_req, 0, CEPH_OSD_OP_CALL, "rbd",
                            "copyup");
        osd_req_op_cls_request_data_bvecs(obj_req->osd_req, 0,
-                                         obj_req->copyup_bvecs, bytes);
+                                         obj_req->copyup_bvecs,
+                                         obj_req->copyup_bvec_count,
+                                         bytes);
 
        switch (obj_req->img_request->op_type) {
        case OBJ_OP_WRITE:
index c8c8b0b8d333434fbe08dfc94f1a87e6f002b2e2..b937cc1e2c07491c6888a3c43fed96dc7205b1ba 100644 (file)
@@ -231,6 +231,7 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
@@ -263,7 +264,6 @@ static const struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
 
        /* QCA ROME chipset */
-       { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_QCA_ROME },
        { USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME },
        { USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME },
        { USB_DEVICE(0x0cf3, 0xe010), .driver_info = BTUSB_QCA_ROME },
@@ -399,6 +399,13 @@ static const struct dmi_system_id btusb_needs_reset_resume_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 3060"),
                },
        },
+       {
+               /* Dell XPS 9360 (QCA ROME device 0cf3:e300) */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9360"),
+               },
+       },
        {}
 };
 
@@ -2852,6 +2859,12 @@ static int btusb_config_oob_wake(struct hci_dev *hdev)
 }
 #endif
 
+static void btusb_check_needs_reset_resume(struct usb_interface *intf)
+{
+       if (dmi_check_system(btusb_needs_reset_resume_table))
+               interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
+}
+
 static int btusb_probe(struct usb_interface *intf,
                       const struct usb_device_id *id)
 {
@@ -2974,9 +2987,6 @@ static int btusb_probe(struct usb_interface *intf,
        hdev->send   = btusb_send_frame;
        hdev->notify = btusb_notify;
 
-       if (dmi_check_system(btusb_needs_reset_resume_table))
-               interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
-
 #ifdef CONFIG_PM
        err = btusb_config_oob_wake(hdev);
        if (err)
@@ -3064,6 +3074,7 @@ static int btusb_probe(struct usb_interface *intf,
                data->setup_on_usb = btusb_setup_qca;
                hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
                set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks);
+               btusb_check_needs_reset_resume(intf);
        }
 
 #ifdef CONFIG_BT_HCIBTUSB_RTL
index c381c8e396fcc0e43b5a1b2a5ebd0c9e80ad732f..79d8c84693a185264990d40185006f5eaec0f145 100644 (file)
@@ -195,7 +195,7 @@ static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, int ty
        return 0;
 }
 
-int uninorth_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
+static int uninorth_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
        size_t i;
        u32 *gp;
@@ -470,7 +470,7 @@ static int uninorth_free_gatt_table(struct agp_bridge_data *bridge)
        return 0;
 }
 
-void null_cache_flush(void)
+static void null_cache_flush(void)
 {
        mb();
 }
index 41492e980ef4c0deb4fd6f62020d76137c912b42..34968a381d0fdc878d98e7fab60762f2f6588ec5 100644 (file)
@@ -266,15 +266,13 @@ config COMMON_CLK_STM32MP157
          Support for stm32mp157 SoC family clocks
 
 config COMMON_CLK_STM32F
-       bool "Clock driver for stm32f4 and stm32f7 SoC families"
-       depends on MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746
+       def_bool COMMON_CLK && (MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746)
        help
        ---help---
          Support for stm32f4 and stm32f7 SoC families clocks
 
 config COMMON_CLK_STM32H7
-       bool "Clock driver for stm32h7 SoC family"
-       depends on MACH_STM32H743
+       def_bool COMMON_CLK && MACH_STM32H743
        help
        ---help---
          Support for stm32h7 SoC family clocks
index 114ecbb94ec5ed8d5e364c981d740ecc305d553a..12320118f8deea7dabba7a4d7af975645fb1d48f 100644 (file)
@@ -464,7 +464,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        clk_set_rate(clks[IMX6UL_CLK_AHB], 99000000);
 
        /* Change periph_pre clock to pll2_bus to adjust AXI rate to 264MHz */
-       clk_set_parent(clks[IMX6UL_CLK_PERIPH_CLK2_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+       clk_set_parent(clks[IMX6UL_CLK_PERIPH_CLK2_SEL], clks[IMX6UL_CLK_OSC]);
        clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_CLK2]);
        clk_set_parent(clks[IMX6UL_CLK_PERIPH_PRE], clks[IMX6UL_CLK_PLL2_BUS]);
        clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_PRE]);
index de55c7d57438c8e094a49d2d1d0b9240c20971ab..96b35b8b36060f4af9eed2ac82c46aa5d2ea08be 100644 (file)
@@ -20,7 +20,7 @@ config ACPI_CPPC_CPUFREQ
 
 config ARM_ARMADA_37XX_CPUFREQ
        tristate "Armada 37xx CPUFreq support"
-       depends on ARCH_MVEBU
+       depends on ARCH_MVEBU && CPUFREQ_DT
        help
          This adds the CPUFreq driver support for Marvell Armada 37xx SoCs.
          The Armada 37xx PMU supports 4 frequency and VDD levels.
index 77e485557498329193fd291194cc037de55c8160..6f693b7d5220a02b110ae28b8fb6dd5a997d631f 100644 (file)
@@ -384,7 +384,7 @@ static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
        if (set)
                reg |= bit;
        else
-               reg &= bit;
+               reg &= ~bit;
        iowrite32(reg, addr);
 
        spin_unlock_irqrestore(&gpio->lock, flags);
index 1948724d8c369df7baab3e889138408c1e860db8..25d16b2af1c39b305830d837c5aff62ecaf95ae2 100644 (file)
@@ -116,9 +116,9 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
        unsigned long word_mask;
        const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
        unsigned long port_state;
-       u8 __iomem ports[] = {
-               idio16gpio->reg->out0_7, idio16gpio->reg->out8_15,
-               idio16gpio->reg->in0_7, idio16gpio->reg->in8_15,
+       void __iomem *ports[] = {
+               &idio16gpio->reg->out0_7, &idio16gpio->reg->out8_15,
+               &idio16gpio->reg->in0_7, &idio16gpio->reg->in8_15,
        };
 
        /* clear bits array to a clean slate */
@@ -143,7 +143,7 @@ static int idio_16_gpio_get_multiple(struct gpio_chip *chip,
                }
 
                /* read bits from current gpio port */
-               port_state = ioread8(ports + i);
+               port_state = ioread8(ports[i]);
 
                /* store acquired bits at respective bits array offset */
                bits[word_index] |= port_state << word_offset;
index 835607ecf658efc95af727767f81caaaf9180d9c..f953541e78901b3971242338492af07a570b533d 100644 (file)
@@ -206,10 +206,10 @@ static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
        unsigned long word_mask;
        const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
        unsigned long port_state;
-       u8 __iomem ports[] = {
-               idio24gpio->reg->out0_7, idio24gpio->reg->out8_15,
-               idio24gpio->reg->out16_23, idio24gpio->reg->in0_7,
-               idio24gpio->reg->in8_15, idio24gpio->reg->in16_23,
+       void __iomem *ports[] = {
+               &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
+               &idio24gpio->reg->out16_23, &idio24gpio->reg->in0_7,
+               &idio24gpio->reg->in8_15, &idio24gpio->reg->in16_23,
        };
        const unsigned long out_mode_mask = BIT(1);
 
@@ -217,7 +217,7 @@ static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
        bitmap_zero(bits, chip->ngpio);
 
        /* get bits are evaluated a gpio port register at a time */
-       for (i = 0; i < ARRAY_SIZE(ports); i++) {
+       for (i = 0; i < ARRAY_SIZE(ports) + 1; i++) {
                /* gpio offset in bits array */
                bits_offset = i * gpio_reg_size;
 
@@ -236,7 +236,7 @@ static int idio_24_gpio_get_multiple(struct gpio_chip *chip,
 
                /* read bits from current gpio port (port 6 is TTL GPIO) */
                if (i < 6)
-                       port_state = ioread8(ports + i);
+                       port_state = ioread8(ports[i]);
                else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask)
                        port_state = ioread8(&idio24gpio->reg->ttl_out0_7);
                else
@@ -301,9 +301,9 @@ static void idio_24_gpio_set_multiple(struct gpio_chip *chip,
        const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
        unsigned long flags;
        unsigned int out_state;
-       u8 __iomem ports[] = {
-               idio24gpio->reg->out0_7, idio24gpio->reg->out8_15,
-               idio24gpio->reg->out16_23
+       void __iomem *ports[] = {
+               &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15,
+               &idio24gpio->reg->out16_23
        };
        const unsigned long out_mode_mask = BIT(1);
        const unsigned int ttl_offset = 48;
@@ -327,9 +327,9 @@ static void idio_24_gpio_set_multiple(struct gpio_chip *chip,
                raw_spin_lock_irqsave(&idio24gpio->lock, flags);
 
                /* process output lines */
-               out_state = ioread8(ports + i) & ~gpio_mask;
+               out_state = ioread8(ports[i]) & ~gpio_mask;
                out_state |= (*bits >> bits_offset) & gpio_mask;
-               iowrite8(out_state, ports + i);
+               iowrite8(out_state, ports[i]);
 
                raw_spin_unlock_irqrestore(&idio24gpio->lock, flags);
        }
index 43aeb07343ec76fe3eeef0283d8d52327530bfdf..d8ccb500872fa2eacd26a91c473ee02a131cea18 100644 (file)
@@ -497,7 +497,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
        struct gpiohandle_request handlereq;
        struct linehandle_state *lh;
        struct file *file;
-       int fd, i, ret;
+       int fd, i, count = 0, ret;
        u32 lflags;
 
        if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
@@ -558,6 +558,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
                if (ret)
                        goto out_free_descs;
                lh->descs[i] = desc;
+               count = i;
 
                if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW)
                        set_bit(FLAG_ACTIVE_LOW, &desc->flags);
@@ -628,7 +629,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
 out_put_unused_fd:
        put_unused_fd(fd);
 out_free_descs:
-       for (; i >= 0; i--)
+       for (i = 0; i < count; i++)
                gpiod_free(lh->descs[i]);
        kfree(lh->label);
 out_free_lh:
@@ -902,7 +903,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
        desc = &gdev->descs[offset];
        ret = gpiod_request(desc, le->label);
        if (ret)
-               goto out_free_desc;
+               goto out_free_label;
        le->desc = desc;
        le->eflags = eflags;
 
index 09d35051fdd68689ac00d69504765166e738076f..3fabf9f97022e9c74c2fe0f59e9207b408a6546f 100644 (file)
@@ -419,9 +419,11 @@ int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx, unsigned ring_id)
 
        if (other) {
                signed long r;
-               r = dma_fence_wait_timeout(other, false, MAX_SCHEDULE_TIMEOUT);
+               r = dma_fence_wait(other, true);
                if (r < 0) {
-                       DRM_ERROR("Error (%ld) waiting for fence!\n", r);
+                       if (r != -ERESTARTSYS)
+                               DRM_ERROR("Error (%ld) waiting for fence!\n", r);
+
                        return r;
                }
        }
index ace9ad578ca08f85aeccf49ac4d744b071444274..4304d9e408b88d180eabac07327497fdda353b25 100644 (file)
@@ -83,21 +83,22 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
        enum i2c_mot_mode mot = (msg->request & DP_AUX_I2C_MOT) ?
                I2C_MOT_TRUE : I2C_MOT_FALSE;
        enum ddc_result res;
-       ssize_t read_bytes;
+       uint32_t read_bytes = msg->size;
 
        if (WARN_ON(msg->size > 16))
                return -E2BIG;
 
        switch (msg->request & ~DP_AUX_I2C_MOT) {
        case DP_AUX_NATIVE_READ:
-               read_bytes = dal_ddc_service_read_dpcd_data(
+               res = dal_ddc_service_read_dpcd_data(
                                TO_DM_AUX(aux)->ddc_service,
                                false,
                                I2C_MOT_UNDEF,
                                msg->address,
                                msg->buffer,
-                               msg->size);
-               return read_bytes;
+                               msg->size,
+                               &read_bytes);
+               break;
        case DP_AUX_NATIVE_WRITE:
                res = dal_ddc_service_write_dpcd_data(
                                TO_DM_AUX(aux)->ddc_service,
@@ -108,14 +109,15 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
                                msg->size);
                break;
        case DP_AUX_I2C_READ:
-               read_bytes = dal_ddc_service_read_dpcd_data(
+               res = dal_ddc_service_read_dpcd_data(
                                TO_DM_AUX(aux)->ddc_service,
                                true,
                                mot,
                                msg->address,
                                msg->buffer,
-                               msg->size);
-               return read_bytes;
+                               msg->size,
+                               &read_bytes);
+               break;
        case DP_AUX_I2C_WRITE:
                res = dal_ddc_service_write_dpcd_data(
                                TO_DM_AUX(aux)->ddc_service,
@@ -137,7 +139,9 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux,
                 r == DDC_RESULT_SUCESSFULL);
 #endif
 
-       return msg->size;
+       if (res != DDC_RESULT_SUCESSFULL)
+               return -EIO;
+       return read_bytes;
 }
 
 static enum drm_connector_status
index 985fe8c22875abe3610de2f8fb0dc64c12bba2cf..10a5807a7e8b20e59a2e02009ad7fe0ebe5bfa6c 100644 (file)
@@ -70,6 +70,10 @@ static enum bp_result get_firmware_info_v3_1(
        struct bios_parser *bp,
        struct dc_firmware_info *info);
 
+static enum bp_result get_firmware_info_v3_2(
+       struct bios_parser *bp,
+       struct dc_firmware_info *info);
+
 static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp,
                struct atom_display_object_path_v2 *object);
 
@@ -1321,9 +1325,11 @@ static enum bp_result bios_parser_get_firmware_info(
                case 3:
                        switch (revision.minor) {
                        case 1:
-                       case 2:
                                result = get_firmware_info_v3_1(bp, info);
                                break;
+                       case 2:
+                               result = get_firmware_info_v3_2(bp, info);
+                               break;
                        default:
                                break;
                        }
@@ -1383,6 +1389,84 @@ static enum bp_result get_firmware_info_v3_1(
        return BP_RESULT_OK;
 }
 
+static enum bp_result get_firmware_info_v3_2(
+       struct bios_parser *bp,
+       struct dc_firmware_info *info)
+{
+       struct atom_firmware_info_v3_2 *firmware_info;
+       struct atom_display_controller_info_v4_1 *dce_info = NULL;
+       struct atom_common_table_header *header;
+       struct atom_data_revision revision;
+       struct atom_smu_info_v3_2 *smu_info_v3_2 = NULL;
+       struct atom_smu_info_v3_3 *smu_info_v3_3 = NULL;
+
+       if (!info)
+               return BP_RESULT_BADINPUT;
+
+       firmware_info = GET_IMAGE(struct atom_firmware_info_v3_2,
+                       DATA_TABLES(firmwareinfo));
+
+       dce_info = GET_IMAGE(struct atom_display_controller_info_v4_1,
+                       DATA_TABLES(dce_info));
+
+       if (!firmware_info || !dce_info)
+               return BP_RESULT_BADBIOSTABLE;
+
+       memset(info, 0, sizeof(*info));
+
+       header = GET_IMAGE(struct atom_common_table_header,
+                                       DATA_TABLES(smu_info));
+       get_atom_data_table_revision(header, &revision);
+
+       if (revision.minor == 2) {
+               /* Vega12 */
+               smu_info_v3_2 = GET_IMAGE(struct atom_smu_info_v3_2,
+                                                       DATA_TABLES(smu_info));
+
+               if (!smu_info_v3_2)
+                       return BP_RESULT_BADBIOSTABLE;
+
+               info->default_engine_clk = smu_info_v3_2->bootup_dcefclk_10khz * 10;
+       } else if (revision.minor == 3) {
+               /* Vega20 */
+               smu_info_v3_3 = GET_IMAGE(struct atom_smu_info_v3_3,
+                                                       DATA_TABLES(smu_info));
+
+               if (!smu_info_v3_3)
+                       return BP_RESULT_BADBIOSTABLE;
+
+               info->default_engine_clk = smu_info_v3_3->bootup_dcefclk_10khz * 10;
+       }
+
+        // We need to convert from 10KHz units into KHz units.
+       info->default_memory_clk = firmware_info->bootup_mclk_in10khz * 10;
+
+        /* 27MHz for Vega10 & Vega12; 100MHz for Vega20 */
+       info->pll_info.crystal_frequency = dce_info->dce_refclk_10khz * 10;
+       /* Hardcode frequency if BIOS gives no DCE Ref Clk */
+       if (info->pll_info.crystal_frequency == 0) {
+               if (revision.minor == 2)
+                       info->pll_info.crystal_frequency = 27000;
+               else if (revision.minor == 3)
+                       info->pll_info.crystal_frequency = 100000;
+       }
+       /*dp_phy_ref_clk is not correct for atom_display_controller_info_v4_2, but we don't use it*/
+       info->dp_phy_ref_clk     = dce_info->dpphy_refclk_10khz * 10;
+       info->i2c_engine_ref_clk = dce_info->i2c_engine_refclk_10khz * 10;
+
+       /* Get GPU PLL VCO Clock */
+       if (bp->cmd_tbl.get_smu_clock_info != NULL) {
+               if (revision.minor == 2)
+                       info->smu_gpu_pll_output_freq =
+                                       bp->cmd_tbl.get_smu_clock_info(bp, SMU9_SYSPLL0_ID) * 10;
+               else if (revision.minor == 3)
+                       info->smu_gpu_pll_output_freq =
+                                       bp->cmd_tbl.get_smu_clock_info(bp, SMU11_SYSPLL3_0_ID) * 10;
+       }
+
+       return BP_RESULT_OK;
+}
+
 static enum bp_result bios_parser_get_encoder_cap_info(
        struct dc_bios *dcb,
        struct graphics_object_id object_id,
index 49c2face1e7a869e07e94da881e7ed33acbe483e..ae48d603ebd6ca73c289c71f50795f5d3bd6f65e 100644 (file)
@@ -629,13 +629,14 @@ bool dal_ddc_service_query_ddc_data(
        return ret;
 }
 
-ssize_t dal_ddc_service_read_dpcd_data(
+enum ddc_result dal_ddc_service_read_dpcd_data(
        struct ddc_service *ddc,
        bool i2c,
        enum i2c_mot_mode mot,
        uint32_t address,
        uint8_t *data,
-       uint32_t len)
+       uint32_t len,
+       uint32_t *read)
 {
        struct aux_payload read_payload = {
                .i2c_over_aux = i2c,
@@ -652,6 +653,8 @@ ssize_t dal_ddc_service_read_dpcd_data(
                .mot = mot
        };
 
+       *read = 0;
+
        if (len > DEFAULT_AUX_MAX_DATA_SIZE) {
                BREAK_TO_DEBUGGER();
                return DDC_RESULT_FAILED_INVALID_OPERATION;
@@ -661,7 +664,8 @@ ssize_t dal_ddc_service_read_dpcd_data(
                ddc->ctx->i2caux,
                ddc->ddc_pin,
                &command)) {
-               return (ssize_t)command.payloads->length;
+               *read = command.payloads->length;
+               return DDC_RESULT_SUCESSFULL;
        }
 
        return DDC_RESULT_FAILED_OPERATION;
index ade5b8ee9c3c0ead9272204360e9372208ba2b50..132eef3826e2d99b71115d509e887887e9eb220b 100644 (file)
@@ -66,8 +66,8 @@ struct dc_plane_state *dc_create_plane_state(struct dc *dc)
 {
        struct dc *core_dc = dc;
 
-       struct dc_plane_state *plane_state = kzalloc(sizeof(*plane_state),
-                                                    GFP_KERNEL);
+       struct dc_plane_state *plane_state = kvzalloc(sizeof(*plane_state),
+                                                     GFP_KERNEL);
 
        if (NULL == plane_state)
                return NULL;
@@ -120,7 +120,7 @@ static void dc_plane_state_free(struct kref *kref)
 {
        struct dc_plane_state *plane_state = container_of(kref, struct dc_plane_state, refcount);
        destruct(plane_state);
-       kfree(plane_state);
+       kvfree(plane_state);
 }
 
 void dc_plane_state_release(struct dc_plane_state *plane_state)
@@ -136,7 +136,7 @@ void dc_gamma_retain(struct dc_gamma *gamma)
 static void dc_gamma_free(struct kref *kref)
 {
        struct dc_gamma *gamma = container_of(kref, struct dc_gamma, refcount);
-       kfree(gamma);
+       kvfree(gamma);
 }
 
 void dc_gamma_release(struct dc_gamma **gamma)
@@ -147,7 +147,7 @@ void dc_gamma_release(struct dc_gamma **gamma)
 
 struct dc_gamma *dc_create_gamma(void)
 {
-       struct dc_gamma *gamma = kzalloc(sizeof(*gamma), GFP_KERNEL);
+       struct dc_gamma *gamma = kvzalloc(sizeof(*gamma), GFP_KERNEL);
 
        if (gamma == NULL)
                goto alloc_fail;
@@ -167,7 +167,7 @@ void dc_transfer_func_retain(struct dc_transfer_func *tf)
 static void dc_transfer_func_free(struct kref *kref)
 {
        struct dc_transfer_func *tf = container_of(kref, struct dc_transfer_func, refcount);
-       kfree(tf);
+       kvfree(tf);
 }
 
 void dc_transfer_func_release(struct dc_transfer_func *tf)
@@ -177,7 +177,7 @@ void dc_transfer_func_release(struct dc_transfer_func *tf)
 
 struct dc_transfer_func *dc_create_transfer_func(void)
 {
-       struct dc_transfer_func *tf = kzalloc(sizeof(*tf), GFP_KERNEL);
+       struct dc_transfer_func *tf = kvzalloc(sizeof(*tf), GFP_KERNEL);
 
        if (tf == NULL)
                goto alloc_fail;
index 090b7a8dd67bde2bdfdaf243c04d175abf82112c..30b3a08b91be27dade29620cfc5dbf857c89bad1 100644 (file)
@@ -102,13 +102,14 @@ bool dal_ddc_service_query_ddc_data(
                uint8_t *read_buf,
                uint32_t read_size);
 
-ssize_t dal_ddc_service_read_dpcd_data(
+enum ddc_result dal_ddc_service_read_dpcd_data(
                struct ddc_service *ddc,
                bool i2c,
                enum i2c_mot_mode mot,
                uint32_t address,
                uint8_t *data,
-               uint32_t len);
+               uint32_t len,
+               uint32_t *read);
 
 enum ddc_result dal_ddc_service_write_dpcd_data(
                struct ddc_service *ddc,
index 9831cb5eaa7cfc8b67d33c8ee4cbcc7ec3b915c3..9b0a04f99ac836188dd06c071486f87f626eb191 100644 (file)
 
 #define AI_GREENLAND_P_A0 1
 #define AI_GREENLAND_P_A1 2
+#define AI_UNKNOWN 0xFF
 
-#define ASICREV_IS_GREENLAND_M(eChipRev)  (eChipRev < AI_UNKNOWN)
-#define ASICREV_IS_GREENLAND_P(eChipRev)  (eChipRev < AI_UNKNOWN)
+#define AI_VEGA12_P_A0 20
+#define ASICREV_IS_GREENLAND_M(eChipRev)  (eChipRev < AI_VEGA12_P_A0)
+#define ASICREV_IS_GREENLAND_P(eChipRev)  (eChipRev < AI_VEGA12_P_A0)
+
+#define ASICREV_IS_VEGA12_P(eChipRev) ((eChipRev >= AI_VEGA12_P_A0) && (eChipRev < AI_UNKNOWN))
+#define ASICREV_IS_VEGA12_p(eChipRev) ((eChipRev >= AI_VEGA12_P_A0) && (eChipRev < AI_UNKNOWN))
 
 /* DCN1_0 */
 #define INTERNAL_REV_RAVEN_A0             0x00    /* First spin of Raven */
index e7e374f5686449d5ef6f596c8a4aa92a9e40ec2a..b3747a019debf8fe7336b408fdaa032e9feae056 100644 (file)
@@ -1093,19 +1093,19 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
 
        output_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
 
-       rgb_user = kzalloc(sizeof(*rgb_user) * (ramp->num_entries + _EXTRA_POINTS),
-                          GFP_KERNEL);
+       rgb_user = kvzalloc(sizeof(*rgb_user) * (ramp->num_entries + _EXTRA_POINTS),
+                           GFP_KERNEL);
        if (!rgb_user)
                goto rgb_user_alloc_fail;
-       rgb_regamma = kzalloc(sizeof(*rgb_regamma) * (MAX_HW_POINTS + _EXTRA_POINTS),
-                       GFP_KERNEL);
+       rgb_regamma = kvzalloc(sizeof(*rgb_regamma) * (MAX_HW_POINTS + _EXTRA_POINTS),
+                              GFP_KERNEL);
        if (!rgb_regamma)
                goto rgb_regamma_alloc_fail;
-       axix_x = kzalloc(sizeof(*axix_x) * (ramp->num_entries + 3),
-                        GFP_KERNEL);
+       axix_x = kvzalloc(sizeof(*axix_x) * (ramp->num_entries + 3),
+                         GFP_KERNEL);
        if (!axix_x)
                goto axix_x_alloc_fail;
-       coeff = kzalloc(sizeof(*coeff) * (MAX_HW_POINTS + _EXTRA_POINTS), GFP_KERNEL);
+       coeff = kvzalloc(sizeof(*coeff) * (MAX_HW_POINTS + _EXTRA_POINTS), GFP_KERNEL);
        if (!coeff)
                goto coeff_alloc_fail;
 
@@ -1157,13 +1157,13 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
 
        ret = true;
 
-       kfree(coeff);
+       kvfree(coeff);
 coeff_alloc_fail:
-       kfree(axix_x);
+       kvfree(axix_x);
 axix_x_alloc_fail:
-       kfree(rgb_regamma);
+       kvfree(rgb_regamma);
 rgb_regamma_alloc_fail:
-       kfree(rgb_user);
+       kvfree(rgb_user);
 rgb_user_alloc_fail:
        return ret;
 }
@@ -1192,19 +1192,19 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
 
        input_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
 
-       rgb_user = kzalloc(sizeof(*rgb_user) * (ramp->num_entries + _EXTRA_POINTS),
-                          GFP_KERNEL);
+       rgb_user = kvzalloc(sizeof(*rgb_user) * (ramp->num_entries + _EXTRA_POINTS),
+                           GFP_KERNEL);
        if (!rgb_user)
                goto rgb_user_alloc_fail;
-       curve = kzalloc(sizeof(*curve) * (MAX_HW_POINTS + _EXTRA_POINTS),
-                       GFP_KERNEL);
+       curve = kvzalloc(sizeof(*curve) * (MAX_HW_POINTS + _EXTRA_POINTS),
+                        GFP_KERNEL);
        if (!curve)
                goto curve_alloc_fail;
-       axix_x = kzalloc(sizeof(*axix_x) * (ramp->num_entries + _EXTRA_POINTS),
-                        GFP_KERNEL);
+       axix_x = kvzalloc(sizeof(*axix_x) * (ramp->num_entries + _EXTRA_POINTS),
+                         GFP_KERNEL);
        if (!axix_x)
                goto axix_x_alloc_fail;
-       coeff = kzalloc(sizeof(*coeff) * (MAX_HW_POINTS + _EXTRA_POINTS), GFP_KERNEL);
+       coeff = kvzalloc(sizeof(*coeff) * (MAX_HW_POINTS + _EXTRA_POINTS), GFP_KERNEL);
        if (!coeff)
                goto coeff_alloc_fail;
 
@@ -1246,13 +1246,13 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
 
        ret = true;
 
-       kfree(coeff);
+       kvfree(coeff);
 coeff_alloc_fail:
-       kfree(axix_x);
+       kvfree(axix_x);
 axix_x_alloc_fail:
-       kfree(curve);
+       kvfree(curve);
 curve_alloc_fail:
-       kfree(rgb_user);
+       kvfree(rgb_user);
 rgb_user_alloc_fail:
 
        return ret;
@@ -1281,8 +1281,9 @@ bool  mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
                }
                ret = true;
        } else if (trans == TRANSFER_FUNCTION_PQ) {
-               rgb_regamma = kzalloc(sizeof(*rgb_regamma) * (MAX_HW_POINTS +
-                                               _EXTRA_POINTS), GFP_KERNEL);
+               rgb_regamma = kvzalloc(sizeof(*rgb_regamma) *
+                                      (MAX_HW_POINTS + _EXTRA_POINTS),
+                                      GFP_KERNEL);
                if (!rgb_regamma)
                        goto rgb_regamma_alloc_fail;
                points->end_exponent = 7;
@@ -1302,11 +1303,12 @@ bool  mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
                }
                ret = true;
 
-               kfree(rgb_regamma);
+               kvfree(rgb_regamma);
        } else if (trans == TRANSFER_FUNCTION_SRGB ||
                          trans == TRANSFER_FUNCTION_BT709) {
-               rgb_regamma = kzalloc(sizeof(*rgb_regamma) * (MAX_HW_POINTS +
-                                               _EXTRA_POINTS), GFP_KERNEL);
+               rgb_regamma = kvzalloc(sizeof(*rgb_regamma) *
+                                      (MAX_HW_POINTS + _EXTRA_POINTS),
+                                      GFP_KERNEL);
                if (!rgb_regamma)
                        goto rgb_regamma_alloc_fail;
                points->end_exponent = 0;
@@ -1324,7 +1326,7 @@ bool  mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
                }
                ret = true;
 
-               kfree(rgb_regamma);
+               kvfree(rgb_regamma);
        }
 rgb_regamma_alloc_fail:
        return ret;
@@ -1348,8 +1350,9 @@ bool  mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
                }
                ret = true;
        } else if (trans == TRANSFER_FUNCTION_PQ) {
-               rgb_degamma = kzalloc(sizeof(*rgb_degamma) * (MAX_HW_POINTS +
-                                               _EXTRA_POINTS), GFP_KERNEL);
+               rgb_degamma = kvzalloc(sizeof(*rgb_degamma) *
+                                      (MAX_HW_POINTS + _EXTRA_POINTS),
+                                      GFP_KERNEL);
                if (!rgb_degamma)
                        goto rgb_degamma_alloc_fail;
 
@@ -1364,11 +1367,12 @@ bool  mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
                }
                ret = true;
 
-               kfree(rgb_degamma);
+               kvfree(rgb_degamma);
        } else if (trans == TRANSFER_FUNCTION_SRGB ||
                          trans == TRANSFER_FUNCTION_BT709) {
-               rgb_degamma = kzalloc(sizeof(*rgb_degamma) * (MAX_HW_POINTS +
-                                               _EXTRA_POINTS), GFP_KERNEL);
+               rgb_degamma = kvzalloc(sizeof(*rgb_degamma) *
+                                      (MAX_HW_POINTS + _EXTRA_POINTS),
+                                      GFP_KERNEL);
                if (!rgb_degamma)
                        goto rgb_degamma_alloc_fail;
 
@@ -1382,7 +1386,7 @@ bool  mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
                }
                ret = true;
 
-               kfree(rgb_degamma);
+               kvfree(rgb_degamma);
        }
        points->end_exponent = 0;
        points->x_point_at_y1_red = 1;
index 0f5ad54d3fd3d9c5e3700ec1d3e6324bf0436f4c..de177ce8ca80216b126f3503c9821ae12efc27ef 100644 (file)
@@ -501,6 +501,32 @@ enum atom_cooling_solution_id{
   LIQUID_COOLING = 0x01
 };
 
+struct atom_firmware_info_v3_2 {
+  struct atom_common_table_header table_header;
+  uint32_t firmware_revision;
+  uint32_t bootup_sclk_in10khz;
+  uint32_t bootup_mclk_in10khz;
+  uint32_t firmware_capability;             // enum atombios_firmware_capability
+  uint32_t main_call_parser_entry;          /* direct address of main parser call in VBIOS binary. */
+  uint32_t bios_scratch_reg_startaddr;      // 1st bios scratch register dword address
+  uint16_t bootup_vddc_mv;
+  uint16_t bootup_vddci_mv;
+  uint16_t bootup_mvddc_mv;
+  uint16_t bootup_vddgfx_mv;
+  uint8_t  mem_module_id;
+  uint8_t  coolingsolution_id;              /*0: Air cooling; 1: Liquid cooling ... */
+  uint8_t  reserved1[2];
+  uint32_t mc_baseaddr_high;
+  uint32_t mc_baseaddr_low;
+  uint8_t  board_i2c_feature_id;            // enum of atom_board_i2c_feature_id_def
+  uint8_t  board_i2c_feature_gpio_id;       // i2c id find in gpio_lut data table gpio_id
+  uint8_t  board_i2c_feature_slave_addr;
+  uint8_t  reserved3;
+  uint16_t bootup_mvddq_mv;
+  uint16_t bootup_mvpp_mv;
+  uint32_t zfbstartaddrin16mb;
+  uint32_t reserved2[3];
+};
 
 /* 
   ***************************************************************************
@@ -1169,7 +1195,29 @@ struct  atom_gfx_info_v2_2
   uint32_t rlc_gpu_timer_refclk; 
 };
 
-
+struct  atom_gfx_info_v2_3 {
+  struct  atom_common_table_header  table_header;
+  uint8_t gfxip_min_ver;
+  uint8_t gfxip_max_ver;
+  uint8_t max_shader_engines;
+  uint8_t max_tile_pipes;
+  uint8_t max_cu_per_sh;
+  uint8_t max_sh_per_se;
+  uint8_t max_backends_per_se;
+  uint8_t max_texture_channel_caches;
+  uint32_t regaddr_cp_dma_src_addr;
+  uint32_t regaddr_cp_dma_src_addr_hi;
+  uint32_t regaddr_cp_dma_dst_addr;
+  uint32_t regaddr_cp_dma_dst_addr_hi;
+  uint32_t regaddr_cp_dma_command;
+  uint32_t regaddr_cp_status;
+  uint32_t regaddr_rlc_gpu_clock_32;
+  uint32_t rlc_gpu_timer_refclk;
+  uint8_t active_cu_per_sh;
+  uint8_t active_rb_per_se;
+  uint16_t gcgoldenoffset;
+  uint32_t rm21_sram_vmin_value;
+};
 
 /* 
   ***************************************************************************
@@ -1198,6 +1246,76 @@ struct atom_smu_info_v3_1
   uint8_t  fw_ctf_polarity;         // GPIO polarity for CTF
 };
 
+struct atom_smu_info_v3_2 {
+  struct   atom_common_table_header  table_header;
+  uint8_t  smuip_min_ver;
+  uint8_t  smuip_max_ver;
+  uint8_t  smu_rsd1;
+  uint8_t  gpuclk_ss_mode;
+  uint16_t sclk_ss_percentage;
+  uint16_t sclk_ss_rate_10hz;
+  uint16_t gpuclk_ss_percentage;    // in unit of 0.001%
+  uint16_t gpuclk_ss_rate_10hz;
+  uint32_t core_refclk_10khz;
+  uint8_t  ac_dc_gpio_bit;          // GPIO bit shift in SMU_GPIOPAD_A  configured for AC/DC switching, =0xff means invalid
+  uint8_t  ac_dc_polarity;          // GPIO polarity for AC/DC switching
+  uint8_t  vr0hot_gpio_bit;         // GPIO bit shift in SMU_GPIOPAD_A  configured for VR0 HOT event, =0xff means invalid
+  uint8_t  vr0hot_polarity;         // GPIO polarity for VR0 HOT event
+  uint8_t  vr1hot_gpio_bit;         // GPIO bit shift in SMU_GPIOPAD_A configured for VR1 HOT event , =0xff means invalid
+  uint8_t  vr1hot_polarity;         // GPIO polarity for VR1 HOT event
+  uint8_t  fw_ctf_gpio_bit;         // GPIO bit shift in SMU_GPIOPAD_A configured for CTF, =0xff means invalid
+  uint8_t  fw_ctf_polarity;         // GPIO polarity for CTF
+  uint8_t  pcc_gpio_bit;            // GPIO bit shift in SMU_GPIOPAD_A configured for PCC, =0xff means invalid
+  uint8_t  pcc_gpio_polarity;       // GPIO polarity for CTF
+  uint16_t smugoldenoffset;
+  uint32_t gpupll_vco_freq_10khz;
+  uint32_t bootup_smnclk_10khz;
+  uint32_t bootup_socclk_10khz;
+  uint32_t bootup_mp0clk_10khz;
+  uint32_t bootup_mp1clk_10khz;
+  uint32_t bootup_lclk_10khz;
+  uint32_t bootup_dcefclk_10khz;
+  uint32_t ctf_threshold_override_value;
+  uint32_t reserved[5];
+};
+
+struct atom_smu_info_v3_3 {
+  struct   atom_common_table_header  table_header;
+  uint8_t  smuip_min_ver;
+  uint8_t  smuip_max_ver;
+  uint8_t  smu_rsd1;
+  uint8_t  gpuclk_ss_mode;
+  uint16_t sclk_ss_percentage;
+  uint16_t sclk_ss_rate_10hz;
+  uint16_t gpuclk_ss_percentage;    // in unit of 0.001%
+  uint16_t gpuclk_ss_rate_10hz;
+  uint32_t core_refclk_10khz;
+  uint8_t  ac_dc_gpio_bit;          // GPIO bit shift in SMU_GPIOPAD_A  configured for AC/DC switching, =0xff means invalid
+  uint8_t  ac_dc_polarity;          // GPIO polarity for AC/DC switching
+  uint8_t  vr0hot_gpio_bit;         // GPIO bit shift in SMU_GPIOPAD_A  configured for VR0 HOT event, =0xff means invalid
+  uint8_t  vr0hot_polarity;         // GPIO polarity for VR0 HOT event
+  uint8_t  vr1hot_gpio_bit;         // GPIO bit shift in SMU_GPIOPAD_A configured for VR1 HOT event , =0xff means invalid
+  uint8_t  vr1hot_polarity;         // GPIO polarity for VR1 HOT event
+  uint8_t  fw_ctf_gpio_bit;         // GPIO bit shift in SMU_GPIOPAD_A configured for CTF, =0xff means invalid
+  uint8_t  fw_ctf_polarity;         // GPIO polarity for CTF
+  uint8_t  pcc_gpio_bit;            // GPIO bit shift in SMU_GPIOPAD_A configured for PCC, =0xff means invalid
+  uint8_t  pcc_gpio_polarity;       // GPIO polarity for CTF
+  uint16_t smugoldenoffset;
+  uint32_t gpupll_vco_freq_10khz;
+  uint32_t bootup_smnclk_10khz;
+  uint32_t bootup_socclk_10khz;
+  uint32_t bootup_mp0clk_10khz;
+  uint32_t bootup_mp1clk_10khz;
+  uint32_t bootup_lclk_10khz;
+  uint32_t bootup_dcefclk_10khz;
+  uint32_t ctf_threshold_override_value;
+  uint32_t syspll3_0_vco_freq_10khz;
+  uint32_t syspll3_1_vco_freq_10khz;
+  uint32_t bootup_fclk_10khz;
+  uint32_t bootup_waflclk_10khz;
+  uint32_t reserved[3];
+};
+
 /*
  ***************************************************************************
    Data Table smc_dpm_info  structure
@@ -1283,7 +1401,6 @@ struct atom_smc_dpm_info_v4_1
        uint32_t boardreserved[10];
 };
 
-
 /* 
   ***************************************************************************
     Data Table asic_profiling_info  structure
@@ -1864,6 +1981,55 @@ enum atom_smu9_syspll0_clock_id
   SMU9_SYSPLL0_DISPCLK_ID  = 11,      //       DISPCLK
 };
 
+enum atom_smu11_syspll_id {
+  SMU11_SYSPLL0_ID            = 0,
+  SMU11_SYSPLL1_0_ID          = 1,
+  SMU11_SYSPLL1_1_ID          = 2,
+  SMU11_SYSPLL1_2_ID          = 3,
+  SMU11_SYSPLL2_ID            = 4,
+  SMU11_SYSPLL3_0_ID          = 5,
+  SMU11_SYSPLL3_1_ID          = 6,
+};
+
+
+enum atom_smu11_syspll0_clock_id {
+  SMU11_SYSPLL0_SOCCLK_ID   = 0,       //      SOCCLK
+  SMU11_SYSPLL0_MP0CLK_ID   = 1,       //      MP0CLK
+  SMU11_SYSPLL0_DCLK_ID     = 2,       //      DCLK
+  SMU11_SYSPLL0_VCLK_ID     = 3,       //      VCLK
+  SMU11_SYSPLL0_ECLK_ID     = 4,       //      ECLK
+  SMU11_SYSPLL0_DCEFCLK_ID  = 5,       //      DCEFCLK
+};
+
+
+enum atom_smu11_syspll1_0_clock_id {
+  SMU11_SYSPLL1_0_UCLKA_ID   = 0,       // UCLK_a
+};
+
+enum atom_smu11_syspll1_1_clock_id {
+  SMU11_SYSPLL1_0_UCLKB_ID   = 0,       // UCLK_b
+};
+
+enum atom_smu11_syspll1_2_clock_id {
+  SMU11_SYSPLL1_0_FCLK_ID   = 0,        // FCLK
+};
+
+enum atom_smu11_syspll2_clock_id {
+  SMU11_SYSPLL2_GFXCLK_ID   = 0,        // GFXCLK
+};
+
+enum atom_smu11_syspll3_0_clock_id {
+  SMU11_SYSPLL3_0_WAFCLK_ID = 0,       //      WAFCLK
+  SMU11_SYSPLL3_0_DISPCLK_ID = 1,      //      DISPCLK
+  SMU11_SYSPLL3_0_DPREFCLK_ID = 2,     //      DPREFCLK
+};
+
+enum atom_smu11_syspll3_1_clock_id {
+  SMU11_SYSPLL3_1_MP1CLK_ID = 0,       //      MP1CLK
+  SMU11_SYSPLL3_1_SMNCLK_ID = 1,       //      SMNCLK
+  SMU11_SYSPLL3_1_LCLK_ID = 2,         //      LCLK
+};
+
 struct  atom_get_smu_clock_info_output_parameters_v3_1
 {
   union {
index 26fbeafc3c9654dbf4ed205c684c8097e0429c27..18b5b2ff47febeb13c0682994fb5e2bd57bb53ef 100644 (file)
 #define PCIE_BUS_CLK                10000
 #define TCLK                        (PCIE_BUS_CLK / 10)
 
-static const struct profile_mode_setting smu7_profiling[5] =
+static const struct profile_mode_setting smu7_profiling[6] =
                                        {{1, 0, 100, 30, 1, 0, 100, 10},
                                         {1, 10, 0, 30, 0, 0, 0, 0},
                                         {0, 0, 0, 0, 1, 10, 16, 31},
                                         {1, 0, 11, 50, 1, 0, 100, 10},
                                         {1, 0, 5, 30, 0, 0, 0, 0},
+                                        {0, 0, 0, 0, 0, 0, 0, 0},
                                        };
 
 /** Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */
@@ -4864,6 +4865,17 @@ static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
        len = sizeof(smu7_profiling) / sizeof(struct profile_mode_setting);
 
        for (i = 0; i < len; i++) {
+               if (i == hwmgr->power_profile_mode) {
+                       size += sprintf(buf + size, "%3d %14s %s: %8d %16d %16d %16d %16d %16d\n",
+                       i, profile_name[i], "*",
+                       data->current_profile_setting.sclk_up_hyst,
+                       data->current_profile_setting.sclk_down_hyst,
+                       data->current_profile_setting.sclk_activity,
+                       data->current_profile_setting.mclk_up_hyst,
+                       data->current_profile_setting.mclk_down_hyst,
+                       data->current_profile_setting.mclk_activity);
+                       continue;
+               }
                if (smu7_profiling[i].bupdate_sclk)
                        size += sprintf(buf + size, "%3d %16s: %8d %16d %16d ",
                        i, profile_name[i], smu7_profiling[i].sclk_up_hyst,
@@ -4883,24 +4895,6 @@ static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
                        "-", "-", "-");
        }
 
-       size += sprintf(buf + size, "%3d %16s: %8d %16d %16d %16d %16d %16d\n",
-                       i, profile_name[i],
-                       data->custom_profile_setting.sclk_up_hyst,
-                       data->custom_profile_setting.sclk_down_hyst,
-                       data->custom_profile_setting.sclk_activity,
-                       data->custom_profile_setting.mclk_up_hyst,
-                       data->custom_profile_setting.mclk_down_hyst,
-                       data->custom_profile_setting.mclk_activity);
-
-       size += sprintf(buf + size, "%3s %16s: %8d %16d %16d %16d %16d %16d\n",
-                       "*", "CURRENT",
-                       data->current_profile_setting.sclk_up_hyst,
-                       data->current_profile_setting.sclk_down_hyst,
-                       data->current_profile_setting.sclk_activity,
-                       data->current_profile_setting.mclk_up_hyst,
-                       data->current_profile_setting.mclk_down_hyst,
-                       data->current_profile_setting.mclk_activity);
-
        return size;
 }
 
@@ -4939,16 +4933,16 @@ static int smu7_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint
                if (size < 8)
                        return -EINVAL;
 
-               data->custom_profile_setting.bupdate_sclk = input[0];
-               data->custom_profile_setting.sclk_up_hyst = input[1];
-               data->custom_profile_setting.sclk_down_hyst = input[2];
-               data->custom_profile_setting.sclk_activity = input[3];
-               data->custom_profile_setting.bupdate_mclk = input[4];
-               data->custom_profile_setting.mclk_up_hyst = input[5];
-               data->custom_profile_setting.mclk_down_hyst = input[6];
-               data->custom_profile_setting.mclk_activity = input[7];
-               if (!smum_update_dpm_settings(hwmgr, &data->custom_profile_setting)) {
-                       memcpy(&data->current_profile_setting, &data->custom_profile_setting, sizeof(struct profile_mode_setting));
+               tmp.bupdate_sclk = input[0];
+               tmp.sclk_up_hyst = input[1];
+               tmp.sclk_down_hyst = input[2];
+               tmp.sclk_activity = input[3];
+               tmp.bupdate_mclk = input[4];
+               tmp.mclk_up_hyst = input[5];
+               tmp.mclk_down_hyst = input[6];
+               tmp.mclk_activity = input[7];
+               if (!smum_update_dpm_settings(hwmgr, &tmp)) {
+                       memcpy(&data->current_profile_setting, &tmp, sizeof(struct profile_mode_setting));
                        hwmgr->power_profile_mode = mode;
                }
                break;
index f40179c9ca97795e94e749ca1f107711c93c31cf..b8d0bb37859507ba3d51d6f99b8968dd085823b0 100644 (file)
@@ -325,7 +325,6 @@ struct smu7_hwmgr {
        uint16_t                              mem_latency_high;
        uint16_t                              mem_latency_low;
        uint32_t                              vr_config;
-       struct profile_mode_setting           custom_profile_setting;
        struct profile_mode_setting           current_profile_setting;
 };
 
index 03bc7453f3b1e4db89eb24b515ee16d03fbd6228..d9e92e3065352e8b59d9cf2ccac53cdb94af1f9c 100644 (file)
@@ -852,12 +852,10 @@ int smu7_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n)
 {
        struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
 
-       n = (n & 0xff) << 8;
-
        if (data->power_containment_features &
                        POWERCONTAINMENT_FEATURE_PkgPwrLimit)
                return smum_send_msg_to_smc_with_parameter(hwmgr,
-                               PPSMC_MSG_PkgPwrSetLimit, n);
+                               PPSMC_MSG_PkgPwrSetLimit, n<<8);
        return 0;
 }
 
index 3aa65bdecb0e80aeb289486d1b705b52e0076856..684ac626ac53277ffe4e4be5c97576fd861b9dde 100644 (file)
@@ -74,6 +74,7 @@ config DRM_SIL_SII8620
        tristate "Silicon Image SII8620 HDMI/MHL bridge"
        depends on OF && RC_CORE
        select DRM_KMS_HELPER
+       imply EXTCON
        help
          Silicon Image SII8620 HDMI/MHL bridge chip driver.
 
index 7d25c42f22dbcf8d3efc8949b1db59999eda693e..c825c76edc1d1cfc25b7fa9b7ba6112a40e55184 100644 (file)
@@ -155,6 +155,8 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state)
                                                       state->connectors[i].state);
                state->connectors[i].ptr = NULL;
                state->connectors[i].state = NULL;
+               state->connectors[i].old_state = NULL;
+               state->connectors[i].new_state = NULL;
                drm_connector_put(connector);
        }
 
@@ -169,6 +171,8 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state)
 
                state->crtcs[i].ptr = NULL;
                state->crtcs[i].state = NULL;
+               state->crtcs[i].old_state = NULL;
+               state->crtcs[i].new_state = NULL;
        }
 
        for (i = 0; i < config->num_total_plane; i++) {
@@ -181,6 +185,8 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state)
                                                   state->planes[i].state);
                state->planes[i].ptr = NULL;
                state->planes[i].state = NULL;
+               state->planes[i].old_state = NULL;
+               state->planes[i].new_state = NULL;
        }
 
        for (i = 0; i < state->num_private_objs; i++) {
@@ -190,6 +196,8 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state)
                                                 state->private_objs[i].state);
                state->private_objs[i].ptr = NULL;
                state->private_objs[i].state = NULL;
+               state->private_objs[i].old_state = NULL;
+               state->private_objs[i].new_state = NULL;
        }
        state->num_private_objs = 0;
 
index a1b9338736e3be4aafc5522c217f75ce3dcea832..c2c21d839727869ef30a59245b75708d7c6fbcf7 100644 (file)
@@ -716,7 +716,7 @@ static void remove_compat_control_link(struct drm_device *dev)
        if (!minor)
                return;
 
-       name = kasprintf(GFP_KERNEL, "controlD%d", minor->index);
+       name = kasprintf(GFP_KERNEL, "controlD%d", minor->index + 64);
        if (!name)
                return;
 
index 39ac15ce47023055f5a2badb7e5a99c59e19b3dd..9e2ae02f31e08fbad87669a126761c015d25db44 100644 (file)
@@ -65,12 +65,13 @@ int drm_mode_create_dumb_ioctl(struct drm_device *dev,
                return -EINVAL;
 
        /* overflow checks for 32bit size calculations */
-       /* NOTE: DIV_ROUND_UP() can overflow */
+       if (args->bpp > U32_MAX - 8)
+               return -EINVAL;
        cpp = DIV_ROUND_UP(args->bpp, 8);
-       if (!cpp || cpp > 0xffffffffU / args->width)
+       if (cpp > U32_MAX / args->width)
                return -EINVAL;
        stride = cpp * args->width;
-       if (args->height > 0xffffffffU / stride)
+       if (args->height > U32_MAX / stride)
                return -EINVAL;
 
        /* test for wrap-around */
index e394799979a6eabce5c91a7a6b87773dd4b45186..6d9b9453707c5af4cbad984c790ce9538daa5d82 100644 (file)
@@ -212,6 +212,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
                return -ENOMEM;
 
        filp->private_data = priv;
+       filp->f_mode |= FMODE_UNSIGNED_OFFSET;
        priv->filp = filp;
        priv->pid = get_pid(task_pid(current));
        priv->minor = minor;
index abd84cbcf1c2ca763e71d4e493661f8bef22170f..09c4bc0b1859f7bc8412cc3dfb3806ddaa0d3134 100644 (file)
@@ -954,8 +954,6 @@ static int hdmi_create_connector(struct drm_encoder *encoder)
        drm_mode_connector_attach_encoder(connector, encoder);
 
        if (hdata->bridge) {
-               encoder->bridge = hdata->bridge;
-               hdata->bridge->encoder = encoder;
                ret = drm_bridge_attach(encoder, hdata->bridge, NULL);
                if (ret)
                        DRM_ERROR("Failed to attach bridge\n");
index 257299ec95c435ae08660f7f659f62c7577e2b1c..272c79f5f5bff856dfa4a29a2574a70ee72366cf 100644 (file)
@@ -473,7 +473,7 @@ static void vp_video_buffer(struct mixer_context *ctx,
                        chroma_addr[1] = chroma_addr[0] + 0x40;
                } else {
                        luma_addr[1] = luma_addr[0] + fb->pitches[0];
-                       chroma_addr[1] = chroma_addr[0] + fb->pitches[0];
+                       chroma_addr[1] = chroma_addr[0] + fb->pitches[1];
                }
        } else {
                luma_addr[1] = 0;
@@ -482,6 +482,7 @@ static void vp_video_buffer(struct mixer_context *ctx,
 
        spin_lock_irqsave(&ctx->reg_slock, flags);
 
+       vp_reg_write(ctx, VP_SHADOW_UPDATE, 1);
        /* interlace or progressive scan mode */
        val = (test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? ~0 : 0);
        vp_reg_writemask(ctx, VP_MODE, val, VP_MODE_LINE_SKIP);
@@ -495,21 +496,23 @@ static void vp_video_buffer(struct mixer_context *ctx,
        vp_reg_write(ctx, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) |
                VP_IMG_VSIZE(fb->height));
        /* chroma plane for NV12/NV21 is half the height of the luma plane */
-       vp_reg_write(ctx, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) |
+       vp_reg_write(ctx, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[1]) |
                VP_IMG_VSIZE(fb->height / 2));
 
        vp_reg_write(ctx, VP_SRC_WIDTH, state->src.w);
-       vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h);
        vp_reg_write(ctx, VP_SRC_H_POSITION,
                        VP_SRC_H_POSITION_VAL(state->src.x));
-       vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y);
-
        vp_reg_write(ctx, VP_DST_WIDTH, state->crtc.w);
        vp_reg_write(ctx, VP_DST_H_POSITION, state->crtc.x);
+
        if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) {
+               vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h / 2);
+               vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y / 2);
                vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h / 2);
                vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y / 2);
        } else {
+               vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h);
+               vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y);
                vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h);
                vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y);
        }
@@ -699,6 +702,15 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
 
                /* interlace scan need to check shadow register */
                if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) {
+                       if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags) &&
+                           vp_reg_read(ctx, VP_SHADOW_UPDATE))
+                               goto out;
+
+                       base = mixer_reg_read(ctx, MXR_CFG);
+                       shadow = mixer_reg_read(ctx, MXR_CFG_S);
+                       if (base != shadow)
+                               goto out;
+
                        base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(0));
                        shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(0));
                        if (base != shadow)
index c311f571bdf9ec522f938c5cc4891acf9c1026b2..189cfa2470a850a65db8b619d27c8ab58d4e27b1 100644 (file)
@@ -47,6 +47,7 @@
 #define MXR_MO                         0x0304
 #define MXR_RESOLUTION                 0x0310
 
+#define MXR_CFG_S                      0x2004
 #define MXR_GRAPHIC0_BASE_S            0x2024
 #define MXR_GRAPHIC1_BASE_S            0x2044
 
index d596a8302ca3cca529977a10ebc02965855525af..854bd51b9478a59d6b0c18820c85498674842a66 100644 (file)
@@ -778,6 +778,9 @@ i915_gem_userptr_ioctl(struct drm_device *dev,
                            I915_USERPTR_UNSYNCHRONIZED))
                return -EINVAL;
 
+       if (!args->user_size)
+               return -EINVAL;
+
        if (offset_in_page(args->user_ptr | args->user_size))
                return -EINVAL;
 
index e6a8c0ee7df113704d103eab2b1f7586253970f7..8a69a9275e28d3c87a4443bb950d7ab2d6351a9c 100644 (file)
@@ -7326,6 +7326,9 @@ enum {
 #define SLICE_ECO_CHICKEN0                     _MMIO(0x7308)
 #define   PIXEL_MASK_CAMMING_DISABLE           (1 << 14)
 
+#define GEN9_WM_CHICKEN3                       _MMIO(0x5588)
+#define   GEN9_FACTOR_IN_CLR_VAL_HIZ           (1 << 9)
+
 /* WaCatErrorRejectionIssue */
 #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG         _MMIO(0x9030)
 #define  GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB      (1<<11)
index 32d24c69da3c699a0dd3a0b88a99429a1db929f8..704ddb4d3ca7ef6f40c565eeb07a5cbe8c427a97 100644 (file)
@@ -2302,9 +2302,44 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
        return 0;
 }
 
+static int skl_dpll0_vco(struct intel_atomic_state *intel_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(intel_state->base.dev);
+       struct intel_crtc *crtc;
+       struct intel_crtc_state *crtc_state;
+       int vco, i;
+
+       vco = intel_state->cdclk.logical.vco;
+       if (!vco)
+               vco = dev_priv->skl_preferred_vco_freq;
+
+       for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) {
+               if (!crtc_state->base.enable)
+                       continue;
+
+               if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
+                       continue;
+
+               /*
+                * DPLL0 VCO may need to be adjusted to get the correct
+                * clock for eDP. This will affect cdclk as well.
+                */
+               switch (crtc_state->port_clock / 2) {
+               case 108000:
+               case 216000:
+                       vco = 8640000;
+                       break;
+               default:
+                       vco = 8100000;
+                       break;
+               }
+       }
+
+       return vco;
+}
+
 static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
 {
-       struct drm_i915_private *dev_priv = to_i915(state->dev);
        struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
        int min_cdclk, cdclk, vco;
 
@@ -2312,9 +2347,7 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
        if (min_cdclk < 0)
                return min_cdclk;
 
-       vco = intel_state->cdclk.logical.vco;
-       if (!vco)
-               vco = dev_priv->skl_preferred_vco_freq;
+       vco = skl_dpll0_vco(intel_state);
 
        /*
         * FIXME should also account for plane ratio
index 3b48fd2561feccc48b5e0c549ee68e5d25214555..56004ffbd8bbf4499f87e92823ba10e38eff55da 100644 (file)
@@ -15178,6 +15178,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
                if (crtc_state->base.active) {
                        intel_mode_from_pipe_config(&crtc->base.mode, crtc_state);
+                       crtc->base.mode.hdisplay = crtc_state->pipe_src_w;
+                       crtc->base.mode.vdisplay = crtc_state->pipe_src_h;
                        intel_mode_from_pipe_config(&crtc_state->base.adjusted_mode, crtc_state);
                        WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode));
 
index 9a4a51e79fa12a8c75a773258d33db5214655ea6..b7b4cfdeb974a67c7eba222504ea8474d8bcd0df 100644 (file)
@@ -1881,26 +1881,6 @@ found:
                                reduce_m_n);
        }
 
-       /*
-        * DPLL0 VCO may need to be adjusted to get the correct
-        * clock for eDP. This will affect cdclk as well.
-        */
-       if (intel_dp_is_edp(intel_dp) && IS_GEN9_BC(dev_priv)) {
-               int vco;
-
-               switch (pipe_config->port_clock / 2) {
-               case 108000:
-               case 216000:
-                       vco = 8640000;
-                       break;
-               default:
-                       vco = 8100000;
-                       break;
-               }
-
-               to_intel_atomic_state(pipe_config->base.state)->cdclk.logical.vco = vco;
-       }
-
        if (!HAS_DDI(dev_priv))
                intel_dp_set_clock(encoder, pipe_config);
 
index 4ba139c27fbad43cb81435229e92bab7eba6a1e1..f7c25828d3bbacb743ecd468177cc510a5f16d4c 100644 (file)
@@ -1149,6 +1149,10 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine)
        WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_GPGPU_LEVEL_MASK,
                            GEN9_PREEMPT_GPGPU_COMMAND_LEVEL);
 
+       /* WaClearHIZ_WM_CHICKEN3:bxt,glk */
+       if (IS_GEN9_LP(dev_priv))
+               WA_SET_BIT_MASKED(GEN9_WM_CHICKEN3, GEN9_FACTOR_IN_CLR_VAL_HIZ);
+
        /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk,cfl */
        ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG);
        if (ret)
index e3a5f673ff673d2784bfc2bff7ca14c0a959578e..8704f7f8d0725664d41140dc2a3cd5e35d1aa612 100644 (file)
@@ -884,6 +884,7 @@ static void execlists_submission_tasklet(unsigned long data)
 
                        head = execlists->csb_head;
                        tail = READ_ONCE(buf[write_idx]);
+                       rmb(); /* Hopefully paired with a wmb() in HW */
                }
                GEM_TRACE("%s cs-irq head=%d [%d%s], tail=%d [%d%s]\n",
                          engine->name,
index d35d2d50f5951542bc58ec8bd19a51952300bb16..8691c86f579c7dc2eba793af80cd4ca0ce392595 100644 (file)
@@ -326,7 +326,8 @@ static void intel_enable_lvds(struct intel_encoder *encoder,
 
        I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | PANEL_POWER_ON);
        POSTING_READ(lvds_encoder->reg);
-       if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, PP_ON, 1000))
+
+       if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, PP_ON, 5000))
                DRM_ERROR("timed out waiting for panel to power on\n");
 
        intel_panel_enable_backlight(pipe_config, conn_state);
index 6f402c4f2bdd695cfe5d9344bcabba12e5a30e12..ab61c038f42c9d3eae6bc5c67ea3a9920cda8766 100644 (file)
@@ -214,7 +214,6 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align,
        INIT_LIST_HEAD(&nvbo->entry);
        INIT_LIST_HEAD(&nvbo->vma_list);
        nvbo->bo.bdev = &drm->ttm.bdev;
-       nvbo->cli = cli;
 
        /* This is confusing, and doesn't actually mean we want an uncached
         * mapping, but is what NOUVEAU_GEM_DOMAIN_COHERENT gets translated
index be8e00b49cdef1a961a7fcbd3f0cc25770be24cb..73c48440d4d7fb53cb3b09d6cb933b330489b0e0 100644 (file)
@@ -26,8 +26,6 @@ struct nouveau_bo {
 
        struct list_head vma_list;
 
-       struct nouveau_cli *cli;
-
        unsigned contig:1;
        unsigned page:5;
        unsigned kind:8;
index dff51a0ee0281e8f5924ffc0135d8b4baf8542f9..8c093ca4222e25b04b52096d4066159cdeb65451 100644 (file)
@@ -63,7 +63,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
                         struct ttm_mem_reg *reg)
 {
        struct nouveau_bo *nvbo = nouveau_bo(bo);
-       struct nouveau_drm *drm = nvbo->cli->drm;
+       struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
        struct nouveau_mem *mem;
        int ret;
 
@@ -103,7 +103,7 @@ nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
                         struct ttm_mem_reg *reg)
 {
        struct nouveau_bo *nvbo = nouveau_bo(bo);
-       struct nouveau_drm *drm = nvbo->cli->drm;
+       struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
        struct nouveau_mem *mem;
        int ret;
 
@@ -131,7 +131,7 @@ nv04_gart_manager_new(struct ttm_mem_type_manager *man,
                      struct ttm_mem_reg *reg)
 {
        struct nouveau_bo *nvbo = nouveau_bo(bo);
-       struct nouveau_drm *drm = nvbo->cli->drm;
+       struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
        struct nouveau_mem *mem;
        int ret;
 
index 8bd739cfd00d97f895ab2be06e3405e272e84992..2b3ccd85075058b86e0fb17e07eb9f3e791abf5e 100644 (file)
@@ -3264,10 +3264,11 @@ nv50_mstm_destroy_connector(struct drm_dp_mst_topology_mgr *mgr,
 
        drm_connector_unregister(&mstc->connector);
 
-       drm_modeset_lock_all(drm->dev);
        drm_fb_helper_remove_one_connector(&drm->fbcon->helper, &mstc->connector);
+
+       drm_modeset_lock(&drm->dev->mode_config.connection_mutex, NULL);
        mstc->port = NULL;
-       drm_modeset_unlock_all(drm->dev);
+       drm_modeset_unlock(&drm->dev->mode_config.connection_mutex);
 
        drm_connector_unreference(&mstc->connector);
 }
@@ -3277,9 +3278,7 @@ nv50_mstm_register_connector(struct drm_connector *connector)
 {
        struct nouveau_drm *drm = nouveau_drm(connector->dev);
 
-       drm_modeset_lock_all(drm->dev);
        drm_fb_helper_add_one_connector(&drm->fbcon->helper, connector);
-       drm_modeset_unlock_all(drm->dev);
 
        drm_connector_register(connector);
 }
index 5e2e65e888476f6bd39e17aa58a3b8e1137caf90..7f3ac6b13b56745540843bf92ff43fb3dab6f34c 100644 (file)
@@ -828,6 +828,12 @@ static void dispc_ovl_set_scale_coef(struct dispc_device *dispc,
        h_coef = dispc_ovl_get_scale_coef(fir_hinc, true);
        v_coef = dispc_ovl_get_scale_coef(fir_vinc, five_taps);
 
+       if (!h_coef || !v_coef) {
+               dev_err(&dispc->pdev->dev, "%s: failed to find scale coefs\n",
+                       __func__);
+               return;
+       }
+
        for (i = 0; i < 8; i++) {
                u32 h, hv;
 
@@ -2342,7 +2348,7 @@ static int dispc_ovl_calc_scaling_24xx(struct dispc_device *dispc,
        }
 
        if (in_width > maxsinglelinewidth) {
-               DSSERR("Cannot scale max input width exceeded");
+               DSSERR("Cannot scale max input width exceeded\n");
                return -EINVAL;
        }
        return 0;
@@ -2424,13 +2430,13 @@ again:
        }
 
        if (in_width > (maxsinglelinewidth * 2)) {
-               DSSERR("Cannot setup scaling");
-               DSSERR("width exceeds maximum width possible");
+               DSSERR("Cannot setup scaling\n");
+               DSSERR("width exceeds maximum width possible\n");
                return -EINVAL;
        }
 
        if (in_width > maxsinglelinewidth && *five_taps) {
-               DSSERR("cannot setup scaling with five taps");
+               DSSERR("cannot setup scaling with five taps\n");
                return -EINVAL;
        }
        return 0;
@@ -2472,7 +2478,7 @@ static int dispc_ovl_calc_scaling_44xx(struct dispc_device *dispc,
                        in_width > maxsinglelinewidth && ++*decim_x);
 
        if (in_width > maxsinglelinewidth) {
-               DSSERR("Cannot scale width exceeds max line width");
+               DSSERR("Cannot scale width exceeds max line width\n");
                return -EINVAL;
        }
 
@@ -2490,7 +2496,7 @@ static int dispc_ovl_calc_scaling_44xx(struct dispc_device *dispc,
                 * bandwidth. Despite what theory says this appears to
                 * be true also for 16-bit color formats.
                 */
-               DSSERR("Not enough bandwidth, too much downscaling (x-decimation factor %d > 4)", *decim_x);
+               DSSERR("Not enough bandwidth, too much downscaling (x-decimation factor %d > 4)\n", *decim_x);
 
                return -EINVAL;
        }
@@ -4633,7 +4639,7 @@ static int dispc_errata_i734_wa_init(struct dispc_device *dispc)
                                                i734_buf.size, &i734_buf.paddr,
                                                GFP_KERNEL);
        if (!i734_buf.vaddr) {
-               dev_err(&dispc->pdev->dev, "%s: dma_alloc_writecombine failed",
+               dev_err(&dispc->pdev->dev, "%s: dma_alloc_writecombine failed\n",
                        __func__);
                return -ENOMEM;
        }
index 97c88861d67aaf3ca19bf8f60d648095dd4427da..5879f45f6fc9bb5889f80884b7a352fcb6836363 100644 (file)
@@ -679,7 +679,7 @@ static int hdmi_audio_config(struct device *dev,
                             struct omap_dss_audio *dss_audio)
 {
        struct omap_hdmi *hd = dev_get_drvdata(dev);
-       int ret;
+       int ret = 0;
 
        mutex_lock(&hd->lock);
 
index 35ed2add6189c68e405dc5cf0715ad329c5ece9a..813ba42f27539ce94b85afc20295e411f6b4c123 100644 (file)
@@ -922,8 +922,13 @@ int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core)
 {
        const struct hdmi4_features *features;
        struct resource *res;
+       const struct soc_device_attribute *soc;
 
-       features = soc_device_match(hdmi4_soc_devices)->data;
+       soc = soc_device_match(hdmi4_soc_devices);
+       if (!soc)
+               return -ENODEV;
+
+       features = soc->data;
        core->cts_swmode = features->cts_swmode;
        core->audio_use_mclk = features->audio_use_mclk;
 
index d28da9ac3e900e57b2e6c762af197d9a04d0ea23..ae1a001d1b838ad32c7ae39a04a7103d6d7b99b1 100644 (file)
@@ -671,7 +671,7 @@ static int hdmi_audio_config(struct device *dev,
                             struct omap_dss_audio *dss_audio)
 {
        struct omap_hdmi *hd = dev_get_drvdata(dev);
-       int ret;
+       int ret = 0;
 
        mutex_lock(&hd->lock);
 
index a0d7b1d905e85500cc011d76fefb19453384a7fe..5cde26ac937bd3c88d7b4be1e2355ca196fe0c8d 100644 (file)
@@ -121,6 +121,9 @@ static int omap_connector_get_modes(struct drm_connector *connector)
        if (dssdrv->read_edid) {
                void *edid = kzalloc(MAX_EDID, GFP_KERNEL);
 
+               if (!edid)
+                       return 0;
+
                if ((dssdrv->read_edid(dssdev, edid, MAX_EDID) > 0) &&
                                drm_edid_is_valid(edid)) {
                        drm_mode_connector_update_edid_property(
@@ -139,6 +142,9 @@ static int omap_connector_get_modes(struct drm_connector *connector)
                struct drm_display_mode *mode = drm_mode_create(dev);
                struct videomode vm = {0};
 
+               if (!mode)
+                       return 0;
+
                dssdrv->get_timings(dssdev, &vm);
 
                drm_display_mode_from_videomode(&vm, mode);
@@ -200,6 +206,10 @@ static int omap_connector_mode_valid(struct drm_connector *connector,
        if (!r) {
                /* check if vrefresh is still valid */
                new_mode = drm_mode_duplicate(dev, mode);
+
+               if (!new_mode)
+                       return MODE_BAD;
+
                new_mode->clock = vm.pixelclock / 1000;
                new_mode->vrefresh = 0;
                if (mode->vrefresh == drm_mode_vrefresh(new_mode))
index f9fa1c90b35c6bda4f7a0a2461dc4f3e042cffdc..401c02e9e6b2e2b69e3bcaf35e1e390be09dc0b4 100644 (file)
@@ -401,12 +401,16 @@ int tiler_unpin(struct tiler_block *block)
 struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, u16 w,
                u16 h, u16 align)
 {
-       struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
+       struct tiler_block *block;
        u32 min_align = 128;
        int ret;
        unsigned long flags;
        u32 slot_bytes;
 
+       block = kzalloc(sizeof(*block), GFP_KERNEL);
+       if (!block)
+               return ERR_PTR(-ENOMEM);
+
        BUG_ON(!validfmt(fmt));
 
        /* convert width/height to slots */
index d7f7bc9f061af0a989ebe7924bd624dea4266786..817be3c418634f6a889a6e8f22652889d299761a 100644 (file)
@@ -90,7 +90,7 @@ static int l2r_t2b(u16 w, u16 h, u16 a, s16 offset,
 {
        int i;
        unsigned long index;
-       bool area_free;
+       bool area_free = false;
        unsigned long slots_per_band = PAGE_SIZE / slot_bytes;
        unsigned long bit_offset = (offset > 0) ? offset / slot_bytes : 0;
        unsigned long curr_bit = bit_offset;
index f0481b7b60c5e5330d12ecda16f7c08d258bcc2f..06c94e3a5f1521b0759148ede50b85752183e6bc 100644 (file)
@@ -910,7 +910,8 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
                        while (npages >= HPAGE_PMD_NR) {
                                gfp_t huge_flags = gfp_flags;
 
-                               huge_flags |= GFP_TRANSHUGE;
+                               huge_flags |= GFP_TRANSHUGE_LIGHT | __GFP_NORETRY |
+                                       __GFP_KSWAPD_RECLAIM;
                                huge_flags &= ~__GFP_MOVABLE;
                                huge_flags &= ~__GFP_COMP;
                                p = alloc_pages(huge_flags, HPAGE_PMD_ORDER);
@@ -1027,11 +1028,15 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages)
                                  GFP_USER | GFP_DMA32, "uc dma", 0);
 
        ttm_page_pool_init_locked(&_manager->wc_pool_huge,
-                                 GFP_TRANSHUGE & ~(__GFP_MOVABLE | __GFP_COMP),
+                                 (GFP_TRANSHUGE_LIGHT | __GFP_NORETRY |
+                                  __GFP_KSWAPD_RECLAIM) &
+                                 ~(__GFP_MOVABLE | __GFP_COMP),
                                  "wc huge", order);
 
        ttm_page_pool_init_locked(&_manager->uc_pool_huge,
-                                 GFP_TRANSHUGE & ~(__GFP_MOVABLE | __GFP_COMP)
+                                 (GFP_TRANSHUGE_LIGHT | __GFP_NORETRY |
+                                  __GFP_KSWAPD_RECLAIM) &
+                                 ~(__GFP_MOVABLE | __GFP_COMP)
                                  , "uc huge", order);
 
        _manager->options.max_size = max_pages;
index 8a25d197438509ab2112ae213d32c16a4627ff8e..f63d99c302e44fe2ca5bd9f9ab65e5e89af4c1a8 100644 (file)
@@ -910,7 +910,8 @@ static gfp_t ttm_dma_pool_gfp_flags(struct ttm_dma_tt *ttm_dma, bool huge)
                gfp_flags |= __GFP_ZERO;
 
        if (huge) {
-               gfp_flags |= GFP_TRANSHUGE;
+               gfp_flags |= GFP_TRANSHUGE_LIGHT | __GFP_NORETRY |
+                       __GFP_KSWAPD_RECLAIM;
                gfp_flags &= ~__GFP_MOVABLE;
                gfp_flags &= ~__GFP_COMP;
        }
index 72c9dbd81d7f4c61661924072a34f3a39fb3a170..f185812970da7a44aa7b82d6ae88942ae673ec9a 100644 (file)
@@ -96,7 +96,6 @@ struct vc4_dpi {
        struct platform_device *pdev;
 
        struct drm_encoder *encoder;
-       struct drm_connector *connector;
 
        void __iomem *regs;
 
@@ -164,14 +163,31 @@ static void vc4_dpi_encoder_disable(struct drm_encoder *encoder)
 
 static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
 {
+       struct drm_device *dev = encoder->dev;
        struct drm_display_mode *mode = &encoder->crtc->mode;
        struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder);
        struct vc4_dpi *dpi = vc4_encoder->dpi;
+       struct drm_connector_list_iter conn_iter;
+       struct drm_connector *connector = NULL, *connector_scan;
        u32 dpi_c = DPI_ENABLE | DPI_OUTPUT_ENABLE_MODE;
        int ret;
 
-       if (dpi->connector->display_info.num_bus_formats) {
-               u32 bus_format = dpi->connector->display_info.bus_formats[0];
+       /* Look up the connector attached to DPI so we can get the
+        * bus_format.  Ideally the bridge would tell us the
+        * bus_format we want, but it doesn't yet, so assume that it's
+        * uniform throughout the bridge chain.
+        */
+       drm_connector_list_iter_begin(dev, &conn_iter);
+       drm_for_each_connector_iter(connector_scan, &conn_iter) {
+               if (connector_scan->encoder == encoder) {
+                       connector = connector_scan;
+                       break;
+               }
+       }
+       drm_connector_list_iter_end(&conn_iter);
+
+       if (connector && connector->display_info.num_bus_formats) {
+               u32 bus_format = connector->display_info.bus_formats[0];
 
                switch (bus_format) {
                case MEDIA_BUS_FMT_RGB888_1X24:
@@ -199,6 +215,9 @@ static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
                        DRM_ERROR("Unknown media bus format %d\n", bus_format);
                        break;
                }
+       } else {
+               /* Default to 24bit if no connector found. */
+               dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB, DPI_FORMAT);
        }
 
        if (mode->flags & DRM_MODE_FLAG_NHSYNC)
index 94b99c90425a488cfaec255b1f2030f9b31242b3..7c95ed5c5cac0a6fc3358b7491f7e4e8e42eb9d2 100644 (file)
@@ -130,6 +130,7 @@ static void vc4_close(struct drm_device *dev, struct drm_file *file)
        struct vc4_file *vc4file = file->driver_priv;
 
        vc4_perfmon_close_file(vc4file);
+       kfree(vc4file);
 }
 
 static const struct vm_operations_struct vc4_vm_ops = {
index ce39390be389305bdd10a2641234785f465308f0..13dcaad06798d233b620872872c8ab50ee3c001f 100644 (file)
@@ -503,7 +503,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
         * the scl fields here.
         */
        if (num_planes == 1) {
-               scl0 = vc4_get_scl_field(state, 1);
+               scl0 = vc4_get_scl_field(state, 0);
                scl1 = scl0;
        } else {
                scl0 = vc4_get_scl_field(state, 1);
index 648f8127f65ae099baf3492031d30cd2c7280a64..3d667e903beb7bd76d13d8048a26a1763e835709 100644 (file)
@@ -482,6 +482,8 @@ vmw_sou_primary_plane_prepare_fb(struct drm_plane *plane,
                return ret;
        }
 
+       vps->dmabuf_size = size;
+
        /*
         * TTM already thinks the buffer is pinned, but make sure the
         * pin_count is upped.
index 60252fd796f6a86513b577f7b05cb3123ddeec81..0000434a1fbd253264d63b638d6841ef4476f2b6 100644 (file)
@@ -462,10 +462,11 @@ config HID_LENOVO
        select NEW_LEDS
        select LEDS_CLASS
        ---help---
-       Support for Lenovo devices that are not fully compliant with HID standard.
+       Support for IBM/Lenovo devices that are not fully compliant with HID standard.
 
-       Say Y if you want support for the non-compliant features of the Lenovo
-       Thinkpad standalone keyboards, e.g:
+       Say Y if you want support for horizontal scrolling of the IBM/Lenovo
+       Scrollpoint mice or the non-compliant features of the Lenovo Thinkpad
+       standalone keyboards, e.g:
        - ThinkPad USB Keyboard with TrackPoint (supports extra LEDs and trackpoint
          configuration)
        - ThinkPad Compact Bluetooth Keyboard with TrackPoint (supports Fn keys)
index 0b5cc910f62e560758f50bb03585ac27942ef199..46f5ecd11bf73b9d76b3614d8feb114440d4f65a 100644 (file)
 #define USB_VENDOR_ID_HUION            0x256c
 #define USB_DEVICE_ID_HUION_TABLET     0x006e
 
+#define USB_VENDOR_ID_IBM                                      0x04b3
+#define USB_DEVICE_ID_IBM_SCROLLPOINT_III                      0x3100
+#define USB_DEVICE_ID_IBM_SCROLLPOINT_PRO                      0x3103
+#define USB_DEVICE_ID_IBM_SCROLLPOINT_OPTICAL                  0x3105
+#define USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL           0x3108
+#define USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL_PRO       0x3109
+
 #define USB_VENDOR_ID_IDEACOM          0x1cb6
 #define USB_DEVICE_ID_IDEACOM_IDC6650  0x6650
 #define USB_DEVICE_ID_IDEACOM_IDC6651  0x6651
 #define USB_DEVICE_ID_LENOVO_TPKBD     0x6009
 #define USB_DEVICE_ID_LENOVO_CUSBKBD   0x6047
 #define USB_DEVICE_ID_LENOVO_CBTKBD    0x6048
+#define USB_DEVICE_ID_LENOVO_SCROLLPOINT_OPTICAL       0x6049
 #define USB_DEVICE_ID_LENOVO_TPPRODOCK 0x6067
 #define USB_DEVICE_ID_LENOVO_X1_COVER  0x6085
 #define USB_DEVICE_ID_LENOVO_X1_TAB    0x60a3
 #define USB_DEVICE_ID_SIS817_TOUCH     0x0817
 #define USB_DEVICE_ID_SIS_TS           0x1013
 #define USB_DEVICE_ID_SIS1030_TOUCH    0x1030
+#define USB_DEVICE_ID_SIS10FB_TOUCH    0x10fb
 
 #define USB_VENDOR_ID_SKYCABLE                 0x1223
 #define        USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER       0x3F07
index 1ac4ff4d57a659fc89c6a2bf36b83ba2d679fdcc..643b6eb54442ed4bc297e182ad1b7c77a25e82c0 100644 (file)
@@ -6,6 +6,17 @@
  *
  *  Copyright (c) 2012 Bernhard Seibold
  *  Copyright (c) 2014 Jamie Lentin <jm@lentin.co.uk>
+ *
+ * Linux IBM/Lenovo Scrollpoint mouse driver:
+ * - IBM Scrollpoint III
+ * - IBM Scrollpoint Pro
+ * - IBM Scrollpoint Optical
+ * - IBM Scrollpoint Optical 800dpi
+ * - IBM Scrollpoint Optical 800dpi Pro
+ * - Lenovo Scrollpoint Optical
+ *
+ *  Copyright (c) 2012 Peter De Wachter <pdewacht@gmail.com>
+ *  Copyright (c) 2018 Peter Ganzhorn <peter.ganzhorn@gmail.com>
  */
 
 /*
@@ -160,6 +171,17 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev,
        return 0;
 }
 
+static int lenovo_input_mapping_scrollpoint(struct hid_device *hdev,
+               struct hid_input *hi, struct hid_field *field,
+               struct hid_usage *usage, unsigned long **bit, int *max)
+{
+       if (usage->hid == HID_GD_Z) {
+               hid_map_usage(hi, usage, bit, max, EV_REL, REL_HWHEEL);
+               return 1;
+       }
+       return 0;
+}
+
 static int lenovo_input_mapping(struct hid_device *hdev,
                struct hid_input *hi, struct hid_field *field,
                struct hid_usage *usage, unsigned long **bit, int *max)
@@ -172,6 +194,14 @@ static int lenovo_input_mapping(struct hid_device *hdev,
        case USB_DEVICE_ID_LENOVO_CBTKBD:
                return lenovo_input_mapping_cptkbd(hdev, hi, field,
                                                        usage, bit, max);
+       case USB_DEVICE_ID_IBM_SCROLLPOINT_III:
+       case USB_DEVICE_ID_IBM_SCROLLPOINT_PRO:
+       case USB_DEVICE_ID_IBM_SCROLLPOINT_OPTICAL:
+       case USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL:
+       case USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL_PRO:
+       case USB_DEVICE_ID_LENOVO_SCROLLPOINT_OPTICAL:
+               return lenovo_input_mapping_scrollpoint(hdev, hi, field,
+                                                       usage, bit, max);
        default:
                return 0;
        }
@@ -883,6 +913,12 @@ static const struct hid_device_id lenovo_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_SCROLLPOINT_III) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_SCROLLPOINT_PRO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_SCROLLPOINT_OPTICAL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_SCROLLPOINT_800DPI_OPTICAL_PRO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_SCROLLPOINT_OPTICAL) },
        { }
 };
 
index 963328674e93af929fde1e20a3dc3deff3d75569..cc33622253aa5d4051a1df57fd815e0c5840185c 100644 (file)
@@ -174,6 +174,8 @@ static const struct i2c_hid_quirks {
                I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
        { I2C_VENDOR_ID_RAYD, I2C_PRODUCT_ID_RAYD_3118,
                I2C_HID_QUIRK_RESEND_REPORT_DESCR },
+       { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS10FB_TOUCH,
+               I2C_HID_QUIRK_RESEND_REPORT_DESCR },
        { 0, 0 }
 };
 
index 157b44aacdffb60203cb154680f9d02a94115fdc..acc2536c80948522f66873f6e61da1499502066a 100644 (file)
@@ -77,21 +77,21 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
        struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data;
        int curr_hid_dev = client_data->cur_hid_dev;
 
-       if (data_len < sizeof(struct hostif_msg_hdr)) {
-               dev_err(&client_data->cl_device->dev,
-                       "[hid-ish]: error, received %u which is less than data header %u\n",
-                       (unsigned int)data_len,
-                       (unsigned int)sizeof(struct hostif_msg_hdr));
-               ++client_data->bad_recv_cnt;
-               ish_hw_reset(hid_ishtp_cl->dev);
-               return;
-       }
-
        payload = recv_buf + sizeof(struct hostif_msg_hdr);
        total_len = data_len;
        cur_pos = 0;
 
        do {
+               if (cur_pos + sizeof(struct hostif_msg) > total_len) {
+                       dev_err(&client_data->cl_device->dev,
+                               "[hid-ish]: error, received %u which is less than data header %u\n",
+                               (unsigned int)data_len,
+                               (unsigned int)sizeof(struct hostif_msg_hdr));
+                       ++client_data->bad_recv_cnt;
+                       ish_hw_reset(hid_ishtp_cl->dev);
+                       break;
+               }
+
                recv_msg = (struct hostif_msg *)(recv_buf + cur_pos);
                payload_len = recv_msg->hdr.size;
 
@@ -412,9 +412,7 @@ void hid_ishtp_get_report(struct hid_device *hid, int report_id,
 {
        struct ishtp_hid_data *hid_data =  hid->driver_data;
        struct ishtp_cl_data *client_data = hid_data->client_data;
-       static unsigned char    buf[10];
-       unsigned int    len;
-       struct hostif_msg_to_sensor *msg = (struct hostif_msg_to_sensor *)buf;
+       struct hostif_msg_to_sensor msg = {};
        int     rv;
        int     i;
 
@@ -426,14 +424,11 @@ void hid_ishtp_get_report(struct hid_device *hid, int report_id,
                return;
        }
 
-       len = sizeof(struct hostif_msg_to_sensor);
-
-       memset(msg, 0, sizeof(struct hostif_msg_to_sensor));
-       msg->hdr.command = (report_type == HID_FEATURE_REPORT) ?
+       msg.hdr.command = (report_type == HID_FEATURE_REPORT) ?
                HOSTIF_GET_FEATURE_REPORT : HOSTIF_GET_INPUT_REPORT;
        for (i = 0; i < client_data->num_hid_devices; ++i) {
                if (hid == client_data->hid_sensor_hubs[i]) {
-                       msg->hdr.device_id =
+                       msg.hdr.device_id =
                                client_data->hid_devices[i].dev_id;
                        break;
                }
@@ -442,8 +437,9 @@ void hid_ishtp_get_report(struct hid_device *hid, int report_id,
        if (i == client_data->num_hid_devices)
                return;
 
-       msg->report_id = report_id;
-       rv = ishtp_cl_send(client_data->hid_ishtp_cl, buf, len);
+       msg.report_id = report_id;
+       rv = ishtp_cl_send(client_data->hid_ishtp_cl, (uint8_t *)&msg,
+                           sizeof(msg));
        if (rv)
                hid_ishtp_trace(client_data,  "%s hid %p send failed\n",
                                __func__, hid);
index f272cdd9bd558311c27a82729c5eb314cade2a1f..2623a567ffba5ae51e90653e47bea42127ea9b02 100644 (file)
@@ -418,7 +418,7 @@ static struct ishtp_cl_device *ishtp_bus_add_device(struct ishtp_device *dev,
                list_del(&device->device_link);
                spin_unlock_irqrestore(&dev->device_list_lock, flags);
                dev_err(dev->devc, "Failed to register ISHTP client device\n");
-               kfree(device);
+               put_device(&device->dev);
                return NULL;
        }
 
index b54ef1ffcbec329b99520365a63bf347d16a66d2..ee7a37eb159acf41fcb6c40ac685c7f659672b29 100644 (file)
@@ -1213,8 +1213,10 @@ static int __wacom_devm_sysfs_create_group(struct wacom *wacom,
        devres->root = root;
 
        error = sysfs_create_group(devres->root, group);
-       if (error)
+       if (error) {
+               devres_free(devres);
                return error;
+       }
 
        devres_add(&wacom->hdev->dev, devres);
 
index f249a442845804d8f22cdab29ec7e4a708874566..6ec307c93ecef937dbd47b1865df009b028c8d49 100644 (file)
@@ -272,7 +272,7 @@ config SENSORS_K8TEMP
 
 config SENSORS_K10TEMP
        tristate "AMD Family 10h+ temperature sensor"
-       depends on X86 && PCI
+       depends on X86 && PCI && AMD_NB
        help
          If you say yes here you get support for the temperature
          sensor(s) inside your CPU. Supported are later revisions of
index d2cc55e213747963de9cf5e061896032f1609fd5..3b73dee6fdc68ba6aa2619b083fb4c2dffbf063a 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <asm/amd_nb.h>
 #include <asm/processor.h>
 
 MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor");
@@ -40,8 +41,8 @@ static DEFINE_MUTEX(nb_smu_ind_mutex);
 #define PCI_DEVICE_ID_AMD_17H_DF_F3    0x1463
 #endif
 
-#ifndef PCI_DEVICE_ID_AMD_17H_RR_NB
-#define PCI_DEVICE_ID_AMD_17H_RR_NB    0x15d0
+#ifndef PCI_DEVICE_ID_AMD_17H_M10H_DF_F3
+#define PCI_DEVICE_ID_AMD_17H_M10H_DF_F3       0x15eb
 #endif
 
 /* CPUID function 0x80000001, ebx */
@@ -63,10 +64,12 @@ static DEFINE_MUTEX(nb_smu_ind_mutex);
 #define  NB_CAP_HTC                    0x00000400
 
 /*
- * For F15h M60h, functionality of REG_REPORTED_TEMPERATURE
- * has been moved to D0F0xBC_xD820_0CA4 [Reported Temperature
- * Control]
+ * For F15h M60h and M70h, REG_HARDWARE_THERMAL_CONTROL
+ * and REG_REPORTED_TEMPERATURE have been moved to
+ * D0F0xBC_xD820_0C64 [Hardware Temperature Control]
+ * D0F0xBC_xD820_0CA4 [Reported Temperature Control]
  */
+#define F15H_M60H_HARDWARE_TEMP_CTRL_OFFSET    0xd8200c64
 #define F15H_M60H_REPORTED_TEMP_CTRL_OFFSET    0xd8200ca4
 
 /* F17h M01h Access througn SMN */
@@ -74,6 +77,7 @@ static DEFINE_MUTEX(nb_smu_ind_mutex);
 
 struct k10temp_data {
        struct pci_dev *pdev;
+       void (*read_htcreg)(struct pci_dev *pdev, u32 *regval);
        void (*read_tempreg)(struct pci_dev *pdev, u32 *regval);
        int temp_offset;
        u32 temp_adjust_mask;
@@ -98,6 +102,11 @@ static const struct tctl_offset tctl_offset_table[] = {
        { 0x17, "AMD Ryzen Threadripper 1910", 10000 },
 };
 
+static void read_htcreg_pci(struct pci_dev *pdev, u32 *regval)
+{
+       pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, regval);
+}
+
 static void read_tempreg_pci(struct pci_dev *pdev, u32 *regval)
 {
        pci_read_config_dword(pdev, REG_REPORTED_TEMPERATURE, regval);
@@ -114,6 +123,12 @@ static void amd_nb_index_read(struct pci_dev *pdev, unsigned int devfn,
        mutex_unlock(&nb_smu_ind_mutex);
 }
 
+static void read_htcreg_nb_f15(struct pci_dev *pdev, u32 *regval)
+{
+       amd_nb_index_read(pdev, PCI_DEVFN(0, 0), 0xb8,
+                         F15H_M60H_HARDWARE_TEMP_CTRL_OFFSET, regval);
+}
+
 static void read_tempreg_nb_f15(struct pci_dev *pdev, u32 *regval)
 {
        amd_nb_index_read(pdev, PCI_DEVFN(0, 0), 0xb8,
@@ -122,8 +137,8 @@ static void read_tempreg_nb_f15(struct pci_dev *pdev, u32 *regval)
 
 static void read_tempreg_nb_f17(struct pci_dev *pdev, u32 *regval)
 {
-       amd_nb_index_read(pdev, PCI_DEVFN(0, 0), 0x60,
-                         F17H_M01H_REPORTED_TEMP_CTRL_OFFSET, regval);
+       amd_smn_read(amd_pci_dev_to_node_id(pdev),
+                    F17H_M01H_REPORTED_TEMP_CTRL_OFFSET, regval);
 }
 
 static ssize_t temp1_input_show(struct device *dev,
@@ -160,8 +175,7 @@ static ssize_t show_temp_crit(struct device *dev,
        u32 regval;
        int value;
 
-       pci_read_config_dword(data->pdev,
-                             REG_HARDWARE_THERMAL_CONTROL, &regval);
+       data->read_htcreg(data->pdev, &regval);
        value = ((regval >> 16) & 0x7f) * 500 + 52000;
        if (show_hyst)
                value -= ((regval >> 24) & 0xf) * 500;
@@ -181,13 +195,18 @@ static umode_t k10temp_is_visible(struct kobject *kobj,
        struct pci_dev *pdev = data->pdev;
 
        if (index >= 2) {
-               u32 reg_caps, reg_htc;
+               u32 reg;
+
+               if (!data->read_htcreg)
+                       return 0;
 
                pci_read_config_dword(pdev, REG_NORTHBRIDGE_CAPABILITIES,
-                                     &reg_caps);
-               pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL,
-                                     &reg_htc);
-               if (!(reg_caps & NB_CAP_HTC) || !(reg_htc & HTC_ENABLE))
+                                     &reg);
+               if (!(reg & NB_CAP_HTC))
+                       return 0;
+
+               data->read_htcreg(data->pdev, &reg);
+               if (!(reg & HTC_ENABLE))
                        return 0;
        }
        return attr->mode;
@@ -268,11 +287,13 @@ static int k10temp_probe(struct pci_dev *pdev,
 
        if (boot_cpu_data.x86 == 0x15 && (boot_cpu_data.x86_model == 0x60 ||
                                          boot_cpu_data.x86_model == 0x70)) {
+               data->read_htcreg = read_htcreg_nb_f15;
                data->read_tempreg = read_tempreg_nb_f15;
        } else if (boot_cpu_data.x86 == 0x17) {
                data->temp_adjust_mask = 0x80000;
                data->read_tempreg = read_tempreg_nb_f17;
        } else {
+               data->read_htcreg = read_htcreg_pci;
                data->read_tempreg = read_tempreg_pci;
        }
 
@@ -302,7 +323,7 @@ static const struct pci_device_id k10temp_id_table[] = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
-       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_RR_NB) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) },
        {}
 };
 MODULE_DEVICE_TABLE(pci, k10temp_id_table);
index fd36c39ddf4e86efd4ae8f12bd9f4ab9df4da860..0cdba29ae0a9ad25212f21a56acf76f46c1b5213 100644 (file)
@@ -209,7 +209,10 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
        i2c_dw_disable_int(dev);
 
        /* Enable the adapter */
-       __i2c_dw_enable_and_wait(dev, true);
+       __i2c_dw_enable(dev, true);
+
+       /* Dummy read to avoid the register getting stuck on Bay Trail */
+       dw_readl(dev, DW_IC_ENABLE_STATUS);
 
        /* Clear and enable interrupts */
        dw_readl(dev, DW_IC_CLR_INTR);
index 2aa0e83174c52895a0fb1416e8a17a00d31b24c6..dae8ac618a5221fdd886afab417f88945af7f143 100644 (file)
@@ -564,10 +564,10 @@ static int pmcmsptwi_master_xfer(struct i2c_adapter *adap,
                 * TODO: We could potentially loop and retry in the case
                 * of MSP_TWI_XFER_TIMEOUT.
                 */
-               return -1;
+               return -EIO;
        }
 
-       return 0;
+       return num;
 }
 
 static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter)
index e4be86b3de9a28b201bcd197470ab3a3a78ee683..7235c7302bb7cd000db814ec12de03193a22ef01 100644 (file)
@@ -337,7 +337,7 @@ static int vprbrd_i2c_xfer(struct i2c_adapter *i2c, struct i2c_msg *msgs,
                }
                mutex_unlock(&vb->lock);
        }
-       return 0;
+       return num;
 error:
        mutex_unlock(&vb->lock);
        return error;
index a9126b3cda61bc95f6a9d1282821ab7552484534..7c3b4740b94b644509ae3658fa2eda4885086bba 100644 (file)
@@ -445,10 +445,17 @@ static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
        msgs[1].buf = buffer;
 
        ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
-       if (ret < 0)
-               dev_err(&client->adapter->dev, "i2c read failed\n");
-       else
+       if (ret < 0) {
+               /* Getting a NACK is unfortunately normal with some DSTDs */
+               if (ret == -EREMOTEIO)
+                       dev_dbg(&client->adapter->dev, "i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\n",
+                               data_len, client->addr, cmd, ret);
+               else
+                       dev_err(&client->adapter->dev, "i2c read %d bytes from client@%#x starting at reg %#x failed, error: %d\n",
+                               data_len, client->addr, cmd, ret);
+       } else {
                memcpy(data, buffer, data_len);
+       }
 
        kfree(buffer);
        return ret;
index 2a99f0f14795549eacb6d88b87e30cc0ca78272e..8fb8c737fffefa18ac3ae716474a40002a36ff05 100644 (file)
@@ -83,7 +83,6 @@
 
 static DEFINE_SPINLOCK(amd_iommu_devtable_lock);
 static DEFINE_SPINLOCK(pd_bitmap_lock);
-static DEFINE_SPINLOCK(iommu_table_lock);
 
 /* List of all available dev_data structures */
 static LLIST_HEAD(dev_data_list);
@@ -3562,6 +3561,7 @@ EXPORT_SYMBOL(amd_iommu_device_info);
  *****************************************************************************/
 
 static struct irq_chip amd_ir_chip;
+static DEFINE_SPINLOCK(iommu_table_lock);
 
 static void set_dte_irq_entry(u16 devid, struct irq_remap_table *table)
 {
index f05f3cf9075675a4e466bda1d0621376fb5fea44..ddcbbdb5d65806dd7bc1e98ac95eed37c5752ca4 100644 (file)
@@ -167,40 +167,16 @@ EXPORT_SYMBOL(iommu_put_dma_cookie);
  * @list: Reserved region list from iommu_get_resv_regions()
  *
  * IOMMU drivers can use this to implement their .get_resv_regions callback
- * for general non-IOMMU-specific reservations. Currently, this covers host
- * bridge windows for PCI devices and GICv3 ITS region reservation on ACPI
- * based ARM platforms that may require HW MSI reservation.
+ * for general non-IOMMU-specific reservations. Currently, this covers GICv3
+ * ITS region reservation on ACPI based ARM platforms that may require HW MSI
+ * reservation.
  */
 void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
 {
-       struct pci_host_bridge *bridge;
-       struct resource_entry *window;
-
-       if (!is_of_node(dev->iommu_fwspec->iommu_fwnode) &&
-               iort_iommu_msi_get_resv_regions(dev, list) < 0)
-               return;
-
-       if (!dev_is_pci(dev))
-               return;
-
-       bridge = pci_find_host_bridge(to_pci_dev(dev)->bus);
-       resource_list_for_each_entry(window, &bridge->windows) {
-               struct iommu_resv_region *region;
-               phys_addr_t start;
-               size_t length;
-
-               if (resource_type(window->res) != IORESOURCE_MEM)
-                       continue;
 
-               start = window->res->start - window->offset;
-               length = window->res->end - window->res->start + 1;
-               region = iommu_alloc_resv_region(start, length, 0,
-                               IOMMU_RESV_RESERVED);
-               if (!region)
-                       return;
+       if (!is_of_node(dev->iommu_fwspec->iommu_fwnode))
+               iort_iommu_msi_get_resv_regions(dev, list);
 
-               list_add_tail(&region->list, list);
-       }
 }
 EXPORT_SYMBOL(iommu_dma_get_resv_regions);
 
@@ -229,6 +205,23 @@ static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie,
        return 0;
 }
 
+static void iova_reserve_pci_windows(struct pci_dev *dev,
+               struct iova_domain *iovad)
+{
+       struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus);
+       struct resource_entry *window;
+       unsigned long lo, hi;
+
+       resource_list_for_each_entry(window, &bridge->windows) {
+               if (resource_type(window->res) != IORESOURCE_MEM)
+                       continue;
+
+               lo = iova_pfn(iovad, window->res->start - window->offset);
+               hi = iova_pfn(iovad, window->res->end - window->offset);
+               reserve_iova(iovad, lo, hi);
+       }
+}
+
 static int iova_reserve_iommu_regions(struct device *dev,
                struct iommu_domain *domain)
 {
@@ -238,6 +231,9 @@ static int iova_reserve_iommu_regions(struct device *dev,
        LIST_HEAD(resv_regions);
        int ret = 0;
 
+       if (dev_is_pci(dev))
+               iova_reserve_pci_windows(to_pci_dev(dev), iovad);
+
        iommu_get_resv_regions(dev, &resv_regions);
        list_for_each_entry(region, &resv_regions, list) {
                unsigned long lo, hi;
index accf58388bdb4892369f0bac43f928667e937035..460bed4fc5b159ecd12d99a8ea770b0d90369b8a 100644 (file)
@@ -1345,7 +1345,7 @@ void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep,
        struct qi_desc desc;
 
        if (mask) {
-               BUG_ON(addr & ((1 << (VTD_PAGE_SHIFT + mask)) - 1));
+               WARN_ON_ONCE(addr & ((1ULL << (VTD_PAGE_SHIFT + mask)) - 1));
                addr |= (1ULL << (VTD_PAGE_SHIFT + mask - 1)) - 1;
                desc.high = QI_DEV_IOTLB_ADDR(addr) | QI_DEV_IOTLB_SIZE;
        } else
index 66f69af2c2191f6a247a82acc227ed64b85c6bff..3062a154a9fbf31cfa296ad6b50c2cd3471ad400 100644 (file)
@@ -1136,7 +1136,7 @@ static void intel_ir_reconfigure_irte(struct irq_data *irqd, bool force)
        irte->dest_id = IRTE_DEST(cfg->dest_apicid);
 
        /* Update the hardware only if the interrupt is in remapped mode. */
-       if (!force || ir_data->irq_2_iommu.mode == IRQ_REMAPPING)
+       if (force || ir_data->irq_2_iommu.mode == IRQ_REMAPPING)
                modify_irte(&ir_data->irq_2_iommu, irte);
 }
 
index 5fc8656c60f968b30148eaabbeefa4e63a2f40e2..0468acfa131fe4d1904260561c8f3052673ae0a6 100644 (file)
@@ -1098,7 +1098,7 @@ static int rk_iommu_of_xlate(struct device *dev,
        data->iommu = platform_get_drvdata(iommu_dev);
        dev->archdata.iommu = data;
 
-       of_dev_put(iommu_dev);
+       platform_device_put(iommu_dev);
 
        return 0;
 }
@@ -1175,8 +1175,15 @@ static int rk_iommu_probe(struct platform_device *pdev)
        for (i = 0; i < iommu->num_clocks; ++i)
                iommu->clocks[i].id = rk_iommu_clocks[i];
 
+       /*
+        * iommu clocks should be present for all new devices and devicetrees
+        * but there are older devicetrees without clocks out in the wild.
+        * So clocks as optional for the time being.
+        */
        err = devm_clk_bulk_get(iommu->dev, iommu->num_clocks, iommu->clocks);
-       if (err)
+       if (err == -ENOENT)
+               iommu->num_clocks = 0;
+       else if (err)
                return err;
 
        err = clk_bulk_prepare(iommu->num_clocks, iommu->clocks);
index f31265937439608314bf55d70665b55a299a4666..7f0c0be322e08a848bd42cc906c706315816f2c4 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -68,7 +68,7 @@ static void combiner_handle_irq(struct irq_desc *desc)
 
                bit = readl_relaxed(combiner->regs[reg].addr);
                status = bit & combiner->regs[reg].enabled;
-               if (!status)
+               if (bit && !status)
                        pr_warn_ratelimited("Unexpected IRQ on CPU%d: (%08x %08lx %p)\n",
                                            smp_processor_id(), bit,
                                            combiner->regs[reg].enabled,
index 4e63c6f6c04dfed91f94627dcd6a484a1de1652f..d030ce3025a6a6f365cb55c740e436ba43fd52bf 100644 (file)
@@ -250,7 +250,9 @@ void bch_debug_exit(void)
 
 int __init bch_debug_init(struct kobject *kobj)
 {
-       bcache_debug = debugfs_create_dir("bcache", NULL);
+       if (!IS_ENABLED(CONFIG_DEBUG_FS))
+               return 0;
 
+       bcache_debug = debugfs_create_dir("bcache", NULL);
        return IS_ERR_OR_NULL(bcache_debug);
 }
index 12aa9ca21d8c656166d819011adb00e4e7a5e4e0..dc385b70e4c336fc2322c9538f86538b000a8556 100644 (file)
@@ -1681,8 +1681,9 @@ struct dm_bufio_client *dm_bufio_client_create(struct block_device *bdev, unsign
 
        if (block_size <= KMALLOC_MAX_SIZE &&
            (block_size < PAGE_SIZE || !is_power_of_2(block_size))) {
-               snprintf(slab_name, sizeof slab_name, "dm_bufio_cache-%u", c->block_size);
-               c->slab_cache = kmem_cache_create(slab_name, c->block_size, ARCH_KMALLOC_MINALIGN,
+               unsigned align = min(1U << __ffs(block_size), (unsigned)PAGE_SIZE);
+               snprintf(slab_name, sizeof slab_name, "dm_bufio_cache-%u", block_size);
+               c->slab_cache = kmem_cache_create(slab_name, block_size, align,
                                                  SLAB_RECLAIM_ACCOUNT, NULL);
                if (!c->slab_cache) {
                        r = -ENOMEM;
index 1d0af0a21fc7e8253ebdba8e47e581e7b112ef3b..84814e819e4c35130ad6444feb88082c37c35768 100644 (file)
@@ -166,7 +166,7 @@ static bool max_work_reached(struct background_tracker *b)
                atomic_read(&b->pending_demotes) >= b->max_work;
 }
 
-struct bt_work *alloc_work(struct background_tracker *b)
+static struct bt_work *alloc_work(struct background_tracker *b)
 {
        if (max_work_reached(b))
                return NULL;
index 77d9fe58dae22118e872571da2a0542a7fe44b08..514fb4aec5d162b25caa7b0d30f200f66ad8a0c3 100644 (file)
@@ -2440,7 +2440,7 @@ static void dm_integrity_free_journal_scatterlist(struct dm_integrity_c *ic, str
        unsigned i;
        for (i = 0; i < ic->journal_sections; i++)
                kvfree(sl[i]);
-       kfree(sl);
+       kvfree(sl);
 }
 
 static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_integrity_c *ic, struct page_list *pl)
index 580c49cc8079f7b7e82b915a552a0b2ef7030947..5903e492bb34a307deee617726d91464d7e3d462 100644 (file)
@@ -23,6 +23,8 @@
 
 #define MAX_RECOVERY 1 /* Maximum number of regions recovered in parallel. */
 
+#define MAX_NR_MIRRORS (DM_KCOPYD_MAX_REGIONS + 1)
+
 #define DM_RAID1_HANDLE_ERRORS 0x01
 #define DM_RAID1_KEEP_LOG      0x02
 #define errors_handled(p)      ((p)->features & DM_RAID1_HANDLE_ERRORS)
@@ -255,7 +257,7 @@ static int mirror_flush(struct dm_target *ti)
        unsigned long error_bits;
 
        unsigned int i;
-       struct dm_io_region io[ms->nr_mirrors];
+       struct dm_io_region io[MAX_NR_MIRRORS];
        struct mirror *m;
        struct dm_io_request io_req = {
                .bi_op = REQ_OP_WRITE,
@@ -651,7 +653,7 @@ static void write_callback(unsigned long error, void *context)
 static void do_write(struct mirror_set *ms, struct bio *bio)
 {
        unsigned int i;
-       struct dm_io_region io[ms->nr_mirrors], *dest = io;
+       struct dm_io_region io[MAX_NR_MIRRORS], *dest = io;
        struct mirror *m;
        struct dm_io_request io_req = {
                .bi_op = REQ_OP_WRITE,
@@ -1083,7 +1085,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        argc -= args_used;
 
        if (!argc || sscanf(argv[0], "%u%c", &nr_mirrors, &dummy) != 1 ||
-           nr_mirrors < 2 || nr_mirrors > DM_KCOPYD_MAX_REGIONS + 1) {
+           nr_mirrors < 2 || nr_mirrors > MAX_NR_MIRRORS) {
                ti->error = "Invalid number of mirrors";
                dm_dirty_log_destroy(dl);
                return -EINVAL;
@@ -1404,7 +1406,7 @@ static void mirror_status(struct dm_target *ti, status_type_t type,
        int num_feature_args = 0;
        struct mirror_set *ms = (struct mirror_set *) ti->private;
        struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh);
-       char buffer[ms->nr_mirrors + 1];
+       char buffer[MAX_NR_MIRRORS + 1];
 
        switch (type) {
        case STATUSTYPE_INFO:
index 4ea404dbcf0b936b3cc3c42dc76158813ecb88ec..0a7b0107ca78d8ed967e546f9111b0a57e987421 100644 (file)
@@ -1020,7 +1020,8 @@ int dm_set_target_max_io_len(struct dm_target *ti, sector_t len)
 EXPORT_SYMBOL_GPL(dm_set_target_max_io_len);
 
 static struct dm_target *dm_dax_get_live_target(struct mapped_device *md,
-               sector_t sector, int *srcu_idx)
+                                               sector_t sector, int *srcu_idx)
+       __acquires(md->io_barrier)
 {
        struct dm_table *map;
        struct dm_target *ti;
@@ -1037,7 +1038,7 @@ static struct dm_target *dm_dax_get_live_target(struct mapped_device *md,
 }
 
 static long dm_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
-               long nr_pages, void **kaddr, pfn_t *pfn)
+                                long nr_pages, void **kaddr, pfn_t *pfn)
 {
        struct mapped_device *md = dax_get_private(dax_dev);
        sector_t sector = pgoff * PAGE_SECTORS;
@@ -1065,7 +1066,7 @@ static long dm_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff,
 }
 
 static size_t dm_dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff,
-               void *addr, size_t bytes, struct iov_iter *i)
+                                   void *addr, size_t bytes, struct iov_iter *i)
 {
        struct mapped_device *md = dax_get_private(dax_dev);
        sector_t sector = pgoff * PAGE_SECTORS;
index a4c9c8297a6d825db6321032f7125aa01c9ca751..918d4fb742d1dd98dc3475adf4eef4feeafa7fdf 100644 (file)
@@ -717,6 +717,7 @@ struct cxl {
        bool perst_select_user;
        bool perst_same_image;
        bool psl_timebase_synced;
+       bool tunneled_ops_supported;
 
        /*
         * number of contexts mapped on to this card. Possible values are:
index 83f1d08058fc234dc9b141b543084ece35c53b0f..4d6736f9d46399b0ea2f1336404acd041af91c86 100644 (file)
@@ -1742,6 +1742,15 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev)
        /* Required for devices using CAPP DMA mode, harmless for others */
        pci_set_master(dev);
 
+       adapter->tunneled_ops_supported = false;
+
+       if (cxl_is_power9()) {
+               if (pnv_pci_set_tunnel_bar(dev, 0x00020000E0000000ull, 1))
+                       dev_info(&dev->dev, "Tunneled operations unsupported\n");
+               else
+                       adapter->tunneled_ops_supported = true;
+       }
+
        if ((rc = pnv_phb_to_cxl_mode(dev, adapter->native->sl_ops->capi_mode)))
                goto err;
 
@@ -1768,6 +1777,9 @@ static void cxl_deconfigure_adapter(struct cxl *adapter)
 {
        struct pci_dev *pdev = to_pci_dev(adapter->dev.parent);
 
+       if (cxl_is_power9())
+               pnv_pci_set_tunnel_bar(pdev, 0x00020000E0000000ull, 0);
+
        cxl_native_release_psl_err_irq(adapter);
        cxl_unmap_adapter_regs(adapter);
 
index 95285b7f636ff3f854876e5743658f91d88c3e3d..4b5a4c5d3c012dff77508b9f0b8b9883671e594c 100644 (file)
@@ -78,6 +78,15 @@ static ssize_t psl_timebase_synced_show(struct device *device,
        return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->psl_timebase_synced);
 }
 
+static ssize_t tunneled_ops_supported_show(struct device *device,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct cxl *adapter = to_cxl_adapter(device);
+
+       return scnprintf(buf, PAGE_SIZE, "%i\n", adapter->tunneled_ops_supported);
+}
+
 static ssize_t reset_adapter_store(struct device *device,
                                   struct device_attribute *attr,
                                   const char *buf, size_t count)
@@ -183,6 +192,7 @@ static struct device_attribute adapter_attrs[] = {
        __ATTR_RO(base_image),
        __ATTR_RO(image_loaded),
        __ATTR_RO(psl_timebase_synced),
+       __ATTR_RO(tunneled_ops_supported),
        __ATTR_RW(load_image_on_perst),
        __ATTR_RW(perst_reloads_same_image),
        __ATTR(reset, S_IWUSR, NULL, reset_adapter_store),
index 0c125f207aea82c394f989f5033fccda9cd7e0b1..33053b0d1fdf65c2d590598cd361b7869e663522 100644 (file)
@@ -518,7 +518,7 @@ static int at24_get_pdata(struct device *dev, struct at24_platform_data *pdata)
        if (of_node && of_match_device(at24_of_match, dev))
                cdata = of_device_get_match_data(dev);
        else if (id)
-               cdata = (void *)&id->driver_data;
+               cdata = (void *)id->driver_data;
        else
                cdata = acpi_device_get_match_data(dev);
 
index 9c159f0dd9a61183892bb067c41dac17386c56e6..321137158ff3161a1c89aa7f1a6ad51fa91647c4 100644 (file)
@@ -375,56 +375,42 @@ static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
 {
        struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
        struct onenand_chip *this = mtd->priv;
-       dma_addr_t dma_src, dma_dst;
-       int bram_offset;
+       struct device *dev = &c->pdev->dev;
        void *buf = (void *)buffer;
+       dma_addr_t dma_src, dma_dst;
+       int bram_offset, err;
        size_t xtra;
-       int ret;
 
        bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
-       if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
-               goto out_copy;
-
-       /* panic_write() may be in an interrupt context */
-       if (in_interrupt() || oops_in_progress)
+       /*
+        * If the buffer address is not DMA-able, len is not long enough to make
+        * DMA transfers profitable or panic_write() may be in an interrupt
+        * context fallback to PIO mode.
+        */
+       if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 ||
+           count < 384 || in_interrupt() || oops_in_progress )
                goto out_copy;
 
-       if (buf >= high_memory) {
-               struct page *p1;
-
-               if (((size_t)buf & PAGE_MASK) !=
-                   ((size_t)(buf + count - 1) & PAGE_MASK))
-                       goto out_copy;
-               p1 = vmalloc_to_page(buf);
-               if (!p1)
-                       goto out_copy;
-               buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
-       }
-
        xtra = count & 3;
        if (xtra) {
                count -= xtra;
                memcpy(buf + count, this->base + bram_offset + count, xtra);
        }
 
+       dma_dst = dma_map_single(dev, buf, count, DMA_FROM_DEVICE);
        dma_src = c->phys_base + bram_offset;
-       dma_dst = dma_map_single(&c->pdev->dev, buf, count, DMA_FROM_DEVICE);
-       if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
-               dev_err(&c->pdev->dev,
-                       "Couldn't DMA map a %d byte buffer\n",
-                       count);
-               goto out_copy;
-       }
 
-       ret = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count);
-       dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
-
-       if (ret) {
-               dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
+       if (dma_mapping_error(dev, dma_dst)) {
+               dev_err(dev, "Couldn't DMA map a %d byte buffer\n", count);
                goto out_copy;
        }
 
-       return 0;
+       err = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count);
+       dma_unmap_single(dev, dma_dst, count, DMA_FROM_DEVICE);
+       if (!err)
+               return 0;
+
+       dev_err(dev, "timeout waiting for DMA\n");
 
 out_copy:
        memcpy(buf, this->base + bram_offset, count);
@@ -437,49 +423,34 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
 {
        struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
        struct onenand_chip *this = mtd->priv;
-       dma_addr_t dma_src, dma_dst;
-       int bram_offset;
+       struct device *dev = &c->pdev->dev;
        void *buf = (void *)buffer;
-       int ret;
+       dma_addr_t dma_src, dma_dst;
+       int bram_offset, err;
 
        bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
-       if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
-               goto out_copy;
-
-       /* panic_write() may be in an interrupt context */
-       if (in_interrupt() || oops_in_progress)
+       /*
+        * If the buffer address is not DMA-able, len is not long enough to make
+        * DMA transfers profitable or panic_write() may be in an interrupt
+        * context fallback to PIO mode.
+        */
+       if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 ||
+           count < 384 || in_interrupt() || oops_in_progress )
                goto out_copy;
 
-       if (buf >= high_memory) {
-               struct page *p1;
-
-               if (((size_t)buf & PAGE_MASK) !=
-                   ((size_t)(buf + count - 1) & PAGE_MASK))
-                       goto out_copy;
-               p1 = vmalloc_to_page(buf);
-               if (!p1)
-                       goto out_copy;
-               buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
-       }
-
-       dma_src = dma_map_single(&c->pdev->dev, buf, count, DMA_TO_DEVICE);
+       dma_src = dma_map_single(dev, buf, count, DMA_TO_DEVICE);
        dma_dst = c->phys_base + bram_offset;
-       if (dma_mapping_error(&c->pdev->dev, dma_src)) {
-               dev_err(&c->pdev->dev,
-                       "Couldn't DMA map a %d byte buffer\n",
-                       count);
-               return -1;
-       }
-
-       ret = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count);
-       dma_unmap_single(&c->pdev->dev, dma_src, count, DMA_TO_DEVICE);
-
-       if (ret) {
-               dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
+       if (dma_mapping_error(dev, dma_src)) {
+               dev_err(dev, "Couldn't DMA map a %d byte buffer\n", count);
                goto out_copy;
        }
 
-       return 0;
+       err = omap2_onenand_dma_transfer(c, dma_src, dma_dst, count);
+       dma_unmap_page(dev, dma_src, count, DMA_TO_DEVICE);
+       if (!err)
+               return 0;
+
+       dev_err(dev, "timeout waiting for DMA\n");
 
 out_copy:
        memcpy(this->base + bram_offset, buf, count);
index 1d779a35ac8ee03152f8d9b1a4f99df753995785..ebb1d141b90000c069b0634fe0a3c4d5d5f842d4 100644 (file)
@@ -1074,7 +1074,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip,
                return ret;
 
        ret = marvell_nfc_wait_op(chip,
-                                 chip->data_interface.timings.sdr.tPROG_max);
+                                 PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max));
        return ret;
 }
 
@@ -1194,11 +1194,13 @@ static void marvell_nfc_hw_ecc_bch_read_chunk(struct nand_chip *chip, int chunk,
                                  NDCB0_CMD2(NAND_CMD_READSTART);
 
        /*
-        * Trigger the naked read operation only on the last chunk.
-        * Otherwise, use monolithic read.
+        * Trigger the monolithic read on the first chunk, then naked read on
+        * intermediate chunks and finally a last naked read on the last chunk.
         */
-       if (lt->nchunks == 1 || (chunk < lt->nchunks - 1))
+       if (chunk == 0)
                nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_MONOLITHIC_RW);
+       else if (chunk < lt->nchunks - 1)
+               nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_NAKED_RW);
        else
                nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_LAST_NAKED_RW);
 
@@ -1408,6 +1410,7 @@ marvell_nfc_hw_ecc_bch_write_chunk(struct nand_chip *chip, int chunk,
        struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
        struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
        const struct marvell_hw_ecc_layout *lt = to_marvell_nand(chip)->layout;
+       u32 xtype;
        int ret;
        struct marvell_nfc_op nfc_op = {
                .ndcb[0] = NDCB0_CMD_TYPE(TYPE_WRITE) | NDCB0_LEN_OVRD,
@@ -1423,7 +1426,12 @@ marvell_nfc_hw_ecc_bch_write_chunk(struct nand_chip *chip, int chunk,
         * last naked write.
         */
        if (chunk == 0) {
-               nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(XTYPE_WRITE_DISPATCH) |
+               if (lt->nchunks == 1)
+                       xtype = XTYPE_MONOLITHIC_RW;
+               else
+                       xtype = XTYPE_WRITE_DISPATCH;
+
+               nfc_op.ndcb[0] |= NDCB0_CMD_XTYPE(xtype) |
                                  NDCB0_ADDR_CYC(marvell_nand->addr_cyc) |
                                  NDCB0_CMD1(NAND_CMD_SEQIN);
                nfc_op.ndcb[1] |= NDCB1_ADDRS_PAGE(page);
@@ -1494,7 +1502,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct mtd_info *mtd,
        }
 
        ret = marvell_nfc_wait_op(chip,
-                                 chip->data_interface.timings.sdr.tPROG_max);
+                                 PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max));
 
        marvell_nfc_disable_hw_ecc(chip);
 
index 72f3a89da513e20dacf87b9943c6ac87db5a2e2f..f28c3a5558619fa22842ed2bffab7e0b4d7141a6 100644 (file)
@@ -706,12 +706,17 @@ static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo)
  */
 int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
 {
+       const struct nand_sdr_timings *timings;
        u8 status = 0;
        int ret;
 
        if (!chip->exec_op)
                return -ENOTSUPP;
 
+       /* Wait tWB before polling the STATUS reg. */
+       timings = nand_get_sdr_timings(&chip->data_interface);
+       ndelay(PSEC_TO_NSEC(timings->tWB_max));
+
        ret = nand_status_op(chip, NULL);
        if (ret)
                return ret;
index 1ed9529e7bd1de923697731dc0db0ceaa926ef1f..5eb0df2e54642c9797efb012d2e10db20cd26949 100644 (file)
@@ -450,7 +450,7 @@ static void rlb_update_client(struct rlb_client_info *client_info)
 {
        int i;
 
-       if (!client_info->slave)
+       if (!client_info->slave || !is_valid_ether_addr(client_info->mac_dst))
                return;
 
        for (i = 0; i < RLB_ARP_BURST_SIZE; i++) {
@@ -943,6 +943,10 @@ static void alb_send_lp_vid(struct slave *slave, u8 mac_addr[],
        skb->priority = TC_PRIO_CONTROL;
        skb->dev = slave->dev;
 
+       netdev_dbg(slave->bond->dev,
+                  "Send learning packet: dev %s mac %pM vlan %d\n",
+                  slave->dev->name, mac_addr, vid);
+
        if (vid)
                __vlan_hwaccel_put_tag(skb, vlan_proto, vid);
 
@@ -965,14 +969,13 @@ static int alb_upper_dev_walk(struct net_device *upper, void *_data)
        u8 *mac_addr = data->mac_addr;
        struct bond_vlan_tag *tags;
 
-       if (is_vlan_dev(upper) && vlan_get_encap_level(upper) == 0) {
-               if (strict_match &&
-                   ether_addr_equal_64bits(mac_addr,
-                                           upper->dev_addr)) {
+       if (is_vlan_dev(upper) &&
+           bond->nest_level == vlan_get_encap_level(upper) - 1) {
+               if (upper->addr_assign_type == NET_ADDR_STOLEN) {
                        alb_send_lp_vid(slave, mac_addr,
                                        vlan_dev_vlan_proto(upper),
                                        vlan_dev_vlan_id(upper));
-               } else if (!strict_match) {
+               } else {
                        alb_send_lp_vid(slave, upper->dev_addr,
                                        vlan_dev_vlan_proto(upper),
                                        vlan_dev_vlan_id(upper));
index 718e4914e3a0b64b0c963e15478ca3c795542a60..1f1e97b26f958c83b156e060fab15c71d6e096ed 100644 (file)
@@ -1738,6 +1738,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
        if (bond_mode_uses_xmit_hash(bond))
                bond_update_slave_arr(bond, NULL);
 
+       bond->nest_level = dev_get_nest_level(bond_dev);
+
        netdev_info(bond_dev, "Enslaving %s as %s interface with %s link\n",
                    slave_dev->name,
                    bond_is_active_slave(new_slave) ? "an active" : "a backup",
index b1779566c5bbf15513d0dd9e5e880f55462c7e21..3c71f1cb205faaa98617eeb2f0f0e3c94a2f36e8 100644 (file)
@@ -605,7 +605,7 @@ void can_bus_off(struct net_device *dev)
 {
        struct can_priv *priv = netdev_priv(dev);
 
-       netdev_dbg(dev, "bus-off\n");
+       netdev_info(dev, "bus-off\n");
 
        netif_carrier_off(dev);
 
index 634c51e6b8ae5d7b73b4dea2180a631fdcfadeee..d53a45bf2a72eb9e0d3cd16fe9f876bccbe5ade5 100644 (file)
 #define FLEXCAN_QUIRK_DISABLE_MECR     BIT(4) /* Disable Memory error detection */
 #define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP        BIT(5) /* Use timestamp based offloading */
 #define FLEXCAN_QUIRK_BROKEN_PERR_STATE        BIT(6) /* No interrupt for error passive */
+#define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN       BIT(7) /* default to BE register access */
 
 /* Structure of the message buffer */
 struct flexcan_mb {
@@ -287,6 +288,12 @@ struct flexcan_priv {
 };
 
 static const struct flexcan_devtype_data fsl_p1010_devtype_data = {
+       .quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE |
+               FLEXCAN_QUIRK_BROKEN_PERR_STATE |
+               FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN,
+};
+
+static const struct flexcan_devtype_data fsl_imx25_devtype_data = {
        .quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE |
                FLEXCAN_QUIRK_BROKEN_PERR_STATE,
 };
@@ -1251,9 +1258,9 @@ static void unregister_flexcandev(struct net_device *dev)
 static const struct of_device_id flexcan_of_match[] = {
        { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
        { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
-       { .compatible = "fsl,imx53-flexcan", .data = &fsl_p1010_devtype_data, },
-       { .compatible = "fsl,imx35-flexcan", .data = &fsl_p1010_devtype_data, },
-       { .compatible = "fsl,imx25-flexcan", .data = &fsl_p1010_devtype_data, },
+       { .compatible = "fsl,imx53-flexcan", .data = &fsl_imx25_devtype_data, },
+       { .compatible = "fsl,imx35-flexcan", .data = &fsl_imx25_devtype_data, },
+       { .compatible = "fsl,imx25-flexcan", .data = &fsl_imx25_devtype_data, },
        { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
        { .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, },
        { .compatible = "fsl,ls1021ar2-flexcan", .data = &fsl_ls1021a_r2_devtype_data, },
@@ -1337,18 +1344,13 @@ static int flexcan_probe(struct platform_device *pdev)
 
        priv = netdev_priv(dev);
 
-       if (of_property_read_bool(pdev->dev.of_node, "big-endian")) {
+       if (of_property_read_bool(pdev->dev.of_node, "big-endian") ||
+           devtype_data->quirks & FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN) {
                priv->read = flexcan_read_be;
                priv->write = flexcan_write_be;
        } else {
-               if (of_device_is_compatible(pdev->dev.of_node,
-                                           "fsl,p1010-flexcan")) {
-                       priv->read = flexcan_read_be;
-                       priv->write = flexcan_write_be;
-               } else {
-                       priv->read = flexcan_read_le;
-                       priv->write = flexcan_write_le;
-               }
+               priv->read = flexcan_read_le;
+               priv->write = flexcan_write_le;
        }
 
        priv->can.clock.freq = clock_freq;
index 5590c559a8ca5305d4eb2ecac18fc8d406afebad..53e320c92a8be21e286ab4f7ada738fd223a08fa 100644 (file)
@@ -91,6 +91,7 @@
 #define HI3110_STAT_BUSOFF BIT(2)
 #define HI3110_STAT_ERRP BIT(3)
 #define HI3110_STAT_ERRW BIT(4)
+#define HI3110_STAT_TXMTY BIT(7)
 
 #define HI3110_BTR0_SJW_SHIFT 6
 #define HI3110_BTR0_BRP_SHIFT 0
@@ -427,8 +428,10 @@ static int hi3110_get_berr_counter(const struct net_device *net,
        struct hi3110_priv *priv = netdev_priv(net);
        struct spi_device *spi = priv->spi;
 
+       mutex_lock(&priv->hi3110_lock);
        bec->txerr = hi3110_read(spi, HI3110_READ_TEC);
        bec->rxerr = hi3110_read(spi, HI3110_READ_REC);
+       mutex_unlock(&priv->hi3110_lock);
 
        return 0;
 }
@@ -735,10 +738,7 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
                        }
                }
 
-               if (intf == 0)
-                       break;
-
-               if (intf & HI3110_INT_TXCPLT) {
+               if (priv->tx_len && statf & HI3110_STAT_TXMTY) {
                        net->stats.tx_packets++;
                        net->stats.tx_bytes += priv->tx_len - 1;
                        can_led_event(net, CAN_LED_EVENT_TX);
@@ -748,6 +748,9 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
                        }
                        netif_wake_queue(net);
                }
+
+               if (intf == 0)
+                       break;
        }
        mutex_unlock(&priv->hi3110_lock);
        return IRQ_HANDLED;
index 63587b8e6825add0dadc75b6e446981935d18adb..daed57d3d2097d5f8ad026e5b902811fff3db813 100644 (file)
@@ -1179,7 +1179,7 @@ static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
 
        skb = alloc_can_skb(priv->netdev, &cf);
        if (!skb) {
-               stats->tx_dropped++;
+               stats->rx_dropped++;
                return;
        }
 
index 3d2091099f7f266de920f575a4d30b417bd64558..5b4374f21d76b873bff94afd466cb2a797025692 100644 (file)
@@ -3370,6 +3370,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_internal_phys = 5,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3391,6 +3392,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_internal_phys = 0,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3410,6 +3412,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_internal_phys = 8,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3431,6 +3434,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_internal_phys = 5,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3452,6 +3456,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_internal_phys = 0,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3472,6 +3477,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_gpio = 11,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x10,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 3750,
@@ -3493,6 +3499,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_internal_phys = 5,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3514,6 +3521,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_internal_phys = 0,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3535,6 +3543,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_internal_phys = 5,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3557,6 +3566,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_gpio = 15,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3578,6 +3588,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_internal_phys = 5,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3600,6 +3611,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_gpio = 15,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3621,6 +3633,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_internal_phys = 0,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3641,6 +3654,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_gpio = 16,
                .max_vid = 8191,
                .port_base_addr = 0x0,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .tag_protocol = DSA_TAG_PROTO_DSA,
@@ -3663,6 +3677,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_gpio = 16,
                .max_vid = 8191,
                .port_base_addr = 0x0,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 3750,
@@ -3684,6 +3699,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_internal_phys = 11,
                .max_vid = 8191,
                .port_base_addr = 0x0,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 3750,
@@ -3707,6 +3723,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_gpio = 15,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3730,6 +3747,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_gpio = 16,
                .max_vid = 8191,
                .port_base_addr = 0x0,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 3750,
@@ -3753,6 +3771,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_gpio = 15,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3776,6 +3795,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_gpio = 15,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3798,6 +3818,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_gpio = 11,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x10,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 3750,
@@ -3820,6 +3841,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_internal_phys = 5,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3841,6 +3863,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_internal_phys = 5,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3863,6 +3886,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_gpio = 15,
                .max_vid = 4095,
                .port_base_addr = 0x10,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 15000,
@@ -3885,6 +3909,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_gpio = 16,
                .max_vid = 8191,
                .port_base_addr = 0x0,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 3750,
@@ -3907,6 +3932,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .num_gpio = 16,
                .max_vid = 8191,
                .port_base_addr = 0x0,
+               .phy_base_addr = 0x0,
                .global1_addr = 0x1b,
                .global2_addr = 0x1c,
                .age_time_coeff = 3750,
index 80490f66bc066eb7c13b64c69c96f7287f480db2..12b7f4649b25bfb5f1c9e00e5dcb4b411155823c 100644 (file)
@@ -114,6 +114,7 @@ struct mv88e6xxx_info {
        unsigned int num_gpio;
        unsigned int max_vid;
        unsigned int port_base_addr;
+       unsigned int phy_base_addr;
        unsigned int global1_addr;
        unsigned int global2_addr;
        unsigned int age_time_coeff;
index 0ce627fded48f2182676d46194c363d30bb93287..8d22d66d84b7807d38366a01c7df80d60e06d105 100644 (file)
@@ -1118,7 +1118,7 @@ int mv88e6xxx_g2_irq_mdio_setup(struct mv88e6xxx_chip *chip,
                        err = irq;
                        goto out;
                }
-               bus->irq[chip->info->port_base_addr + phy] = irq;
+               bus->irq[chip->info->phy_base_addr + phy] = irq;
        }
        return 0;
 out:
index 32f6d2e24d6692ce00ffe077f0c0bc970c90e825..1a1a6380c128c4522b330907cc16258f0e012189 100644 (file)
@@ -95,6 +95,7 @@ void aq_nic_cfg_start(struct aq_nic_s *self)
        /*rss rings */
        cfg->vecs = min(cfg->aq_hw_caps->vecs, AQ_CFG_VECS_DEF);
        cfg->vecs = min(cfg->vecs, num_online_cpus());
+       cfg->vecs = min(cfg->vecs, self->irqvecs);
        /* cfg->vecs should be power of 2 for RSS */
        if (cfg->vecs >= 8U)
                cfg->vecs = 8U;
@@ -246,6 +247,8 @@ void aq_nic_ndev_init(struct aq_nic_s *self)
 
        self->ndev->hw_features |= aq_hw_caps->hw_features;
        self->ndev->features = aq_hw_caps->hw_features;
+       self->ndev->vlan_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM |
+                                    NETIF_F_RXHASH | NETIF_F_SG | NETIF_F_LRO;
        self->ndev->priv_flags = aq_hw_caps->hw_priv_flags;
        self->ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
index 219b550d16650bd6b205fb6e10855627a0fd277b..faa533a0ec474116b7d84369c947a7f0f1bfa853 100644 (file)
@@ -80,6 +80,7 @@ struct aq_nic_s {
 
        struct pci_dev *pdev;
        unsigned int msix_entry_mask;
+       u32 irqvecs;
 };
 
 static inline struct device *aq_nic_get_dev(struct aq_nic_s *self)
index ecc6306f940f5d9f975d9cd422114f0be05c3435..a50e08bb4748386f999b1898b8207d973ac3508b 100644 (file)
@@ -267,16 +267,16 @@ static int aq_pci_probe(struct pci_dev *pdev,
        numvecs = min(numvecs, num_online_cpus());
        /*enable interrupts */
 #if !AQ_CFG_FORCE_LEGACY_INT
-       err = pci_alloc_irq_vectors(self->pdev, numvecs, numvecs,
-                                   PCI_IRQ_MSIX);
-
-       if (err < 0) {
-               err = pci_alloc_irq_vectors(self->pdev, 1, 1,
-                                           PCI_IRQ_MSI | PCI_IRQ_LEGACY);
-               if (err < 0)
-                       goto err_hwinit;
+       numvecs = pci_alloc_irq_vectors(self->pdev, 1, numvecs,
+                                       PCI_IRQ_MSIX | PCI_IRQ_MSI |
+                                       PCI_IRQ_LEGACY);
+
+       if (numvecs < 0) {
+               err = numvecs;
+               goto err_hwinit;
        }
 #endif
+       self->irqvecs = numvecs;
 
        /* net device init */
        aq_nic_cfg_start(self);
@@ -298,9 +298,9 @@ err_free_aq_hw:
        kfree(self->aq_hw);
 err_ioremap:
        free_netdev(ndev);
-err_pci_func:
-       pci_release_regions(pdev);
 err_ndev:
+       pci_release_regions(pdev);
+err_pci_func:
        pci_disable_device(pdev);
        return err;
 }
index 08bbb639be1a5ab3bc10ea27b31df88cb6d2b569..9f59b1270a7c68da3086d22db2930d041cbaaec8 100644 (file)
@@ -8733,14 +8733,15 @@ static void tg3_free_consistent(struct tg3 *tp)
        tg3_mem_rx_release(tp);
        tg3_mem_tx_release(tp);
 
-       /* Protect tg3_get_stats64() from reading freed tp->hw_stats. */
-       tg3_full_lock(tp, 0);
+       /* tp->hw_stats can be referenced safely:
+        *     1. under rtnl_lock
+        *     2. or under tp->lock if TG3_FLAG_INIT_COMPLETE is set.
+        */
        if (tp->hw_stats) {
                dma_free_coherent(&tp->pdev->dev, sizeof(struct tg3_hw_stats),
                                  tp->hw_stats, tp->stats_mapping);
                tp->hw_stats = NULL;
        }
-       tg3_full_unlock(tp);
 }
 
 /*
@@ -14178,7 +14179,7 @@ static void tg3_get_stats64(struct net_device *dev,
        struct tg3 *tp = netdev_priv(dev);
 
        spin_lock_bh(&tp->lock);
-       if (!tp->hw_stats) {
+       if (!tp->hw_stats || !tg3_flag(tp, INIT_COMPLETE)) {
                *stats = tp->net_stats_prev;
                spin_unlock_bh(&tp->lock);
                return;
index 24d2865b880665910c4a4a53d9e613124724432b..005283c7cdfe75a75d5e88048d4e6ea241bdfbb9 100644 (file)
@@ -3433,8 +3433,8 @@ static int adap_config_hma(struct adapter *adapter)
        sgl = adapter->hma.sgt->sgl;
        node = dev_to_node(adapter->pdev_dev);
        for_each_sg(sgl, iter, sgt->orig_nents, i) {
-               newpage = alloc_pages_node(node, __GFP_NOWARN | GFP_KERNEL,
-                                          page_order);
+               newpage = alloc_pages_node(node, __GFP_NOWARN | GFP_KERNEL |
+                                          __GFP_ZERO, page_order);
                if (!newpage) {
                        dev_err(adapter->pdev_dev,
                                "Not enough memory for HMA page allocation\n");
@@ -5474,6 +5474,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
        spin_lock_init(&adapter->mbox_lock);
        INIT_LIST_HEAD(&adapter->mlist.list);
+       adapter->mbox_log->size = T4_OS_LOG_MBOX_CMDS;
        pci_set_drvdata(pdev, adapter);
 
        if (func != ent->driver_data) {
@@ -5508,8 +5509,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto out_free_adapter;
        }
 
-       adapter->mbox_log->size = T4_OS_LOG_MBOX_CMDS;
-
        /* PCI device has been enabled */
        adapter->flags |= DEV_ENABLED;
        memset(adapter->chan_map, 0xff, sizeof(adapter->chan_map));
index 5909a4407e38f912345d1285d40919903a85294d..7c511f144ed60d92c16f0f526cfb5b03a3c2a59e 100644 (file)
@@ -1014,10 +1014,10 @@ ice_clean_rq_elem(struct ice_hw *hw, struct ice_ctl_q_info *cq,
        desc = ICE_CTL_Q_DESC(cq->rq, ntc);
        desc_idx = ntc;
 
+       cq->rq_last_status = (enum ice_aq_err)le16_to_cpu(desc->retval);
        flags = le16_to_cpu(desc->flags);
        if (flags & ICE_AQ_FLAG_ERR) {
                ret_code = ICE_ERR_AQ_ERROR;
-               cq->rq_last_status = (enum ice_aq_err)le16_to_cpu(desc->retval);
                ice_debug(hw, ICE_DBG_AQ_MSG,
                          "Control Receive Queue Event received with error 0x%x\n",
                          cq->rq_last_status);
index 68af127987bcbc65981ebbd7e7be5512f4b63bde..cead23e3db0cb8ba5028a72cc2e89e2ccd6647c6 100644 (file)
@@ -943,8 +943,8 @@ err2:
        kfree(ipsec->ip_tbl);
        kfree(ipsec->rx_tbl);
        kfree(ipsec->tx_tbl);
+       kfree(ipsec);
 err1:
-       kfree(adapter->ipsec);
        netdev_err(adapter->netdev, "Unable to allocate memory for SA tables");
 }
 
index 3123267dfba974049cc26496570cafe842eb81ac..9592f3e3e42ed22c63f6306c45a8cce4cc4e92df 100644 (file)
@@ -3427,6 +3427,9 @@ static s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
                hw->phy.sfp_setup_needed = false;
        }
 
+       if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+               return status;
+
        /* Reset PHY */
        if (!hw->phy.reset_disable && hw->phy.ops.reset)
                hw->phy.ops.reset(hw);
index e3d04f226d57f10a22aff7424a0cb90a28b58602..850f8af95e490714c844f2af7cd07ae8fa6f6062 100644 (file)
@@ -4137,7 +4137,7 @@ out_drop:
        return NETDEV_TX_OK;
 }
 
-static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+static netdev_tx_t ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
        struct ixgbevf_adapter *adapter = netdev_priv(netdev);
        struct ixgbevf_ring *tx_ring;
index a30a2e95d13f56ed58055ac119d8359dd3052fd2..f11b45001cad8c5635684e820a03f183e12d6ef5 100644 (file)
@@ -1027,6 +1027,22 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
        if (!coal->tx_max_coalesced_frames_irq)
                return -EINVAL;
 
+       if (coal->tx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME ||
+           coal->rx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME ||
+           coal->rx_coalesce_usecs_low > MLX4_EN_MAX_COAL_TIME ||
+           coal->rx_coalesce_usecs_high > MLX4_EN_MAX_COAL_TIME) {
+               netdev_info(dev, "%s: maximum coalesce time supported is %d usecs\n",
+                           __func__, MLX4_EN_MAX_COAL_TIME);
+               return -ERANGE;
+       }
+
+       if (coal->tx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS ||
+           coal->rx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS) {
+               netdev_info(dev, "%s: maximum coalesced frames supported is %d\n",
+                           __func__, MLX4_EN_MAX_COAL_PKTS);
+               return -ERANGE;
+       }
+
        priv->rx_frames = (coal->rx_max_coalesced_frames ==
                           MLX4_EN_AUTO_CONF) ?
                                MLX4_EN_RX_COAL_TARGET :
index e0adac4a9a191f923e68d896293c04dce5b67fc7..9670b33fc9b1ffd64a160bb1186af2f47419ab38 100644 (file)
@@ -3324,12 +3324,11 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
                                           MAX_TX_RINGS, GFP_KERNEL);
                if (!priv->tx_ring[t]) {
                        err = -ENOMEM;
-                       goto err_free_tx;
+                       goto out;
                }
                priv->tx_cq[t] = kzalloc(sizeof(struct mlx4_en_cq *) *
                                         MAX_TX_RINGS, GFP_KERNEL);
                if (!priv->tx_cq[t]) {
-                       kfree(priv->tx_ring[t]);
                        err = -ENOMEM;
                        goto out;
                }
@@ -3582,11 +3581,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
 
        return 0;
 
-err_free_tx:
-       while (t--) {
-               kfree(priv->tx_ring[t]);
-               kfree(priv->tx_cq[t]);
-       }
 out:
        mlx4_en_destroy_netdev(dev);
        return err;
index f7c81133594f341cfb0a6e2b1dbb1cc54c3d72ac..ace6545f82e6b343d26acd6d0bb4c55cd6ae4809 100644 (file)
 #define MLX4_EN_TX_COAL_PKTS   16
 #define MLX4_EN_TX_COAL_TIME   0x10
 
+#define MLX4_EN_MAX_COAL_PKTS  U16_MAX
+#define MLX4_EN_MAX_COAL_TIME  U16_MAX
+
 #define MLX4_EN_RX_RATE_LOW            400000
 #define MLX4_EN_RX_COAL_TIME_LOW       0
 #define MLX4_EN_RX_RATE_HIGH           450000
@@ -552,8 +555,8 @@ struct mlx4_en_priv {
        u16 rx_usecs_low;
        u32 pkt_rate_high;
        u16 rx_usecs_high;
-       u16 sample_interval;
-       u16 adaptive_rx_coal;
+       u32 sample_interval;
+       u32 adaptive_rx_coal;
        u32 msg_enable;
        u32 loopback_ok;
        u32 validate_loopback;
index 3c534fc434002a3d39d034dd6e28aa822fd49dc4..b94276db3ce939225b282996ce0f382a2f36fa63 100644 (file)
@@ -1261,6 +1261,10 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                                                  f->mask);
                addr_type = key->addr_type;
 
+               /* the HW doesn't support frag first/later */
+               if (mask->flags & FLOW_DIS_FIRST_FRAG)
+                       return -EOPNOTSUPP;
+
                if (mask->flags & FLOW_DIS_IS_FRAGMENT) {
                        MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
                        MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
index c1c94974e16b13b1d1e2cf7961601ffa4632d9f7..1814f803bd2cbf8b00baa4b9091cc4e954dd2304 100644 (file)
@@ -34,6 +34,9 @@
 #include <linux/module.h>
 #include <linux/mlx5/driver.h>
 #include <linux/mlx5/cmd.h>
+#ifdef CONFIG_RFS_ACCEL
+#include <linux/cpu_rmap.h>
+#endif
 #include "mlx5_core.h"
 #include "fpga/core.h"
 #include "eswitch.h"
@@ -923,3 +926,28 @@ int mlx5_core_eq_query(struct mlx5_core_dev *dev, struct mlx5_eq *eq,
        MLX5_SET(query_eq_in, in, eq_number, eq->eqn);
        return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
 }
+
+/* This function should only be called after mlx5_cmd_force_teardown_hca */
+void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev)
+{
+       struct mlx5_eq_table *table = &dev->priv.eq_table;
+       struct mlx5_eq *eq;
+
+#ifdef CONFIG_RFS_ACCEL
+       if (dev->rmap) {
+               free_irq_cpu_rmap(dev->rmap);
+               dev->rmap = NULL;
+       }
+#endif
+       list_for_each_entry(eq, &table->comp_eqs_list, list)
+               free_irq(eq->irqn, eq);
+
+       free_irq(table->pages_eq.irqn, &table->pages_eq);
+       free_irq(table->async_eq.irqn, &table->async_eq);
+       free_irq(table->cmd_eq.irqn, &table->cmd_eq);
+#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
+       if (MLX5_CAP_GEN(dev, pg))
+               free_irq(table->pfault_eq.irqn, &table->pfault_eq);
+#endif
+       pci_free_irq_vectors(dev->pdev);
+}
index 332bc56306bf5cb22b2a7283f80a3b2c1f4e9a10..1352d13eedb3c8f8575e999226029f7d62122274 100644 (file)
@@ -2175,26 +2175,35 @@ int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
        memset(vf_stats, 0, sizeof(*vf_stats));
        vf_stats->rx_packets =
                MLX5_GET_CTR(out, received_eth_unicast.packets) +
+               MLX5_GET_CTR(out, received_ib_unicast.packets) +
                MLX5_GET_CTR(out, received_eth_multicast.packets) +
+               MLX5_GET_CTR(out, received_ib_multicast.packets) +
                MLX5_GET_CTR(out, received_eth_broadcast.packets);
 
        vf_stats->rx_bytes =
                MLX5_GET_CTR(out, received_eth_unicast.octets) +
+               MLX5_GET_CTR(out, received_ib_unicast.octets) +
                MLX5_GET_CTR(out, received_eth_multicast.octets) +
+               MLX5_GET_CTR(out, received_ib_multicast.octets) +
                MLX5_GET_CTR(out, received_eth_broadcast.octets);
 
        vf_stats->tx_packets =
                MLX5_GET_CTR(out, transmitted_eth_unicast.packets) +
+               MLX5_GET_CTR(out, transmitted_ib_unicast.packets) +
                MLX5_GET_CTR(out, transmitted_eth_multicast.packets) +
+               MLX5_GET_CTR(out, transmitted_ib_multicast.packets) +
                MLX5_GET_CTR(out, transmitted_eth_broadcast.packets);
 
        vf_stats->tx_bytes =
                MLX5_GET_CTR(out, transmitted_eth_unicast.octets) +
+               MLX5_GET_CTR(out, transmitted_ib_unicast.octets) +
                MLX5_GET_CTR(out, transmitted_eth_multicast.octets) +
+               MLX5_GET_CTR(out, transmitted_ib_multicast.octets) +
                MLX5_GET_CTR(out, transmitted_eth_broadcast.octets);
 
        vf_stats->multicast =
-               MLX5_GET_CTR(out, received_eth_multicast.packets);
+               MLX5_GET_CTR(out, received_eth_multicast.packets) +
+               MLX5_GET_CTR(out, received_ib_multicast.packets);
 
        vf_stats->broadcast =
                MLX5_GET_CTR(out, received_eth_broadcast.packets);
index 63a8ea31601cee77fe024d3a84f6e2baab7a8c22..e2c465b0b3f8884529ff040901ffa4073a7e5122 100644 (file)
@@ -1587,6 +1587,14 @@ static int mlx5_try_fast_unload(struct mlx5_core_dev *dev)
 
        mlx5_enter_error_state(dev, true);
 
+       /* Some platforms requiring freeing the IRQ's in the shutdown
+        * flow. If they aren't freed they can't be allocated after
+        * kexec. There is no need to cleanup the mlx5_core software
+        * contexts.
+        */
+       mlx5_irq_clear_affinity_hints(dev);
+       mlx5_core_eq_free_irqs(dev);
+
        return 0;
 }
 
index 7d001fe6e63187fce56e20e0f94bea2417812d12..023882d9a22e59a7b172aee6a3260606932f4a03 100644 (file)
@@ -128,6 +128,8 @@ int mlx5_core_eq_query(struct mlx5_core_dev *dev, struct mlx5_eq *eq,
                       u32 *out, int outlen);
 int mlx5_start_eqs(struct mlx5_core_dev *dev);
 void mlx5_stop_eqs(struct mlx5_core_dev *dev);
+/* This function should only be called after mlx5_cmd_force_teardown_hca */
+void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev);
 struct mlx5_eq *mlx5_eqn2eq(struct mlx5_core_dev *dev, int eqn);
 u32 mlx5_eq_poll_irq_disabled(struct mlx5_eq *eq);
 void mlx5_cq_tasklet_cb(unsigned long data);
index 93ea56620a244ae8c129bfbc20e23d9ead374b64..e13ac3b8dff7562216bdcbdde6ddceb012d024ab 100644 (file)
@@ -1100,11 +1100,11 @@ err_emad_init:
 err_alloc_lag_mapping:
        mlxsw_ports_fini(mlxsw_core);
 err_ports_init:
-       mlxsw_bus->fini(bus_priv);
-err_bus_init:
        if (!reload)
                devlink_resources_unregister(devlink, NULL);
 err_register_resources:
+       mlxsw_bus->fini(bus_priv);
+err_bus_init:
        if (!reload)
                devlink_free(devlink);
 err_devlink_alloc:
index a997e34bcec2eddd9adb93c229683413fcbd9d0e..84e3b9f5abb149a28016a0ad7df09d78f96c7a60 100644 (file)
@@ -52,8 +52,6 @@
 
 #define NFP_FLOWER_ALLOWED_VER 0x0001000000010000UL
 
-#define NFP_FLOWER_FRAME_HEADROOM      158
-
 static const char *nfp_flower_extra_cap(struct nfp_app *app, struct nfp_net *nn)
 {
        return "FLOWER";
@@ -559,22 +557,6 @@ static void nfp_flower_clean(struct nfp_app *app)
        app->priv = NULL;
 }
 
-static int
-nfp_flower_check_mtu(struct nfp_app *app, struct net_device *netdev,
-                    int new_mtu)
-{
-       /* The flower fw reserves NFP_FLOWER_FRAME_HEADROOM bytes of the
-        * supported max MTU to allow for appending tunnel headers. To prevent
-        * unexpected behaviour this needs to be accounted for.
-        */
-       if (new_mtu > netdev->max_mtu - NFP_FLOWER_FRAME_HEADROOM) {
-               nfp_err(app->cpp, "New MTU (%d) is not valid\n", new_mtu);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
 static bool nfp_flower_check_ack(struct nfp_flower_priv *app_priv)
 {
        bool ret;
@@ -656,7 +638,6 @@ const struct nfp_app_type app_flower = {
        .init           = nfp_flower_init,
        .clean          = nfp_flower_clean,
 
-       .check_mtu      = nfp_flower_check_mtu,
        .repr_change_mtu  = nfp_flower_repr_change_mtu,
 
        .vnic_alloc     = nfp_flower_vnic_alloc,
index 27364b7572fc157dad85ddddc905510b1c96701c..b092894dd1287bc7fe00a438ecdd7041f2bed2fe 100644 (file)
@@ -1170,7 +1170,7 @@ static void *nixge_get_nvmem_address(struct device *dev)
 
        cell = nvmem_cell_get(dev, "address");
        if (IS_ERR(cell))
-               return cell;
+               return NULL;
 
        mac = nvmem_cell_read(cell, &cell_size);
        nvmem_cell_put(cell);
@@ -1183,7 +1183,7 @@ static int nixge_probe(struct platform_device *pdev)
        struct nixge_priv *priv;
        struct net_device *ndev;
        struct resource *dmares;
-       const char *mac_addr;
+       const u8 *mac_addr;
        int err;
 
        ndev = alloc_etherdev(sizeof(*priv));
@@ -1202,10 +1202,12 @@ static int nixge_probe(struct platform_device *pdev)
        ndev->max_mtu = NIXGE_JUMBO_MTU;
 
        mac_addr = nixge_get_nvmem_address(&pdev->dev);
-       if (mac_addr && is_valid_ether_addr(mac_addr))
+       if (mac_addr && is_valid_ether_addr(mac_addr)) {
                ether_addr_copy(ndev->dev_addr, mac_addr);
-       else
+               kfree(mac_addr);
+       } else {
                eth_hw_addr_random(ndev);
+       }
 
        priv = netdev_priv(ndev);
        priv->ndev = ndev;
index e874504e8b2879a422c739e5c486ef067723ef19..8667799d0069ff99faaff386d8599cc72a4320cc 100644 (file)
@@ -115,8 +115,7 @@ int qed_l2_alloc(struct qed_hwfn *p_hwfn)
 
 void qed_l2_setup(struct qed_hwfn *p_hwfn)
 {
-       if (p_hwfn->hw_info.personality != QED_PCI_ETH &&
-           p_hwfn->hw_info.personality != QED_PCI_ETH_ROCE)
+       if (!QED_IS_L2_PERSONALITY(p_hwfn))
                return;
 
        mutex_init(&p_hwfn->p_l2_info->lock);
@@ -126,8 +125,7 @@ void qed_l2_free(struct qed_hwfn *p_hwfn)
 {
        u32 i;
 
-       if (p_hwfn->hw_info.personality != QED_PCI_ETH &&
-           p_hwfn->hw_info.personality != QED_PCI_ETH_ROCE)
+       if (!QED_IS_L2_PERSONALITY(p_hwfn))
                return;
 
        if (!p_hwfn->p_l2_info)
index 9854aa9139afa9ca70303093f2c1dc25147ce418..7870ae2a6f7e86870389fb44ae82fb9a21f9f80e 100644 (file)
@@ -680,7 +680,7 @@ static int qed_nic_stop(struct qed_dev *cdev)
                        tasklet_disable(p_hwfn->sp_dpc);
                        p_hwfn->b_sp_dpc_enabled = false;
                        DP_VERBOSE(cdev, NETIF_MSG_IFDOWN,
-                                  "Disabled sp taskelt [hwfn %d] at %p\n",
+                                  "Disabled sp tasklet [hwfn %d] at %p\n",
                                   i, p_hwfn->sp_dpc);
                }
        }
index 50b142fad6b8206c806a91248a0b7ac9f5b196d7..1900bf7e67d1297dc9b24648e99d0ec50f779305 100644 (file)
@@ -238,7 +238,7 @@ qede_rdma_get_free_event_node(struct qede_dev *edev)
        }
 
        if (!found) {
-               event_node = kzalloc(sizeof(*event_node), GFP_KERNEL);
+               event_node = kzalloc(sizeof(*event_node), GFP_ATOMIC);
                if (!event_node) {
                        DP_NOTICE(edev,
                                  "qedr: Could not allocate memory for rdma work\n");
index 604ae78381ae4fdd28836e3cdca589da450c73a9..c7aac1fc99e8c1a7fdd89cd777b262ae88e22afa 100644 (file)
@@ -4981,6 +4981,9 @@ static void rtl_pll_power_down(struct rtl8169_private *tp)
 static void rtl_pll_power_up(struct rtl8169_private *tp)
 {
        rtl_generic_op(tp, tp->pll_power_ops.up);
+
+       /* give MAC/PHY some time to resume */
+       msleep(20);
 }
 
 static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
index f081de4f38d73f7bb37cfa0e119447afc1718f50..88c12474a0c38cc10f539d7eff0b81a0cc9a4d7a 100644 (file)
@@ -3443,7 +3443,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
 
                len = (val & RCR_ENTRY_L2_LEN) >>
                        RCR_ENTRY_L2_LEN_SHIFT;
-               len -= ETH_FCS_LEN;
+               append_size = len + ETH_HLEN + ETH_FCS_LEN;
 
                addr = (val & RCR_ENTRY_PKT_BUF_ADDR) <<
                        RCR_ENTRY_PKT_BUF_ADDR_SHIFT;
@@ -3453,7 +3453,6 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
                                         RCR_ENTRY_PKTBUFSZ_SHIFT];
 
                off = addr & ~PAGE_MASK;
-               append_size = rcr_size;
                if (num_rcr == 1) {
                        int ptype;
 
@@ -3466,7 +3465,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
                        else
                                skb_checksum_none_assert(skb);
                } else if (!(val & RCR_ENTRY_MULTI))
-                       append_size = len - skb->len;
+                       append_size = append_size - skb->len;
 
                niu_rx_skb_append(skb, page, off, append_size, rcr_size);
                if ((page->index + rp->rbr_block_size) - rcr_size == addr) {
index ecc84954c511053fe6c493e0a1131f544467f178..da07ccdf84bf1979fdd43dc3fc1d4d742b41c1af 100644 (file)
@@ -1840,7 +1840,8 @@ static int netvsc_vf_join(struct net_device *vf_netdev,
                goto rx_handler_failed;
        }
 
-       ret = netdev_upper_dev_link(vf_netdev, ndev, NULL);
+       ret = netdev_master_upper_dev_link(vf_netdev, ndev,
+                                          NULL, NULL, NULL);
        if (ret != 0) {
                netdev_err(vf_netdev,
                           "can not set master device %s (err = %d)\n",
index 6b127be781d9c4f88719ab6cf033e4b70dc3a7c6..e7ca5b5f39ede4a905730bb153f87f6cec92bd0c 100644 (file)
@@ -1288,7 +1288,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
                   rndis_device->link_state ? "down" : "up");
 
        if (net_device->nvsp_version < NVSP_PROTOCOL_VERSION_5)
-               return net_device;
+               goto out;
 
        rndis_filter_query_link_speed(rndis_device, net_device);
 
index 9fb9b565a002ff7c2e9f6a06c4ef6b9c4d640266..4f684cbcdc57e4ce382f1b5e57f7885ded2f2af2 100644 (file)
@@ -1045,7 +1045,7 @@ static int atusb_probe(struct usb_interface *interface,
        atusb->tx_dr.bRequest = ATUSB_TX;
        atusb->tx_dr.wValue = cpu_to_le16(0);
 
-       atusb->tx_urb = usb_alloc_urb(0, GFP_ATOMIC);
+       atusb->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!atusb->tx_urb)
                goto fail;
 
index 55a22c7618082c501fe39856988c337c4bda8f41..de0d7f28a181ca4acb1da2131d82a981627a8e96 100644 (file)
@@ -1267,7 +1267,7 @@ mcr20a_probe(struct spi_device *spi)
        ret = mcr20a_get_platform_data(spi, pdata);
        if (ret < 0) {
                dev_crit(&spi->dev, "mcr20a_get_platform_data failed.\n");
-               return ret;
+               goto free_pdata;
        }
 
        /* init reset gpio */
@@ -1275,7 +1275,7 @@ mcr20a_probe(struct spi_device *spi)
                ret = devm_gpio_request_one(&spi->dev, pdata->rst_gpio,
                                            GPIOF_OUT_INIT_HIGH, "reset");
                if (ret)
-                       return ret;
+                       goto free_pdata;
        }
 
        /* reset mcr20a */
@@ -1291,7 +1291,8 @@ mcr20a_probe(struct spi_device *spi)
        hw = ieee802154_alloc_hw(sizeof(*lp), &mcr20a_hw_ops);
        if (!hw) {
                dev_crit(&spi->dev, "ieee802154_alloc_hw failed\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto free_pdata;
        }
 
        /* init mcr20a local data */
@@ -1308,8 +1309,10 @@ mcr20a_probe(struct spi_device *spi)
        /* init buf */
        lp->buf = devm_kzalloc(&spi->dev, SPI_COMMAND_BUFFER, GFP_KERNEL);
 
-       if (!lp->buf)
-               return -ENOMEM;
+       if (!lp->buf) {
+               ret = -ENOMEM;
+               goto free_dev;
+       }
 
        mcr20a_setup_tx_spi_messages(lp);
        mcr20a_setup_rx_spi_messages(lp);
@@ -1366,6 +1369,8 @@ mcr20a_probe(struct spi_device *spi)
 
 free_dev:
        ieee802154_free_hw(lp->hw);
+free_pdata:
+       kfree(pdata);
 
        return ret;
 }
index 3bb6b66dc7bfb0d3eb6fd905c77feefc0138afac..f9c25912eb98c8713229405bc551a4c52816eb24 100644 (file)
@@ -720,6 +720,15 @@ static struct phy_driver broadcom_drivers[] = {
        .get_strings    = bcm_phy_get_strings,
        .get_stats      = bcm53xx_phy_get_stats,
        .probe          = bcm53xx_phy_probe,
+}, {
+       .phy_id         = PHY_ID_BCM89610,
+       .phy_id_mask    = 0xfffffff0,
+       .name           = "Broadcom BCM89610",
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_init    = bcm54xx_config_init,
+       .ack_interrupt  = bcm_phy_ack_intr,
+       .config_intr    = bcm_phy_config_intr,
 } };
 
 module_phy_driver(broadcom_drivers);
@@ -741,6 +750,7 @@ static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
        { PHY_ID_BCMAC131, 0xfffffff0 },
        { PHY_ID_BCM5241, 0xfffffff0 },
        { PHY_ID_BCM5395, 0xfffffff0 },
+       { PHY_ID_BCM89610, 0xfffffff0 },
        { }
 };
 
index 0381da78d228dc2fe7f87fabb8260cc257a3fc66..fd6c23f69c2f0216c9e978329fc1fb74569ef73a 100644 (file)
@@ -125,7 +125,7 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
        if (id->base.br_nominal) {
                if (id->base.br_nominal != 255) {
                        br_nom = id->base.br_nominal * 100;
-                       br_min = br_nom + id->base.br_nominal * id->ext.br_min;
+                       br_min = br_nom - id->base.br_nominal * id->ext.br_min;
                        br_max = br_nom + id->base.br_nominal * id->ext.br_max;
                } else if (id->ext.br_max) {
                        br_nom = 250 * id->ext.br_max;
index 96d26cfae90bd2acf55854f4818f11d4b14f2f5a..4a017a0d71ea47ae270119593f4c9e1db3632513 100644 (file)
@@ -3236,6 +3236,7 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
                        GENL_SET_ERR_MSG(info,"MAC is no valid source addr");
                        NL_SET_BAD_ATTR(info->extack,
                                        info->attrs[HWSIM_ATTR_PERM_ADDR]);
+                       kfree(hwname);
                        return -EINVAL;
                }
 
index a3771c5729f542d6b27e15bc6f66f5ebb75a3372..99b857e5a7a9c7dcde1e031eeab99f3737f026c3 100644 (file)
@@ -99,6 +99,7 @@ static struct class *nvme_subsys_class;
 
 static void nvme_ns_remove(struct nvme_ns *ns);
 static int nvme_revalidate_disk(struct gendisk *disk);
+static void nvme_put_subsystem(struct nvme_subsystem *subsys);
 
 int nvme_reset_ctrl(struct nvme_ctrl *ctrl)
 {
@@ -117,7 +118,8 @@ int nvme_reset_ctrl_sync(struct nvme_ctrl *ctrl)
        ret = nvme_reset_ctrl(ctrl);
        if (!ret) {
                flush_work(&ctrl->reset_work);
-               if (ctrl->state != NVME_CTRL_LIVE)
+               if (ctrl->state != NVME_CTRL_LIVE &&
+                   ctrl->state != NVME_CTRL_ADMIN_ONLY)
                        ret = -ENETRESET;
        }
 
@@ -350,6 +352,7 @@ static void nvme_free_ns_head(struct kref *ref)
        ida_simple_remove(&head->subsys->ns_ida, head->instance);
        list_del_init(&head->entry);
        cleanup_srcu_struct(&head->srcu);
+       nvme_put_subsystem(head->subsys);
        kfree(head);
 }
 
@@ -2861,6 +2864,9 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
                goto out_cleanup_srcu;
 
        list_add_tail(&head->entry, &ctrl->subsys->nsheads);
+
+       kref_get(&ctrl->subsys->ref);
+
        return head;
 out_cleanup_srcu:
        cleanup_srcu_struct(&head->srcu);
index 7ded7a51c4301958e6d6d988593efe36a85a0a71..17d2f7cf3fed6fd6a47dc1e5357c40774d73880c 100644 (file)
@@ -84,6 +84,11 @@ enum nvme_quirks {
         * Supports the LighNVM command set if indicated in vs[1].
         */
        NVME_QUIRK_LIGHTNVM                     = (1 << 6),
+
+       /*
+        * Set MEDIUM priority on SQ creation
+        */
+       NVME_QUIRK_MEDIUM_PRIO_SQ               = (1 << 7),
 };
 
 /*
index fbc71fac6f1e077ad21d336c8e8ca3e3bc311cbe..17a0190bd88fb23e9d525a7f97c877d4b8c2dbc1 100644 (file)
@@ -1093,9 +1093,18 @@ static int adapter_alloc_cq(struct nvme_dev *dev, u16 qid,
 static int adapter_alloc_sq(struct nvme_dev *dev, u16 qid,
                                                struct nvme_queue *nvmeq)
 {
+       struct nvme_ctrl *ctrl = &dev->ctrl;
        struct nvme_command c;
        int flags = NVME_QUEUE_PHYS_CONTIG;
 
+       /*
+        * Some drives have a bug that auto-enables WRRU if MEDIUM isn't
+        * set. Since URGENT priority is zeroes, it makes all queues
+        * URGENT.
+        */
+       if (ctrl->quirks & NVME_QUIRK_MEDIUM_PRIO_SQ)
+               flags |= NVME_SQ_PRIO_MEDIUM;
+
        /*
         * Note: we (ab)use the fact that the prp fields survive if no data
         * is attached to the request.
@@ -2701,7 +2710,8 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_STRIPE_SIZE |
                                NVME_QUIRK_DEALLOCATE_ZEROES, },
        { PCI_VDEVICE(INTEL, 0xf1a5),   /* Intel 600P/P3100 */
-               .driver_data = NVME_QUIRK_NO_DEEPEST_PS },
+               .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
+                               NVME_QUIRK_MEDIUM_PRIO_SQ },
        { PCI_VDEVICE(INTEL, 0x5845),   /* Qemu emulated controller */
                .driver_data = NVME_QUIRK_IDENTIFY_CNS, },
        { PCI_DEVICE(0x1c58, 0x0003),   /* HGST adapter */
index b35fe88f18514d13eaf9460885f42657bd52ed61..7baa53e5b1d74d469959341945e3bc239cf7d5c7 100644 (file)
@@ -102,12 +102,28 @@ static DEFINE_IDR(ovcs_idr);
 
 static BLOCKING_NOTIFIER_HEAD(overlay_notify_chain);
 
+/**
+ * of_overlay_notifier_register() - Register notifier for overlay operations
+ * @nb:                Notifier block to register
+ *
+ * Register for notification on overlay operations on device tree nodes. The
+ * reported actions definied by @of_reconfig_change. The notifier callback
+ * furthermore receives a pointer to the affected device tree node.
+ *
+ * Note that a notifier callback is not supposed to store pointers to a device
+ * tree node or its content beyond @OF_OVERLAY_POST_REMOVE corresponding to the
+ * respective node it received.
+ */
 int of_overlay_notifier_register(struct notifier_block *nb)
 {
        return blocking_notifier_chain_register(&overlay_notify_chain, nb);
 }
 EXPORT_SYMBOL_GPL(of_overlay_notifier_register);
 
+/**
+ * of_overlay_notifier_register() - Unregister notifier for overlay operations
+ * @nb:                Notifier block to unregister
+ */
 int of_overlay_notifier_unregister(struct notifier_block *nb)
 {
        return blocking_notifier_chain_unregister(&overlay_notify_chain, nb);
@@ -671,17 +687,13 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
                of_node_put(ovcs->fragments[i].overlay);
        }
        kfree(ovcs->fragments);
-
        /*
-        * TODO
-        *
-        * would like to: kfree(ovcs->overlay_tree);
-        * but can not since drivers may have pointers into this data
-        *
-        * would like to: kfree(ovcs->fdt);
-        * but can not since drivers may have pointers into this data
+        * There should be no live pointers into ovcs->overlay_tree and
+        * ovcs->fdt due to the policy that overlay notifiers are not allowed
+        * to retain pointers into the overlay devicetree.
         */
-
+       kfree(ovcs->overlay_tree);
+       kfree(ovcs->fdt);
        kfree(ovcs);
 }
 
index a04197ce767dfe62fd504ab99c84102d510e0b6a..dbfe7c4f3776890b9a57401dec13cfdf7729e876 100644 (file)
@@ -1910,7 +1910,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
 EXPORT_SYMBOL(pci_pme_active);
 
 /**
- * pci_enable_wake - enable PCI device as wakeup event source
+ * __pci_enable_wake - enable PCI device as wakeup event source
  * @dev: PCI device affected
  * @state: PCI state from which device will issue wakeup events
  * @enable: True to enable event generation; false to disable
@@ -1928,7 +1928,7 @@ EXPORT_SYMBOL(pci_pme_active);
  * Error code depending on the platform is returned if both the platform and
  * the native mechanism fail to enable the generation of wake-up events
  */
-int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
+static int __pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
 {
        int ret = 0;
 
@@ -1969,6 +1969,23 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
 
        return ret;
 }
+
+/**
+ * pci_enable_wake - change wakeup settings for a PCI device
+ * @pci_dev: Target device
+ * @state: PCI state from which device will issue wakeup events
+ * @enable: Whether or not to enable event generation
+ *
+ * If @enable is set, check device_may_wakeup() for the device before calling
+ * __pci_enable_wake() for it.
+ */
+int pci_enable_wake(struct pci_dev *pci_dev, pci_power_t state, bool enable)
+{
+       if (enable && !device_may_wakeup(&pci_dev->dev))
+               return -EINVAL;
+
+       return __pci_enable_wake(pci_dev, state, enable);
+}
 EXPORT_SYMBOL(pci_enable_wake);
 
 /**
@@ -1981,9 +1998,9 @@ EXPORT_SYMBOL(pci_enable_wake);
  * should not be called twice in a row to enable wake-up due to PCI PM vs ACPI
  * ordering constraints.
  *
- * This function only returns error code if the device is not capable of
- * generating PME# from both D3_hot and D3_cold, and the platform is unable to
- * enable wake-up power for it.
+ * This function only returns error code if the device is not allowed to wake
+ * up the system from sleep or it is not capable of generating PME# from both
+ * D3_hot and D3_cold and the platform is unable to enable wake-up power for it.
  */
 int pci_wake_from_d3(struct pci_dev *dev, bool enable)
 {
@@ -2114,7 +2131,7 @@ int pci_finish_runtime_suspend(struct pci_dev *dev)
 
        dev->runtime_d3cold = target_state == PCI_D3cold;
 
-       pci_enable_wake(dev, target_state, pci_dev_run_wake(dev));
+       __pci_enable_wake(dev, target_state, pci_dev_run_wake(dev));
 
        error = pci_set_power_state(dev, target_state);
 
@@ -2138,16 +2155,16 @@ bool pci_dev_run_wake(struct pci_dev *dev)
 {
        struct pci_bus *bus = dev->bus;
 
-       if (device_can_wakeup(&dev->dev))
-               return true;
-
        if (!dev->pme_support)
                return false;
 
        /* PME-capable in principle, but not from the target power state */
-       if (!pci_pme_capable(dev, pci_target_state(dev, false)))
+       if (!pci_pme_capable(dev, pci_target_state(dev, true)))
                return false;
 
+       if (device_can_wakeup(&dev->dev))
+               return true;
+
        while (bus->parent) {
                struct pci_dev *bridge = bus->self;
 
index b1ae1618fefea7cd14811b71e05823b70e4c614d..fee9225ca559e6860bf28adc7d746d56fb499c34 100644 (file)
@@ -1622,22 +1622,30 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
 
        if (!need_valid_mask) {
                irq_base = devm_irq_alloc_descs(pctrl->dev, -1, 0,
-                                               chip->ngpio, NUMA_NO_NODE);
+                                               community->npins, NUMA_NO_NODE);
                if (irq_base < 0) {
                        dev_err(pctrl->dev, "Failed to allocate IRQ numbers\n");
                        return irq_base;
                }
-       } else {
-               irq_base = 0;
        }
 
-       ret = gpiochip_irqchip_add(chip, &chv_gpio_irqchip, irq_base,
+       ret = gpiochip_irqchip_add(chip, &chv_gpio_irqchip, 0,
                                   handle_bad_irq, IRQ_TYPE_NONE);
        if (ret) {
                dev_err(pctrl->dev, "failed to add IRQ chip\n");
                return ret;
        }
 
+       if (!need_valid_mask) {
+               for (i = 0; i < community->ngpio_ranges; i++) {
+                       range = &community->gpio_ranges[i];
+
+                       irq_domain_associate_many(chip->irq.domain, irq_base,
+                                                 range->base, range->npins);
+                       irq_base += range->npins;
+               }
+       }
+
        gpiochip_set_chained_irqchip(chip, &chv_gpio_irqchip, irq,
                                     chv_gpio_irq_handler);
        return 0;
index 8870a4100164616a9bfcc3492468641cb9bfabbd..fee3435a6f15853edb6ee5e2db3ec649e78b554f 100644 (file)
                .npins = ((e) - (s) + 1),               \
        }
 
+#define SPTH_GPP(r, s, e, g)                           \
+       {                                               \
+               .reg_num = (r),                         \
+               .base = (s),                            \
+               .size = ((e) - (s) + 1),                \
+               .gpio_base = (g),                       \
+       }
+
+#define SPTH_COMMUNITY(b, s, e, g)                     \
+       {                                               \
+               .barno = (b),                           \
+               .padown_offset = SPT_PAD_OWN,           \
+               .padcfglock_offset = SPT_PADCFGLOCK,    \
+               .hostown_offset = SPT_HOSTSW_OWN,       \
+               .ie_offset = SPT_GPI_IE,                \
+               .pin_base = (s),                        \
+               .npins = ((e) - (s) + 1),               \
+               .gpps = (g),                            \
+               .ngpps = ARRAY_SIZE(g),                 \
+       }
+
 /* Sunrisepoint-LP */
 static const struct pinctrl_pin_desc sptlp_pins[] = {
        /* GPP_A */
@@ -531,10 +552,28 @@ static const struct intel_function spth_functions[] = {
        FUNCTION("i2c2", spth_i2c2_groups),
 };
 
+static const struct intel_padgroup spth_community0_gpps[] = {
+       SPTH_GPP(0, 0, 23, 0),          /* GPP_A */
+       SPTH_GPP(1, 24, 47, 24),        /* GPP_B */
+};
+
+static const struct intel_padgroup spth_community1_gpps[] = {
+       SPTH_GPP(0, 48, 71, 48),        /* GPP_C */
+       SPTH_GPP(1, 72, 95, 72),        /* GPP_D */
+       SPTH_GPP(2, 96, 108, 96),       /* GPP_E */
+       SPTH_GPP(3, 109, 132, 120),     /* GPP_F */
+       SPTH_GPP(4, 133, 156, 144),     /* GPP_G */
+       SPTH_GPP(5, 157, 180, 168),     /* GPP_H */
+};
+
+static const struct intel_padgroup spth_community3_gpps[] = {
+       SPTH_GPP(0, 181, 191, 192),     /* GPP_I */
+};
+
 static const struct intel_community spth_communities[] = {
-       SPT_COMMUNITY(0, 0, 47),
-       SPT_COMMUNITY(1, 48, 180),
-       SPT_COMMUNITY(2, 181, 191),
+       SPTH_COMMUNITY(0, 0, 47, spth_community0_gpps),
+       SPTH_COMMUNITY(1, 48, 180, spth_community1_gpps),
+       SPTH_COMMUNITY(2, 181, 191, spth_community3_gpps),
 };
 
 static const struct intel_pinctrl_soc_data spth_soc_data = {
index 4b91ff74779bead16a60f96bf2566e947989e179..99a6ceac8e53ca680eb14f681d3f247622d8eda4 100644 (file)
@@ -898,7 +898,7 @@ static struct meson_bank meson_axg_periphs_banks[] = {
 
 static struct meson_bank meson_axg_aobus_banks[] = {
        /*   name    first      last      irq   pullen  pull    dir     out     in  */
-       BANK("AO",   GPIOAO_0,  GPIOAO_9, 0, 13, 0,  16,  0, 0,  0,  0,  0, 16,  1,  0),
+       BANK("AO",   GPIOAO_0,  GPIOAO_13, 0, 13, 0,  16,  0, 0,  0,  0,  0, 16,  1,  0),
 };
 
 static struct meson_pmx_bank meson_axg_periphs_pmx_banks[] = {
index bc309c5327ffdbe544214bb020e5b76ada5965e3..566644bb496ac82bf3263bb6ea285c7ab1fb070f 100644 (file)
@@ -168,8 +168,8 @@ config DELL_WMI
        depends on DMI
        depends on INPUT
        depends on ACPI_VIDEO || ACPI_VIDEO = n
+       depends on DELL_SMBIOS
        select DELL_WMI_DESCRIPTOR
-       select DELL_SMBIOS
        select INPUT_SPARSEKMAP
        ---help---
          Say Y here if you want to support WMI-based hotkeys on Dell laptops.
index 439991d71b146698c90540c5633cfdd0fbe1bc16..4c14ce428e92d8927fedb8702d3d9dd26801ddad 100644 (file)
@@ -141,7 +141,7 @@ static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues)
        int i;
 
        for (i = 0; i < nr_queues; i++) {
-               q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL);
+               q = kmem_cache_zalloc(qdio_q_cache, GFP_KERNEL);
                if (!q)
                        return -ENOMEM;
 
@@ -456,7 +456,6 @@ int qdio_setup_irq(struct qdio_initialize *init_data)
 {
        struct ciw *ciw;
        struct qdio_irq *irq_ptr = init_data->cdev->private->qdio_data;
-       int rc;
 
        memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib));
        memset(&irq_ptr->siga_flag, 0, sizeof(irq_ptr->siga_flag));
@@ -493,16 +492,14 @@ int qdio_setup_irq(struct qdio_initialize *init_data)
        ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_EQUEUE);
        if (!ciw) {
                DBF_ERROR("%4x NO EQ", irq_ptr->schid.sch_no);
-               rc = -EINVAL;
-               goto out_err;
+               return -EINVAL;
        }
        irq_ptr->equeue = *ciw;
 
        ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_AQUEUE);
        if (!ciw) {
                DBF_ERROR("%4x NO AQ", irq_ptr->schid.sch_no);
-               rc = -EINVAL;
-               goto out_err;
+               return -EINVAL;
        }
        irq_ptr->aqueue = *ciw;
 
@@ -512,9 +509,6 @@ int qdio_setup_irq(struct qdio_initialize *init_data)
        init_data->cdev->handler = qdio_int_handler;
        spin_unlock_irq(get_ccwdev_lock(irq_ptr->cdev));
        return 0;
-out_err:
-       qdio_release_memory(irq_ptr);
-       return rc;
 }
 
 void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
index 2c7550797ec2f51130c6e580a7b10d2bfc1155c5..dce92b2a895d6ff3bbe38104ed08ea32c7979432 100644 (file)
@@ -715,6 +715,10 @@ void cp_free(struct channel_program *cp)
  * and stores the result to ccwchain list. @cp must have been
  * initialized by a previous call with cp_init(). Otherwise, undefined
  * behavior occurs.
+ * For each chain composing the channel program:
+ * - On entry ch_len holds the count of CCWs to be translated.
+ * - On exit ch_len is adjusted to the count of successfully translated CCWs.
+ * This allows cp_free to find in ch_len the count of CCWs to free in a chain.
  *
  * The S/390 CCW Translation APIS (prefixed by 'cp_') are introduced
  * as helpers to do ccw chain translation inside the kernel. Basically
@@ -749,11 +753,18 @@ int cp_prefetch(struct channel_program *cp)
                for (idx = 0; idx < len; idx++) {
                        ret = ccwchain_fetch_one(chain, idx, cp);
                        if (ret)
-                               return ret;
+                               goto out_err;
                }
        }
 
        return 0;
+out_err:
+       /* Only cleanup the chain elements that were actually translated. */
+       chain->ch_len = idx;
+       list_for_each_entry_continue(chain, &cp->ccwchain_list, next) {
+               chain->ch_len = 0;
+       }
+       return ret;
 }
 
 /**
index 0156c9623c35d55012f8c77b24efd19b0b42d980..d62ddd63f4fe115d849f5aea3e16a649fa0531eb 100644 (file)
@@ -724,6 +724,8 @@ int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback,
        int wait;
        unsigned long flags = 0;
        unsigned long mflags = 0;
+       struct aac_hba_cmd_req *hbacmd = (struct aac_hba_cmd_req *)
+                       fibptr->hw_fib_va;
 
        fibptr->flags = (FIB_CONTEXT_FLAG | FIB_CONTEXT_FLAG_NATIVE_HBA);
        if (callback) {
@@ -734,11 +736,9 @@ int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback,
                wait = 1;
 
 
-       if (command == HBA_IU_TYPE_SCSI_CMD_REQ) {
-               struct aac_hba_cmd_req *hbacmd =
-                       (struct aac_hba_cmd_req *)fibptr->hw_fib_va;
+       hbacmd->iu_type = command;
 
-               hbacmd->iu_type = command;
+       if (command == HBA_IU_TYPE_SCSI_CMD_REQ) {
                /* bit1 of request_id must be 0 */
                hbacmd->request_id =
                        cpu_to_le32((((u32)(fibptr - dev->fibs)) << 2) + 1);
index c374e3b5c678d215bfa9e7ed33e2d033e5d4bfb3..777e5f1e52d10968d5f23e0e316db05b8209511d 100644 (file)
@@ -609,7 +609,7 @@ static void pvscsi_complete_request(struct pvscsi_adapter *adapter,
                        break;
 
                case BTSTAT_ABORTQUEUE:
-                       cmd->result = (DID_ABORT << 16);
+                       cmd->result = (DID_BUS_BUSY << 16);
                        break;
 
                case BTSTAT_SCSIPARITY:
index 1596d35498c5a5567bc844c11c2fd1463867dde5..6573152ce8936e728cfb86a0210ce33eeb4e81d8 100644 (file)
@@ -490,7 +490,7 @@ static int bcm_qspi_bspi_set_mode(struct bcm_qspi *qspi,
 
 static void bcm_qspi_enable_bspi(struct bcm_qspi *qspi)
 {
-       if (!has_bspi(qspi) || (qspi->bspi_enabled))
+       if (!has_bspi(qspi))
                return;
 
        qspi->bspi_enabled = 1;
@@ -505,7 +505,7 @@ static void bcm_qspi_enable_bspi(struct bcm_qspi *qspi)
 
 static void bcm_qspi_disable_bspi(struct bcm_qspi *qspi)
 {
-       if (!has_bspi(qspi) || (!qspi->bspi_enabled))
+       if (!has_bspi(qspi))
                return;
 
        qspi->bspi_enabled = 0;
@@ -519,16 +519,19 @@ static void bcm_qspi_disable_bspi(struct bcm_qspi *qspi)
 
 static void bcm_qspi_chip_select(struct bcm_qspi *qspi, int cs)
 {
-       u32 data = 0;
+       u32 rd = 0;
+       u32 wr = 0;
 
-       if (qspi->curr_cs == cs)
-               return;
        if (qspi->base[CHIP_SELECT]) {
-               data = bcm_qspi_read(qspi, CHIP_SELECT, 0);
-               data = (data & ~0xff) | (1 << cs);
-               bcm_qspi_write(qspi, CHIP_SELECT, 0, data);
+               rd = bcm_qspi_read(qspi, CHIP_SELECT, 0);
+               wr = (rd & ~0xff) | (1 << cs);
+               if (rd == wr)
+                       return;
+               bcm_qspi_write(qspi, CHIP_SELECT, 0, wr);
                usleep_range(10, 20);
        }
+
+       dev_dbg(&qspi->pdev->dev, "using cs:%d\n", cs);
        qspi->curr_cs = cs;
 }
 
@@ -755,8 +758,13 @@ static int write_to_hw(struct bcm_qspi *qspi, struct spi_device *spi)
                        dev_dbg(&qspi->pdev->dev, "WR %04x\n", val);
                }
                mspi_cdram = MSPI_CDRAM_CONT_BIT;
-               mspi_cdram |= (~(1 << spi->chip_select) &
-                              MSPI_CDRAM_PCS);
+
+               if (has_bspi(qspi))
+                       mspi_cdram &= ~1;
+               else
+                       mspi_cdram |= (~(1 << spi->chip_select) &
+                                      MSPI_CDRAM_PCS);
+
                mspi_cdram |= ((tp.trans->bits_per_word <= 8) ? 0 :
                                MSPI_CDRAM_BITSE_BIT);
 
index 1431cb98fe403a4b7039195bf172bf47bceb6702..3094d818cf06d4751122611bc2eb807e71d965fd 100644 (file)
@@ -184,6 +184,11 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id)
        struct bcm2835aux_spi *bs = spi_master_get_devdata(master);
        irqreturn_t ret = IRQ_NONE;
 
+       /* IRQ may be shared, so return if our interrupts are disabled */
+       if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) &
+             (BCM2835_AUX_SPI_CNTL1_TXEMPTY | BCM2835_AUX_SPI_CNTL1_IDLE)))
+               return ret;
+
        /* check if we have data to read */
        while (bs->rx_len &&
               (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_STAT) &
index 5c9516ae4942e5cf8b2ef381d2ecd496803cbf14..4a001634023e09b8e83b8e6b82b5af557e2c0853 100644 (file)
@@ -313,6 +313,14 @@ static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi)
 
        while ((trans_cnt < CDNS_SPI_FIFO_DEPTH) &&
               (xspi->tx_bytes > 0)) {
+
+               /* When xspi in busy condition, bytes may send failed,
+                * then spi control did't work thoroughly, add one byte delay
+                */
+               if (cdns_spi_read(xspi, CDNS_SPI_ISR) &
+                   CDNS_SPI_IXR_TXFULL)
+                       usleep_range(10, 20);
+
                if (xspi->txbuf)
                        cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++);
                else
index 6f57592a7f95ad0980362dd69840d72846cbad77..a056ee88a960bf8e0cb33a871ef573d0d81e417e 100644 (file)
@@ -1701,7 +1701,7 @@ static struct platform_driver spi_imx_driver = {
 };
 module_platform_driver(spi_imx_driver);
 
-MODULE_DESCRIPTION("SPI Master Controller driver");
+MODULE_DESCRIPTION("SPI Controller driver");
 MODULE_AUTHOR("Sascha Hauer, Pengutronix");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRIVER_NAME);
index 513ec6c6e25b310b62d0024cd6c71a23c4890b5e..0ae7defd3492001dd096d8772bfde53db63226e7 100644 (file)
@@ -38,7 +38,7 @@ struct driver_data {
 
        /* SSP register addresses */
        void __iomem *ioaddr;
-       u32 ssdr_physical;
+       phys_addr_t ssdr_physical;
 
        /* SSP masks*/
        u32 dma_cr1;
index ae086aab57d51edc2c8014160f4abeab365ea9cc..8171eedbfc90033b5bf942667cfcfe5214453d4e 100644 (file)
@@ -283,6 +283,7 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
        }
 
        k = min_t(int, k, ARRAY_SIZE(sh_msiof_spi_div_table) - 1);
+       brps = min_t(int, brps, 32);
 
        scr = sh_msiof_spi_div_table[k].brdv | SCR_BRPS(brps);
        sh_msiof_write(p, TSCR, scr);
index 8a7f24dd9315e3be809ef98e4513506561be04fb..0c19fcd56a0da02713e93778afc78c84017aeeef 100644 (file)
@@ -194,6 +194,7 @@ static int int3403_cdev_add(struct int3403_priv *priv)
                return -EFAULT;
        }
 
+       priv->priv = obj;
        obj->max_state = p->package.count - 1;
        obj->cdev =
                thermal_cooling_device_register(acpi_device_bid(priv->adev),
@@ -201,8 +202,6 @@ static int int3403_cdev_add(struct int3403_priv *priv)
        if (IS_ERR(obj->cdev))
                result = PTR_ERR(obj->cdev);
 
-       priv->priv = obj;
-
        kfree(buf.pointer);
        /* TODO: add ACPI notification support */
 
index ed805c7c5ace3a121be27359bb4d08ee42634a4d..ac83f721db24d78cff24d9349ecf75edafe9f2d4 100644 (file)
  * @regulator: pointer to the TMU regulator structure.
  * @reg_conf: pointer to structure to register with core thermal.
  * @ntrip: number of supported trip points.
+ * @enabled: current status of TMU device
  * @tmu_initialize: SoC specific TMU initialization method
  * @tmu_control: SoC specific TMU control method
  * @tmu_read: SoC specific TMU temperature read method
@@ -205,6 +206,7 @@ struct exynos_tmu_data {
        struct regulator *regulator;
        struct thermal_zone_device *tzd;
        unsigned int ntrip;
+       bool enabled;
 
        int (*tmu_initialize)(struct platform_device *pdev);
        void (*tmu_control)(struct platform_device *pdev, bool on);
@@ -398,6 +400,7 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
        mutex_lock(&data->lock);
        clk_enable(data->clk);
        data->tmu_control(pdev, on);
+       data->enabled = on;
        clk_disable(data->clk);
        mutex_unlock(&data->lock);
 }
@@ -889,19 +892,24 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on)
 static int exynos_get_temp(void *p, int *temp)
 {
        struct exynos_tmu_data *data = p;
+       int value, ret = 0;
 
-       if (!data || !data->tmu_read)
+       if (!data || !data->tmu_read || !data->enabled)
                return -EINVAL;
 
        mutex_lock(&data->lock);
        clk_enable(data->clk);
 
-       *temp = code_to_temp(data, data->tmu_read(data)) * MCELSIUS;
+       value = data->tmu_read(data);
+       if (value < 0)
+               ret = value;
+       else
+               *temp = code_to_temp(data, value) * MCELSIUS;
 
        clk_disable(data->clk);
        mutex_unlock(&data->lock);
 
-       return 0;
+       return ret;
 }
 
 #ifdef CONFIG_THERMAL_EMULATION
index 72ebbc908e19f7ea9701ca0e831ee703874d1908..32cd52ca8318b6bcb6a9e12f7dbc5c0b18185672 100644 (file)
@@ -354,7 +354,7 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
 
        slot_id = 0;
        for (i = 0; i < MAX_HC_SLOTS; i++) {
-               if (!xhci->devs[i])
+               if (!xhci->devs[i] || !xhci->devs[i]->udev)
                        continue;
                speed = xhci->devs[i]->udev->speed;
                if (((speed >= USB_SPEED_SUPER) == (hcd->speed >= HCD_USB3))
index e7f99d55922af9c82a19722f83794905879d24fc..15a42cee0a9c27ad930fd28ae637fb6d1d9262f9 100644 (file)
@@ -2524,8 +2524,11 @@ static int musb_bus_suspend(struct usb_hcd *hcd)
 {
        struct musb     *musb = hcd_to_musb(hcd);
        u8              devctl;
+       int             ret;
 
-       musb_port_suspend(musb, true);
+       ret = musb_port_suspend(musb, true);
+       if (ret)
+               return ret;
 
        if (!is_host_active(musb))
                return 0;
index 72392bbcd0a4b72bfead8dc2c26c7d40ea0947ee..2999845632cefb2fafa17d7da8622c06772dcda5 100644 (file)
@@ -67,7 +67,7 @@ extern void musb_host_rx(struct musb *, u8);
 extern void musb_root_disconnect(struct musb *musb);
 extern void musb_host_resume_root_hub(struct musb *musb);
 extern void musb_host_poke_root_hub(struct musb *musb);
-extern void musb_port_suspend(struct musb *musb, bool do_suspend);
+extern int musb_port_suspend(struct musb *musb, bool do_suspend);
 extern void musb_port_reset(struct musb *musb, bool do_reset);
 extern void musb_host_finish_resume(struct work_struct *work);
 #else
@@ -99,7 +99,10 @@ static inline void musb_root_disconnect(struct musb *musb)   {}
 static inline void musb_host_resume_root_hub(struct musb *musb)        {}
 static inline void musb_host_poll_rh_status(struct musb *musb) {}
 static inline void musb_host_poke_root_hub(struct musb *musb)  {}
-static inline void musb_port_suspend(struct musb *musb, bool do_suspend) {}
+static inline int musb_port_suspend(struct musb *musb, bool do_suspend)
+{
+       return 0;
+}
 static inline void musb_port_reset(struct musb *musb, bool do_reset) {}
 static inline void musb_host_finish_resume(struct work_struct *work) {}
 #endif
index 5165d2b07ade01985d2e9b104552b33d92850f47..2f8dd9826e9481a99e28f16a65be89e1e13a8955 100644 (file)
@@ -48,14 +48,14 @@ void musb_host_finish_resume(struct work_struct *work)
        spin_unlock_irqrestore(&musb->lock, flags);
 }
 
-void musb_port_suspend(struct musb *musb, bool do_suspend)
+int musb_port_suspend(struct musb *musb, bool do_suspend)
 {
        struct usb_otg  *otg = musb->xceiv->otg;
        u8              power;
        void __iomem    *mbase = musb->mregs;
 
        if (!is_host_active(musb))
-               return;
+               return 0;
 
        /* NOTE:  this doesn't necessarily put PHY into low power mode,
         * turning off its clock; that's a function of PHY integration and
@@ -66,16 +66,20 @@ void musb_port_suspend(struct musb *musb, bool do_suspend)
        if (do_suspend) {
                int retries = 10000;
 
-               power &= ~MUSB_POWER_RESUME;
-               power |= MUSB_POWER_SUSPENDM;
-               musb_writeb(mbase, MUSB_POWER, power);
+               if (power & MUSB_POWER_RESUME)
+                       return -EBUSY;
 
-               /* Needed for OPT A tests */
-               power = musb_readb(mbase, MUSB_POWER);
-               while (power & MUSB_POWER_SUSPENDM) {
+               if (!(power & MUSB_POWER_SUSPENDM)) {
+                       power |= MUSB_POWER_SUSPENDM;
+                       musb_writeb(mbase, MUSB_POWER, power);
+
+                       /* Needed for OPT A tests */
                        power = musb_readb(mbase, MUSB_POWER);
-                       if (retries-- < 1)
-                               break;
+                       while (power & MUSB_POWER_SUSPENDM) {
+                               power = musb_readb(mbase, MUSB_POWER);
+                               if (retries-- < 1)
+                                       break;
+                       }
                }
 
                musb_dbg(musb, "Root port suspended, power %02x", power);
@@ -111,6 +115,7 @@ void musb_port_suspend(struct musb *musb, bool do_suspend)
                schedule_delayed_work(&musb->finish_resume_work,
                                      msecs_to_jiffies(USB_RESUME_TIMEOUT));
        }
+       return 0;
 }
 
 void musb_port_reset(struct musb *musb, bool do_reset)
index 14a72357800ac2b10d067da9b36b7180ba5f70df..35618ceb279134bc02c6d8ff83671f55b25c82a8 100644 (file)
@@ -73,6 +73,7 @@ struct bus_id_priv {
        struct stub_device *sdev;
        struct usb_device *udev;
        char shutdown_busid;
+       spinlock_t busid_lock;
 };
 
 /* stub_priv is allocated from stub_priv_cache */
@@ -83,6 +84,7 @@ extern struct usb_device_driver stub_driver;
 
 /* stub_main.c */
 struct bus_id_priv *get_busid_priv(const char *busid);
+void put_busid_priv(struct bus_id_priv *bid);
 int del_match_busid(char *busid);
 void stub_device_cleanup_urbs(struct stub_device *sdev);
 
index dd8ef36ab10ec7d612bdb2358017f142a43906d8..c0d6ff1baa721754d42d1cae3b076685dcd86fe2 100644 (file)
@@ -300,9 +300,9 @@ static int stub_probe(struct usb_device *udev)
        struct stub_device *sdev = NULL;
        const char *udev_busid = dev_name(&udev->dev);
        struct bus_id_priv *busid_priv;
-       int rc;
+       int rc = 0;
 
-       dev_dbg(&udev->dev, "Enter\n");
+       dev_dbg(&udev->dev, "Enter probe\n");
 
        /* check we should claim or not by busid_table */
        busid_priv = get_busid_priv(udev_busid);
@@ -317,13 +317,15 @@ static int stub_probe(struct usb_device *udev)
                 * other matched drivers by the driver core.
                 * See driver_probe_device() in driver/base/dd.c
                 */
-               return -ENODEV;
+               rc = -ENODEV;
+               goto call_put_busid_priv;
        }
 
        if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) {
                dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n",
                         udev_busid);
-               return -ENODEV;
+               rc = -ENODEV;
+               goto call_put_busid_priv;
        }
 
        if (!strcmp(udev->bus->bus_name, "vhci_hcd")) {
@@ -331,13 +333,16 @@ static int stub_probe(struct usb_device *udev)
                        "%s is attached on vhci_hcd... skip!\n",
                        udev_busid);
 
-               return -ENODEV;
+               rc = -ENODEV;
+               goto call_put_busid_priv;
        }
 
        /* ok, this is my device */
        sdev = stub_device_alloc(udev);
-       if (!sdev)
-               return -ENOMEM;
+       if (!sdev) {
+               rc = -ENOMEM;
+               goto call_put_busid_priv;
+       }
 
        dev_info(&udev->dev,
                "usbip-host: register new device (bus %u dev %u)\n",
@@ -369,7 +374,9 @@ static int stub_probe(struct usb_device *udev)
        }
        busid_priv->status = STUB_BUSID_ALLOC;
 
-       return 0;
+       rc = 0;
+       goto call_put_busid_priv;
+
 err_files:
        usb_hub_release_port(udev->parent, udev->portnum,
                             (struct usb_dev_state *) udev);
@@ -379,6 +386,9 @@ err_port:
 
        busid_priv->sdev = NULL;
        stub_device_free(sdev);
+
+call_put_busid_priv:
+       put_busid_priv(busid_priv);
        return rc;
 }
 
@@ -404,7 +414,7 @@ static void stub_disconnect(struct usb_device *udev)
        struct bus_id_priv *busid_priv;
        int rc;
 
-       dev_dbg(&udev->dev, "Enter\n");
+       dev_dbg(&udev->dev, "Enter disconnect\n");
 
        busid_priv = get_busid_priv(udev_busid);
        if (!busid_priv) {
@@ -417,7 +427,7 @@ static void stub_disconnect(struct usb_device *udev)
        /* get stub_device */
        if (!sdev) {
                dev_err(&udev->dev, "could not get device");
-               return;
+               goto call_put_busid_priv;
        }
 
        dev_set_drvdata(&udev->dev, NULL);
@@ -432,12 +442,12 @@ static void stub_disconnect(struct usb_device *udev)
                                  (struct usb_dev_state *) udev);
        if (rc) {
                dev_dbg(&udev->dev, "unable to release port\n");
-               return;
+               goto call_put_busid_priv;
        }
 
        /* If usb reset is called from event handler */
        if (usbip_in_eh(current))
-               return;
+               goto call_put_busid_priv;
 
        /* shutdown the current connection */
        shutdown_busid(busid_priv);
@@ -448,12 +458,11 @@ static void stub_disconnect(struct usb_device *udev)
        busid_priv->sdev = NULL;
        stub_device_free(sdev);
 
-       if (busid_priv->status == STUB_BUSID_ALLOC) {
+       if (busid_priv->status == STUB_BUSID_ALLOC)
                busid_priv->status = STUB_BUSID_ADDED;
-       } else {
-               busid_priv->status = STUB_BUSID_OTHER;
-               del_match_busid((char *)udev_busid);
-       }
+
+call_put_busid_priv:
+       put_busid_priv(busid_priv);
 }
 
 #ifdef CONFIG_PM
index d41d0cdeec0f2a1861d8d42385a9719789cab558..bf8a5feb0ee937a35ccd7a478e7c3dd01770b4e1 100644 (file)
@@ -14,6 +14,7 @@
 #define DRIVER_DESC "USB/IP Host Driver"
 
 struct kmem_cache *stub_priv_cache;
+
 /*
  * busid_tables defines matching busids that usbip can grab. A user can change
  * dynamically what device is locally used and what device is exported to a
@@ -25,6 +26,8 @@ static spinlock_t busid_table_lock;
 
 static void init_busid_table(void)
 {
+       int i;
+
        /*
         * This also sets the bus_table[i].status to
         * STUB_BUSID_OTHER, which is 0.
@@ -32,6 +35,9 @@ static void init_busid_table(void)
        memset(busid_table, 0, sizeof(busid_table));
 
        spin_lock_init(&busid_table_lock);
+
+       for (i = 0; i < MAX_BUSID; i++)
+               spin_lock_init(&busid_table[i].busid_lock);
 }
 
 /*
@@ -43,15 +49,20 @@ static int get_busid_idx(const char *busid)
        int i;
        int idx = -1;
 
-       for (i = 0; i < MAX_BUSID; i++)
+       for (i = 0; i < MAX_BUSID; i++) {
+               spin_lock(&busid_table[i].busid_lock);
                if (busid_table[i].name[0])
                        if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
                                idx = i;
+                               spin_unlock(&busid_table[i].busid_lock);
                                break;
                        }
+               spin_unlock(&busid_table[i].busid_lock);
+       }
        return idx;
 }
 
+/* Returns holding busid_lock. Should call put_busid_priv() to unlock */
 struct bus_id_priv *get_busid_priv(const char *busid)
 {
        int idx;
@@ -59,13 +70,22 @@ struct bus_id_priv *get_busid_priv(const char *busid)
 
        spin_lock(&busid_table_lock);
        idx = get_busid_idx(busid);
-       if (idx >= 0)
+       if (idx >= 0) {
                bid = &(busid_table[idx]);
+               /* get busid_lock before returning */
+               spin_lock(&bid->busid_lock);
+       }
        spin_unlock(&busid_table_lock);
 
        return bid;
 }
 
+void put_busid_priv(struct bus_id_priv *bid)
+{
+       if (bid)
+               spin_unlock(&bid->busid_lock);
+}
+
 static int add_match_busid(char *busid)
 {
        int i;
@@ -78,15 +98,19 @@ static int add_match_busid(char *busid)
                goto out;
        }
 
-       for (i = 0; i < MAX_BUSID; i++)
+       for (i = 0; i < MAX_BUSID; i++) {
+               spin_lock(&busid_table[i].busid_lock);
                if (!busid_table[i].name[0]) {
                        strlcpy(busid_table[i].name, busid, BUSID_SIZE);
                        if ((busid_table[i].status != STUB_BUSID_ALLOC) &&
                            (busid_table[i].status != STUB_BUSID_REMOV))
                                busid_table[i].status = STUB_BUSID_ADDED;
                        ret = 0;
+                       spin_unlock(&busid_table[i].busid_lock);
                        break;
                }
+               spin_unlock(&busid_table[i].busid_lock);
+       }
 
 out:
        spin_unlock(&busid_table_lock);
@@ -107,6 +131,8 @@ int del_match_busid(char *busid)
        /* found */
        ret = 0;
 
+       spin_lock(&busid_table[idx].busid_lock);
+
        if (busid_table[idx].status == STUB_BUSID_OTHER)
                memset(busid_table[idx].name, 0, BUSID_SIZE);
 
@@ -114,6 +140,7 @@ int del_match_busid(char *busid)
            (busid_table[idx].status != STUB_BUSID_ADDED))
                busid_table[idx].status = STUB_BUSID_REMOV;
 
+       spin_unlock(&busid_table[idx].busid_lock);
 out:
        spin_unlock(&busid_table_lock);
 
@@ -126,9 +153,12 @@ static ssize_t match_busid_show(struct device_driver *drv, char *buf)
        char *out = buf;
 
        spin_lock(&busid_table_lock);
-       for (i = 0; i < MAX_BUSID; i++)
+       for (i = 0; i < MAX_BUSID; i++) {
+               spin_lock(&busid_table[i].busid_lock);
                if (busid_table[i].name[0])
                        out += sprintf(out, "%s ", busid_table[i].name);
+               spin_unlock(&busid_table[i].busid_lock);
+       }
        spin_unlock(&busid_table_lock);
        out += sprintf(out, "\n");
 
@@ -169,6 +199,51 @@ static ssize_t match_busid_store(struct device_driver *dev, const char *buf,
 }
 static DRIVER_ATTR_RW(match_busid);
 
+static int do_rebind(char *busid, struct bus_id_priv *busid_priv)
+{
+       int ret;
+
+       /* device_attach() callers should hold parent lock for USB */
+       if (busid_priv->udev->dev.parent)
+               device_lock(busid_priv->udev->dev.parent);
+       ret = device_attach(&busid_priv->udev->dev);
+       if (busid_priv->udev->dev.parent)
+               device_unlock(busid_priv->udev->dev.parent);
+       if (ret < 0) {
+               dev_err(&busid_priv->udev->dev, "rebind failed\n");
+               return ret;
+       }
+       return 0;
+}
+
+static void stub_device_rebind(void)
+{
+#if IS_MODULE(CONFIG_USBIP_HOST)
+       struct bus_id_priv *busid_priv;
+       int i;
+
+       /* update status to STUB_BUSID_OTHER so probe ignores the device */
+       spin_lock(&busid_table_lock);
+       for (i = 0; i < MAX_BUSID; i++) {
+               if (busid_table[i].name[0] &&
+                   busid_table[i].shutdown_busid) {
+                       busid_priv = &(busid_table[i]);
+                       busid_priv->status = STUB_BUSID_OTHER;
+               }
+       }
+       spin_unlock(&busid_table_lock);
+
+       /* now run rebind - no need to hold locks. driver files are removed */
+       for (i = 0; i < MAX_BUSID; i++) {
+               if (busid_table[i].name[0] &&
+                   busid_table[i].shutdown_busid) {
+                       busid_priv = &(busid_table[i]);
+                       do_rebind(busid_table[i].name, busid_priv);
+               }
+       }
+#endif
+}
+
 static ssize_t rebind_store(struct device_driver *dev, const char *buf,
                                 size_t count)
 {
@@ -186,16 +261,17 @@ static ssize_t rebind_store(struct device_driver *dev, const char *buf,
        if (!bid)
                return -ENODEV;
 
-       /* device_attach() callers should hold parent lock for USB */
-       if (bid->udev->dev.parent)
-               device_lock(bid->udev->dev.parent);
-       ret = device_attach(&bid->udev->dev);
-       if (bid->udev->dev.parent)
-               device_unlock(bid->udev->dev.parent);
-       if (ret < 0) {
-               dev_err(&bid->udev->dev, "rebind failed\n");
+       /* mark the device for deletion so probe ignores it during rescan */
+       bid->status = STUB_BUSID_OTHER;
+       /* release the busid lock */
+       put_busid_priv(bid);
+
+       ret = do_rebind((char *) buf, bid);
+       if (ret < 0)
                return ret;
-       }
+
+       /* delete device from busid_table */
+       del_match_busid((char *) buf);
 
        return count;
 }
@@ -317,6 +393,9 @@ static void __exit usbip_host_exit(void)
         */
        usb_deregister_device_driver(&stub_driver);
 
+       /* initiate scan to attach devices */
+       stub_device_rebind();
+
        kmem_cache_destroy(stub_priv_cache);
 }
 
index 3bedfed608a22eb77b1addd59f7a263f1bd722b8..7587fb665ff189b088b1a9bb9e8c1b7c7005c083 100644 (file)
@@ -121,7 +121,7 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
        p = text;
        do {
                struct sockaddr_rxrpc *srx = &alist->addrs[alist->nr_addrs];
-               char tdelim = delim;
+               const char *q, *stop;
 
                if (*p == delim) {
                        p++;
@@ -130,28 +130,33 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
 
                if (*p == '[') {
                        p++;
-                       tdelim = ']';
+                       q = memchr(p, ']', end - p);
+               } else {
+                       for (q = p; q < end; q++)
+                               if (*q == '+' || *q == delim)
+                                       break;
                }
 
-               if (in4_pton(p, end - p,
+               if (in4_pton(p, q - p,
                             (u8 *)&srx->transport.sin6.sin6_addr.s6_addr32[3],
-                            tdelim, &p)) {
+                            -1, &stop)) {
                        srx->transport.sin6.sin6_addr.s6_addr32[0] = 0;
                        srx->transport.sin6.sin6_addr.s6_addr32[1] = 0;
                        srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
-               } else if (in6_pton(p, end - p,
+               } else if (in6_pton(p, q - p,
                                    srx->transport.sin6.sin6_addr.s6_addr,
-                                   tdelim, &p)) {
+                                   -1, &stop)) {
                        /* Nothing to do */
                } else {
                        goto bad_address;
                }
 
-               if (tdelim == ']') {
-                       if (p == end || *p != ']')
-                               goto bad_address;
+               if (stop != q)
+                       goto bad_address;
+
+               p = q;
+               if (q < end && *q == ']')
                        p++;
-               }
 
                if (p < end) {
                        if (*p == '+') {
index abd9a84f4e88a6dbded5eb02aa75e46a239a4c56..571437dcb252842578b92a6f3b5b60a574703b94 100644 (file)
 /*
  * Set up an interest-in-callbacks record for a volume on a server and
  * register it with the server.
- * - Called with volume->server_sem held.
+ * - Called with vnode->io_lock held.
  */
 int afs_register_server_cb_interest(struct afs_vnode *vnode,
-                                   struct afs_server_entry *entry)
+                                   struct afs_server_list *slist,
+                                   unsigned int index)
 {
-       struct afs_cb_interest *cbi = entry->cb_interest, *vcbi, *new, *x;
+       struct afs_server_entry *entry = &slist->servers[index];
+       struct afs_cb_interest *cbi, *vcbi, *new, *old;
        struct afs_server *server = entry->server;
 
 again:
+       if (vnode->cb_interest &&
+           likely(vnode->cb_interest == entry->cb_interest))
+               return 0;
+
+       read_lock(&slist->lock);
+       cbi = afs_get_cb_interest(entry->cb_interest);
+       read_unlock(&slist->lock);
+
        vcbi = vnode->cb_interest;
        if (vcbi) {
-               if (vcbi == cbi)
+               if (vcbi == cbi) {
+                       afs_put_cb_interest(afs_v2net(vnode), cbi);
                        return 0;
+               }
 
+               /* Use a new interest in the server list for the same server
+                * rather than an old one that's still attached to a vnode.
+                */
                if (cbi && vcbi->server == cbi->server) {
                        write_seqlock(&vnode->cb_lock);
-                       vnode->cb_interest = afs_get_cb_interest(cbi);
+                       old = vnode->cb_interest;
+                       vnode->cb_interest = cbi;
                        write_sequnlock(&vnode->cb_lock);
-                       afs_put_cb_interest(afs_v2net(vnode), cbi);
+                       afs_put_cb_interest(afs_v2net(vnode), old);
                        return 0;
                }
 
+               /* Re-use the one attached to the vnode. */
                if (!cbi && vcbi->server == server) {
-                       afs_get_cb_interest(vcbi);
-                       x = cmpxchg(&entry->cb_interest, cbi, vcbi);
-                       if (x != cbi) {
-                               cbi = x;
-                               afs_put_cb_interest(afs_v2net(vnode), vcbi);
+                       write_lock(&slist->lock);
+                       if (entry->cb_interest) {
+                               write_unlock(&slist->lock);
+                               afs_put_cb_interest(afs_v2net(vnode), cbi);
                                goto again;
                        }
+
+                       entry->cb_interest = cbi;
+                       write_unlock(&slist->lock);
                        return 0;
                }
        }
@@ -72,13 +91,16 @@ again:
                list_add_tail(&new->cb_link, &server->cb_interests);
                write_unlock(&server->cb_break_lock);
 
-               x = cmpxchg(&entry->cb_interest, cbi, new);
-               if (x == cbi) {
+               write_lock(&slist->lock);
+               if (!entry->cb_interest) {
+                       entry->cb_interest = afs_get_cb_interest(new);
                        cbi = new;
+                       new = NULL;
                } else {
-                       cbi = x;
-                       afs_put_cb_interest(afs_v2net(vnode), new);
+                       cbi = afs_get_cb_interest(entry->cb_interest);
                }
+               write_unlock(&slist->lock);
+               afs_put_cb_interest(afs_v2net(vnode), new);
        }
 
        ASSERT(cbi);
@@ -88,11 +110,14 @@ again:
         */
        write_seqlock(&vnode->cb_lock);
 
-       vnode->cb_interest = afs_get_cb_interest(cbi);
+       old = vnode->cb_interest;
+       vnode->cb_interest = cbi;
        vnode->cb_s_break = cbi->server->cb_s_break;
+       vnode->cb_v_break = vnode->volume->cb_v_break;
        clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
 
        write_sequnlock(&vnode->cb_lock);
+       afs_put_cb_interest(afs_v2net(vnode), old);
        return 0;
 }
 
@@ -171,13 +196,24 @@ static void afs_break_one_callback(struct afs_server *server,
                if (cbi->vid != fid->vid)
                        continue;
 
-               data.volume = NULL;
-               data.fid = *fid;
-               inode = ilookup5_nowait(cbi->sb, fid->vnode, afs_iget5_test, &data);
-               if (inode) {
-                       vnode = AFS_FS_I(inode);
-                       afs_break_callback(vnode);
-                       iput(inode);
+               if (fid->vnode == 0 && fid->unique == 0) {
+                       /* The callback break applies to an entire volume. */
+                       struct afs_super_info *as = AFS_FS_S(cbi->sb);
+                       struct afs_volume *volume = as->volume;
+
+                       write_lock(&volume->cb_break_lock);
+                       volume->cb_v_break++;
+                       write_unlock(&volume->cb_break_lock);
+               } else {
+                       data.volume = NULL;
+                       data.fid = *fid;
+                       inode = ilookup5_nowait(cbi->sb, fid->vnode,
+                                               afs_iget5_test, &data);
+                       if (inode) {
+                               vnode = AFS_FS_I(inode);
+                               afs_break_callback(vnode);
+                               iput(inode);
+                       }
                }
        }
 
@@ -195,6 +231,8 @@ void afs_break_callbacks(struct afs_server *server, size_t count,
        ASSERT(server != NULL);
        ASSERTCMP(count, <=, AFSCBMAX);
 
+       /* TODO: Sort the callback break list by volume ID */
+
        for (; count > 0; callbacks++, count--) {
                _debug("- Fid { vl=%08x n=%u u=%u }  CB { v=%u x=%u t=%u }",
                       callbacks->fid.vid,
index 357de908df3ab258c6b0d2d3fbf8cdf94e7b1575..c332c95a6940f50fe3a9e220ebbb6928b0f5d27c 100644 (file)
@@ -133,21 +133,10 @@ bool afs_cm_incoming_call(struct afs_call *call)
 }
 
 /*
- * clean up a cache manager call
+ * Clean up a cache manager call.
  */
 static void afs_cm_destructor(struct afs_call *call)
 {
-       _enter("");
-
-       /* Break the callbacks here so that we do it after the final ACK is
-        * received.  The step number here must match the final number in
-        * afs_deliver_cb_callback().
-        */
-       if (call->unmarshall == 5) {
-               ASSERT(call->cm_server && call->count && call->request);
-               afs_break_callbacks(call->cm_server, call->count, call->request);
-       }
-
        kfree(call->buffer);
        call->buffer = NULL;
 }
@@ -161,14 +150,14 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
 
        _enter("");
 
-       /* be sure to send the reply *before* attempting to spam the AFS server
-        * with FSFetchStatus requests on the vnodes with broken callbacks lest
-        * the AFS server get into a vicious cycle of trying to break further
-        * callbacks because it hadn't received completion of the CBCallBack op
-        * yet */
-       afs_send_empty_reply(call);
+       /* We need to break the callbacks before sending the reply as the
+        * server holds up change visibility till it receives our reply so as
+        * to maintain cache coherency.
+        */
+       if (call->cm_server)
+               afs_break_callbacks(call->cm_server, call->count, call->request);
 
-       afs_break_callbacks(call->cm_server, call->count, call->request);
+       afs_send_empty_reply(call);
        afs_put_call(call);
        _leave("");
 }
@@ -180,7 +169,6 @@ static int afs_deliver_cb_callback(struct afs_call *call)
 {
        struct afs_callback_break *cb;
        struct sockaddr_rxrpc srx;
-       struct afs_server *server;
        __be32 *bp;
        int ret, loop;
 
@@ -267,15 +255,6 @@ static int afs_deliver_cb_callback(struct afs_call *call)
 
                call->offset = 0;
                call->unmarshall++;
-
-               /* Record that the message was unmarshalled successfully so
-                * that the call destructor can know do the callback breaking
-                * work, even if the final ACK isn't received.
-                *
-                * If the step number changes, then afs_cm_destructor() must be
-                * updated also.
-                */
-               call->unmarshall++;
        case 5:
                break;
        }
@@ -286,10 +265,9 @@ static int afs_deliver_cb_callback(struct afs_call *call)
        /* we'll need the file server record as that tells us which set of
         * vnodes to operate upon */
        rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
-       server = afs_find_server(call->net, &srx);
-       if (!server)
-               return -ENOTCONN;
-       call->cm_server = server;
+       call->cm_server = afs_find_server(call->net, &srx);
+       if (!call->cm_server)
+               trace_afs_cm_no_server(call, &srx);
 
        return afs_queue_call_work(call);
 }
@@ -303,7 +281,8 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work)
 
        _enter("{%p}", call->cm_server);
 
-       afs_init_callback_state(call->cm_server);
+       if (call->cm_server)
+               afs_init_callback_state(call->cm_server);
        afs_send_empty_reply(call);
        afs_put_call(call);
        _leave("");
@@ -315,7 +294,6 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work)
 static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
 {
        struct sockaddr_rxrpc srx;
-       struct afs_server *server;
        int ret;
 
        _enter("");
@@ -328,10 +306,9 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
 
        /* we'll need the file server record as that tells us which set of
         * vnodes to operate upon */
-       server = afs_find_server(call->net, &srx);
-       if (!server)
-               return -ENOTCONN;
-       call->cm_server = server;
+       call->cm_server = afs_find_server(call->net, &srx);
+       if (!call->cm_server)
+               trace_afs_cm_no_server(call, &srx);
 
        return afs_queue_call_work(call);
 }
@@ -341,8 +318,6 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
  */
 static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
 {
-       struct sockaddr_rxrpc srx;
-       struct afs_server *server;
        struct afs_uuid *r;
        unsigned loop;
        __be32 *b;
@@ -398,11 +373,11 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
 
        /* we'll need the file server record as that tells us which set of
         * vnodes to operate upon */
-       rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
-       server = afs_find_server(call->net, &srx);
-       if (!server)
-               return -ENOTCONN;
-       call->cm_server = server;
+       rcu_read_lock();
+       call->cm_server = afs_find_server_by_uuid(call->net, call->request);
+       rcu_read_unlock();
+       if (!call->cm_server)
+               trace_afs_cm_no_server_u(call, call->request);
 
        return afs_queue_call_work(call);
 }
index 5889f70d4d273a8622aefbd32148e8ff8e1b7d55..7d623008157ffaf9c77ac6a614a0e329f769c35e 100644 (file)
@@ -180,6 +180,7 @@ static int afs_dir_open(struct inode *inode, struct file *file)
  * get reclaimed during the iteration.
  */
 static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
+       __acquires(&dvnode->validate_lock)
 {
        struct afs_read *req;
        loff_t i_size;
@@ -261,18 +262,21 @@ retry:
        /* If we're going to reload, we need to lock all the pages to prevent
         * races.
         */
-       if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
-               ret = -ERESTARTSYS;
-               for (i = 0; i < req->nr_pages; i++)
-                       if (lock_page_killable(req->pages[i]) < 0)
-                               goto error_unlock;
+       ret = -ERESTARTSYS;
+       if (down_read_killable(&dvnode->validate_lock) < 0)
+               goto error;
 
-               if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
-                       goto success;
+       if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
+               goto success;
+
+       up_read(&dvnode->validate_lock);
+       if (down_write_killable(&dvnode->validate_lock) < 0)
+               goto error;
 
+       if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
                ret = afs_fetch_data(dvnode, key, req);
                if (ret < 0)
-                       goto error_unlock_all;
+                       goto error_unlock;
 
                task_io_account_read(PAGE_SIZE * req->nr_pages);
 
@@ -284,33 +288,26 @@ retry:
                for (i = 0; i < req->nr_pages; i++)
                        if (!afs_dir_check_page(dvnode, req->pages[i],
                                                req->actual_len))
-                               goto error_unlock_all;
+                               goto error_unlock;
 
                // TODO: Trim excess pages
 
                set_bit(AFS_VNODE_DIR_VALID, &dvnode->flags);
        }
 
+       downgrade_write(&dvnode->validate_lock);
 success:
-       i = req->nr_pages;
-       while (i > 0)
-               unlock_page(req->pages[--i]);
        return req;
 
-error_unlock_all:
-       i = req->nr_pages;
 error_unlock:
-       while (i > 0)
-               unlock_page(req->pages[--i]);
+       up_write(&dvnode->validate_lock);
 error:
        afs_put_read(req);
        _leave(" = %d", ret);
        return ERR_PTR(ret);
 
 content_has_grown:
-       i = req->nr_pages;
-       while (i > 0)
-               unlock_page(req->pages[--i]);
+       up_write(&dvnode->validate_lock);
        afs_put_read(req);
        goto retry;
 }
@@ -473,6 +470,7 @@ static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
        }
 
 out:
+       up_read(&dvnode->validate_lock);
        afs_put_read(req);
        _leave(" = %d", ret);
        return ret;
@@ -1143,7 +1141,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, dvnode, key)) {
                while (afs_select_fileserver(&fc)) {
-                       fc.cb_break = dvnode->cb_break + dvnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(dvnode);
                        afs_fs_create(&fc, dentry->d_name.name, mode, data_version,
                                      &newfid, &newstatus, &newcb);
                }
@@ -1213,7 +1211,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, dvnode, key)) {
                while (afs_select_fileserver(&fc)) {
-                       fc.cb_break = dvnode->cb_break + dvnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(dvnode);
                        afs_fs_remove(&fc, dentry->d_name.name, true,
                                      data_version);
                }
@@ -1316,7 +1314,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, dvnode, key)) {
                while (afs_select_fileserver(&fc)) {
-                       fc.cb_break = dvnode->cb_break + dvnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(dvnode);
                        afs_fs_remove(&fc, dentry->d_name.name, false,
                                      data_version);
                }
@@ -1373,7 +1371,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, dvnode, key)) {
                while (afs_select_fileserver(&fc)) {
-                       fc.cb_break = dvnode->cb_break + dvnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(dvnode);
                        afs_fs_create(&fc, dentry->d_name.name, mode, data_version,
                                      &newfid, &newstatus, &newcb);
                }
@@ -1443,8 +1441,8 @@ static int afs_link(struct dentry *from, struct inode *dir,
                }
 
                while (afs_select_fileserver(&fc)) {
-                       fc.cb_break = dvnode->cb_break + dvnode->cb_s_break;
-                       fc.cb_break_2 = vnode->cb_break + vnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(dvnode);
+                       fc.cb_break_2 = afs_calc_vnode_cb_break(vnode);
                        afs_fs_link(&fc, vnode, dentry->d_name.name, data_version);
                }
 
@@ -1512,7 +1510,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, dvnode, key)) {
                while (afs_select_fileserver(&fc)) {
-                       fc.cb_break = dvnode->cb_break + dvnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(dvnode);
                        afs_fs_symlink(&fc, dentry->d_name.name,
                                       content, data_version,
                                       &newfid, &newstatus);
@@ -1588,8 +1586,8 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        }
                }
                while (afs_select_fileserver(&fc)) {
-                       fc.cb_break = orig_dvnode->cb_break + orig_dvnode->cb_s_break;
-                       fc.cb_break_2 = new_dvnode->cb_break + new_dvnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(orig_dvnode);
+                       fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode);
                        afs_fs_rename(&fc, old_dentry->d_name.name,
                                      new_dvnode, new_dentry->d_name.name,
                                      orig_data_version, new_data_version);
index c24c08016dd96e2309ce9e8052d643b2af6da2a6..7d4f26198573d7f6a4dffb7ff4a82ee0f8fbb573 100644 (file)
@@ -238,7 +238,7 @@ int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *de
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, vnode, key)) {
                while (afs_select_fileserver(&fc)) {
-                       fc.cb_break = vnode->cb_break + vnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(vnode);
                        afs_fs_fetch_data(&fc, desc);
                }
 
index 7a0e017070ecede45ed1eb622ac89f6f5a33a5d1..dc62d15a964b8809d7028d33a393c41b6963242b 100644 (file)
@@ -86,7 +86,7 @@ static int afs_set_lock(struct afs_vnode *vnode, struct key *key,
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, vnode, key)) {
                while (afs_select_fileserver(&fc)) {
-                       fc.cb_break = vnode->cb_break + vnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(vnode);
                        afs_fs_set_lock(&fc, type);
                }
 
@@ -117,7 +117,7 @@ static int afs_extend_lock(struct afs_vnode *vnode, struct key *key)
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, vnode, key)) {
                while (afs_select_current_fileserver(&fc)) {
-                       fc.cb_break = vnode->cb_break + vnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(vnode);
                        afs_fs_extend_lock(&fc);
                }
 
@@ -148,7 +148,7 @@ static int afs_release_lock(struct afs_vnode *vnode, struct key *key)
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, vnode, key)) {
                while (afs_select_current_fileserver(&fc)) {
-                       fc.cb_break = vnode->cb_break + vnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(vnode);
                        afs_fs_release_lock(&fc);
                }
 
index efacdb7c1dee59ad78e0c600e73468ea90285638..b273e1d60478c3c9f89a84a7b85fb6325a9a2c84 100644 (file)
@@ -134,6 +134,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
                                     struct afs_read *read_req)
 {
        const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp;
+       bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
        u64 data_version, size;
        u32 type, abort_code;
        u8 flags = 0;
@@ -142,13 +143,32 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
        if (vnode)
                write_seqlock(&vnode->cb_lock);
 
+       abort_code = ntohl(xdr->abort_code);
+
        if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) {
+               if (xdr->if_version == htonl(0) &&
+                   abort_code != 0 &&
+                   inline_error) {
+                       /* The OpenAFS fileserver has a bug in FS.InlineBulkStatus
+                        * whereby it doesn't set the interface version in the error
+                        * case.
+                        */
+                       status->abort_code = abort_code;
+                       ret = 0;
+                       goto out;
+               }
+
                pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
                goto bad;
        }
 
+       if (abort_code != 0 && inline_error) {
+               status->abort_code = abort_code;
+               ret = 0;
+               goto out;
+       }
+
        type = ntohl(xdr->type);
-       abort_code = ntohl(xdr->abort_code);
        switch (type) {
        case AFS_FTYPE_FILE:
        case AFS_FTYPE_DIR:
@@ -165,13 +185,6 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
                }
                status->type = type;
                break;
-       case AFS_FTYPE_INVALID:
-               if (abort_code != 0) {
-                       status->abort_code = abort_code;
-                       ret = 0;
-                       goto out;
-               }
-               /* Fall through */
        default:
                goto bad;
        }
@@ -248,7 +261,7 @@ static void xdr_decode_AFSCallBack(struct afs_call *call,
 
        write_seqlock(&vnode->cb_lock);
 
-       if (call->cb_break == (vnode->cb_break + cbi->server->cb_s_break)) {
+       if (call->cb_break == afs_cb_break_sum(vnode, cbi)) {
                vnode->cb_version       = ntohl(*bp++);
                cb_expiry               = ntohl(*bp++);
                vnode->cb_type          = ntohl(*bp++);
index 06194cfe9724ca8bfa9ce7e0cad9d44bbe06a262..479b7fdda1244f5bf210694e275826cba99b5553 100644 (file)
@@ -108,7 +108,7 @@ int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode)
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, vnode, key)) {
                while (afs_select_fileserver(&fc)) {
-                       fc.cb_break = vnode->cb_break + vnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(vnode);
                        afs_fs_fetch_file_status(&fc, NULL, new_inode);
                }
 
@@ -393,15 +393,18 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
        read_seqlock_excl(&vnode->cb_lock);
 
        if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
-               if (vnode->cb_s_break != vnode->cb_interest->server->cb_s_break) {
+               if (vnode->cb_s_break != vnode->cb_interest->server->cb_s_break ||
+                   vnode->cb_v_break != vnode->volume->cb_v_break) {
                        vnode->cb_s_break = vnode->cb_interest->server->cb_s_break;
+                       vnode->cb_v_break = vnode->volume->cb_v_break;
+                       valid = false;
                } else if (vnode->status.type == AFS_FTYPE_DIR &&
                           test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) &&
                           vnode->cb_expires_at - 10 > now) {
-                               valid = true;
+                       valid = true;
                } else if (!test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) &&
                           vnode->cb_expires_at - 10 > now) {
-                               valid = true;
+                       valid = true;
                }
        } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
                valid = true;
@@ -415,7 +418,7 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
        if (valid)
                goto valid;
 
-       mutex_lock(&vnode->validate_lock);
+       down_write(&vnode->validate_lock);
 
        /* if the promise has expired, we need to check the server again to get
         * a new promise - note that if the (parent) directory's metadata was
@@ -444,13 +447,13 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
         * different */
        if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
                afs_zap_data(vnode);
-       mutex_unlock(&vnode->validate_lock);
+       up_write(&vnode->validate_lock);
 valid:
        _leave(" = 0");
        return 0;
 
 error_unlock:
-       mutex_unlock(&vnode->validate_lock);
+       up_write(&vnode->validate_lock);
        _leave(" = %d", ret);
        return ret;
 }
@@ -574,7 +577,7 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, vnode, key)) {
                while (afs_select_fileserver(&fc)) {
-                       fc.cb_break = vnode->cb_break + vnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(vnode);
                        afs_fs_setattr(&fc, attr);
                }
 
index f8086ec95e24161eb9b9900745275e1cc4c1cfc6..e3f8a46663dbade0149d44e0d543bb7f171170a7 100644 (file)
@@ -396,6 +396,7 @@ struct afs_server {
 #define AFS_SERVER_FL_PROBED   5               /* The fileserver has been probed */
 #define AFS_SERVER_FL_PROBING  6               /* Fileserver is being probed */
 #define AFS_SERVER_FL_NO_IBULK 7               /* Fileserver doesn't support FS.InlineBulkStatus */
+#define AFS_SERVER_FL_MAY_HAVE_CB 8            /* May have callbacks on this fileserver */
        atomic_t                usage;
        u32                     addr_version;   /* Address list version */
 
@@ -433,6 +434,7 @@ struct afs_server_list {
        unsigned short          index;          /* Server currently in use */
        unsigned short          vnovol_mask;    /* Servers to be skipped due to VNOVOL */
        unsigned int            seq;            /* Set to ->servers_seq when installed */
+       rwlock_t                lock;
        struct afs_server_entry servers[];
 };
 
@@ -459,6 +461,9 @@ struct afs_volume {
        rwlock_t                servers_lock;   /* Lock for ->servers */
        unsigned int            servers_seq;    /* Incremented each time ->servers changes */
 
+       unsigned                cb_v_break;     /* Break-everything counter. */
+       rwlock_t                cb_break_lock;
+
        afs_voltype_t           type;           /* type of volume */
        short                   error;
        char                    type_force;     /* force volume type (suppress R/O -> R/W) */
@@ -494,7 +499,7 @@ struct afs_vnode {
 #endif
        struct afs_permits __rcu *permit_cache; /* cache of permits so far obtained */
        struct mutex            io_lock;        /* Lock for serialising I/O on this mutex */
-       struct mutex            validate_lock;  /* lock for validating this vnode */
+       struct rw_semaphore     validate_lock;  /* lock for validating this vnode */
        spinlock_t              wb_lock;        /* lock for wb_keys */
        spinlock_t              lock;           /* waitqueue/flags lock */
        unsigned long           flags;
@@ -519,6 +524,7 @@ struct afs_vnode {
        /* outstanding callback notification on this file */
        struct afs_cb_interest  *cb_interest;   /* Server on which this resides */
        unsigned int            cb_s_break;     /* Mass break counter on ->server */
+       unsigned int            cb_v_break;     /* Mass break counter on ->volume */
        unsigned int            cb_break;       /* Break counter on vnode */
        seqlock_t               cb_lock;        /* Lock for ->cb_interest, ->status, ->cb_*break */
 
@@ -648,16 +654,29 @@ extern void afs_init_callback_state(struct afs_server *);
 extern void afs_break_callback(struct afs_vnode *);
 extern void afs_break_callbacks(struct afs_server *, size_t, struct afs_callback_break*);
 
-extern int afs_register_server_cb_interest(struct afs_vnode *, struct afs_server_entry *);
+extern int afs_register_server_cb_interest(struct afs_vnode *,
+                                          struct afs_server_list *, unsigned int);
 extern void afs_put_cb_interest(struct afs_net *, struct afs_cb_interest *);
 extern void afs_clear_callback_interests(struct afs_net *, struct afs_server_list *);
 
 static inline struct afs_cb_interest *afs_get_cb_interest(struct afs_cb_interest *cbi)
 {
-       refcount_inc(&cbi->usage);
+       if (cbi)
+               refcount_inc(&cbi->usage);
        return cbi;
 }
 
+static inline unsigned int afs_calc_vnode_cb_break(struct afs_vnode *vnode)
+{
+       return vnode->cb_break + vnode->cb_s_break + vnode->cb_v_break;
+}
+
+static inline unsigned int afs_cb_break_sum(struct afs_vnode *vnode,
+                                           struct afs_cb_interest *cbi)
+{
+       return vnode->cb_break + cbi->server->cb_s_break + vnode->volume->cb_v_break;
+}
+
 /*
  * cell.c
  */
index ac0feac9d7468cfeb48b4161ed70961b2088b663..e065bc0768e6a5068ef762e3d3967fc54d50e2b2 100644 (file)
@@ -179,7 +179,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
                         */
                        if (fc->flags & AFS_FS_CURSOR_VNOVOL) {
                                fc->ac.error = -EREMOTEIO;
-                               goto failed;
+                               goto next_server;
                        }
 
                        write_lock(&vnode->volume->servers_lock);
@@ -201,7 +201,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
                         */
                        if (vnode->volume->servers == fc->server_list) {
                                fc->ac.error = -EREMOTEIO;
-                               goto failed;
+                               goto next_server;
                        }
 
                        /* Try again */
@@ -350,8 +350,8 @@ use_server:
         * break request before we've finished decoding the reply and
         * installing the vnode.
         */
-       fc->ac.error = afs_register_server_cb_interest(
-               vnode, &fc->server_list->servers[fc->index]);
+       fc->ac.error = afs_register_server_cb_interest(vnode, fc->server_list,
+                                                      fc->index);
        if (fc->ac.error < 0)
                goto failed;
 
@@ -369,8 +369,16 @@ use_server:
        if (!test_bit(AFS_SERVER_FL_PROBED, &server->flags)) {
                fc->ac.alist = afs_get_addrlist(alist);
 
-               if (!afs_probe_fileserver(fc))
-                       goto failed;
+               if (!afs_probe_fileserver(fc)) {
+                       switch (fc->ac.error) {
+                       case -ENOMEM:
+                       case -ERESTARTSYS:
+                       case -EINTR:
+                               goto failed;
+                       default:
+                               goto next_server;
+                       }
+               }
        }
 
        if (!fc->ac.alist)
index 5c6263972ec9a5651a28fd7ea7c80398e737a090..08735948f15d4caec78be59d5e1c4623591e92d4 100644 (file)
@@ -41,6 +41,7 @@ int afs_open_socket(struct afs_net *net)
 {
        struct sockaddr_rxrpc srx;
        struct socket *socket;
+       unsigned int min_level;
        int ret;
 
        _enter("");
@@ -60,6 +61,12 @@ int afs_open_socket(struct afs_net *net)
        srx.transport.sin6.sin6_family  = AF_INET6;
        srx.transport.sin6.sin6_port    = htons(AFS_CM_PORT);
 
+       min_level = RXRPC_SECURITY_ENCRYPT;
+       ret = kernel_setsockopt(socket, SOL_RXRPC, RXRPC_MIN_SECURITY_LEVEL,
+                               (void *)&min_level, sizeof(min_level));
+       if (ret < 0)
+               goto error_2;
+
        ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
        if (ret == -EADDRINUSE) {
                srx.transport.sin6.sin6_port = 0;
@@ -482,8 +489,12 @@ static void afs_deliver_to_call(struct afs_call *call)
                state = READ_ONCE(call->state);
                switch (ret) {
                case 0:
-                       if (state == AFS_CALL_CL_PROC_REPLY)
+                       if (state == AFS_CALL_CL_PROC_REPLY) {
+                               if (call->cbi)
+                                       set_bit(AFS_SERVER_FL_MAY_HAVE_CB,
+                                               &call->cbi->server->flags);
                                goto call_complete;
+                       }
                        ASSERTCMP(state, >, AFS_CALL_CL_PROC_REPLY);
                        goto done;
                case -EINPROGRESS:
@@ -493,11 +504,6 @@ static void afs_deliver_to_call(struct afs_call *call)
                case -ECONNABORTED:
                        ASSERTCMP(state, ==, AFS_CALL_COMPLETE);
                        goto done;
-               case -ENOTCONN:
-                       abort_code = RX_CALL_DEAD;
-                       rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
-                                               abort_code, ret, "KNC");
-                       goto local_abort;
                case -ENOTSUPP:
                        abort_code = RXGEN_OPCODE;
                        rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
index cea2fff313dc6e3a1efb3c3030a8a59f92136933..1992b0ffa54374da648efbd7ab5b9a87ae3c1889 100644 (file)
@@ -147,8 +147,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
                                        break;
                                }
 
-                               if (cb_break != (vnode->cb_break +
-                                                vnode->cb_interest->server->cb_s_break)) {
+                               if (cb_break != afs_cb_break_sum(vnode, vnode->cb_interest)) {
                                        changed = true;
                                        break;
                                }
@@ -178,7 +177,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key,
                }
        }
 
-       if (cb_break != (vnode->cb_break + vnode->cb_interest->server->cb_s_break))
+       if (cb_break != afs_cb_break_sum(vnode, vnode->cb_interest))
                goto someone_else_changed_it;
 
        /* We need a ref on any permits list we want to copy as we'll have to
@@ -257,7 +256,7 @@ found:
 
        spin_lock(&vnode->lock);
        zap = rcu_access_pointer(vnode->permit_cache);
-       if (cb_break == (vnode->cb_break + vnode->cb_interest->server->cb_s_break) &&
+       if (cb_break == afs_cb_break_sum(vnode, vnode->cb_interest) &&
            zap == permits)
                rcu_assign_pointer(vnode->permit_cache, replacement);
        else
index 629c74986cff4ad1535fcc3c814b6150011c5dec..3af4625e2f8cc7049185048a602826c53a169c03 100644 (file)
@@ -67,12 +67,6 @@ struct afs_server *afs_find_server(struct afs_net *net,
                                                              sizeof(struct in6_addr));
                                        if (diff == 0)
                                                goto found;
-                                       if (diff < 0) {
-                                               // TODO: Sort the list
-                                               //if (i == alist->nr_ipv4)
-                                               //      goto not_found;
-                                               break;
-                                       }
                                }
                        }
                } else {
@@ -87,17 +81,10 @@ struct afs_server *afs_find_server(struct afs_net *net,
                                                        (u32 __force)b->sin6_addr.s6_addr32[3]);
                                        if (diff == 0)
                                                goto found;
-                                       if (diff < 0) {
-                                               // TODO: Sort the list
-                                               //if (i == 0)
-                                               //      goto not_found;
-                                               break;
-                                       }
                                }
                        }
                }
 
-       //not_found:
                server = NULL;
        found:
                if (server && !atomic_inc_not_zero(&server->usage))
@@ -395,14 +382,16 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
        struct afs_addr_list *alist = rcu_access_pointer(server->addresses);
        struct afs_addr_cursor ac = {
                .alist  = alist,
-               .addr   = &alist->addrs[0],
                .start  = alist->index,
-               .index  = alist->index,
+               .index  = 0,
+               .addr   = &alist->addrs[alist->index],
                .error  = 0,
        };
        _enter("%p", server);
 
-       afs_fs_give_up_all_callbacks(net, server, &ac, NULL);
+       if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags))
+               afs_fs_give_up_all_callbacks(net, server, &ac, NULL);
+
        call_rcu(&server->rcu, afs_server_rcu);
        afs_dec_servers_outstanding(net);
 }
index 0f8dc4c8f07c43b3efb0f899b8a40b8f1a697e6c..8a5760aa583213a608d686b60f0782ecbed648e1 100644 (file)
@@ -49,6 +49,7 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
                goto error;
 
        refcount_set(&slist->usage, 1);
+       rwlock_init(&slist->lock);
 
        /* Make sure a records exists for each server in the list. */
        for (i = 0; i < vldb->nr_servers; i++) {
@@ -64,9 +65,11 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
                        goto error_2;
                }
 
-               /* Insertion-sort by server pointer */
+               /* Insertion-sort by UUID */
                for (j = 0; j < slist->nr_servers; j++)
-                       if (slist->servers[j].server >= server)
+                       if (memcmp(&slist->servers[j].server->uuid,
+                                  &server->uuid,
+                                  sizeof(server->uuid)) >= 0)
                                break;
                if (j < slist->nr_servers) {
                        if (slist->servers[j].server == server) {
index 65081ec3c36e572c5822d756b86abb52ed757f90..9e5d7966621c4abaa5cdc51f278a1a05a7e6afac 100644 (file)
@@ -590,7 +590,7 @@ static void afs_i_init_once(void *_vnode)
        memset(vnode, 0, sizeof(*vnode));
        inode_init_once(&vnode->vfs_inode);
        mutex_init(&vnode->io_lock);
-       mutex_init(&vnode->validate_lock);
+       init_rwsem(&vnode->validate_lock);
        spin_lock_init(&vnode->wb_lock);
        spin_lock_init(&vnode->lock);
        INIT_LIST_HEAD(&vnode->wb_keys);
@@ -688,7 +688,7 @@ static int afs_statfs(struct dentry *dentry, struct kstatfs *buf)
        if (afs_begin_vnode_operation(&fc, vnode, key)) {
                fc.flags |= AFS_FS_CURSOR_NO_VSLEEP;
                while (afs_select_fileserver(&fc)) {
-                       fc.cb_break = vnode->cb_break + vnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(vnode);
                        afs_fs_get_volume_status(&fc, &vs);
                }
 
index c164698dc30481156eb9738e0c3f1b91d5ab5108..8b39e6ebb40bc17905cf2eca24b1eacadf933584 100644 (file)
@@ -351,7 +351,7 @@ found_key:
        ret = -ERESTARTSYS;
        if (afs_begin_vnode_operation(&fc, vnode, wbk->key)) {
                while (afs_select_fileserver(&fc)) {
-                       fc.cb_break = vnode->cb_break + vnode->cb_s_break;
+                       fc.cb_break = afs_calc_vnode_cb_break(vnode);
                        afs_fs_store_data(&fc, mapping, first, last, offset, to);
                }
 
index f85040d73e3dcaa0214196ca0c242eadd0db475d..cf0e45b10121aa8323ca7d6a86a109d6f8675c08 100644 (file)
@@ -70,69 +70,104 @@ static __le32 ceph_flags_sys2wire(u32 flags)
  */
 
 /*
- * Calculate the length sum of direct io vectors that can
- * be combined into one page vector.
+ * How many pages to get in one call to iov_iter_get_pages().  This
+ * determines the size of the on-stack array used as a buffer.
  */
-static size_t dio_get_pagev_size(const struct iov_iter *it)
+#define ITER_GET_BVECS_PAGES   64
+
+static ssize_t __iter_get_bvecs(struct iov_iter *iter, size_t maxsize,
+                               struct bio_vec *bvecs)
 {
-    const struct iovec *iov = it->iov;
-    const struct iovec *iovend = iov + it->nr_segs;
-    size_t size;
-
-    size = iov->iov_len - it->iov_offset;
-    /*
-     * An iov can be page vectored when both the current tail
-     * and the next base are page aligned.
-     */
-    while (PAGE_ALIGNED((iov->iov_base + iov->iov_len)) &&
-           (++iov < iovend && PAGE_ALIGNED((iov->iov_base)))) {
-        size += iov->iov_len;
-    }
-    dout("dio_get_pagevlen len = %zu\n", size);
-    return size;
+       size_t size = 0;
+       int bvec_idx = 0;
+
+       if (maxsize > iov_iter_count(iter))
+               maxsize = iov_iter_count(iter);
+
+       while (size < maxsize) {
+               struct page *pages[ITER_GET_BVECS_PAGES];
+               ssize_t bytes;
+               size_t start;
+               int idx = 0;
+
+               bytes = iov_iter_get_pages(iter, pages, maxsize - size,
+                                          ITER_GET_BVECS_PAGES, &start);
+               if (bytes < 0)
+                       return size ?: bytes;
+
+               iov_iter_advance(iter, bytes);
+               size += bytes;
+
+               for ( ; bytes; idx++, bvec_idx++) {
+                       struct bio_vec bv = {
+                               .bv_page = pages[idx],
+                               .bv_len = min_t(int, bytes, PAGE_SIZE - start),
+                               .bv_offset = start,
+                       };
+
+                       bvecs[bvec_idx] = bv;
+                       bytes -= bv.bv_len;
+                       start = 0;
+               }
+       }
+
+       return size;
 }
 
 /*
- * Allocate a page vector based on (@it, @nbytes).
- * The return value is the tuple describing a page vector,
- * that is (@pages, @page_align, @num_pages).
+ * iov_iter_get_pages() only considers one iov_iter segment, no matter
+ * what maxsize or maxpages are given.  For ITER_BVEC that is a single
+ * page.
+ *
+ * Attempt to get up to @maxsize bytes worth of pages from @iter.
+ * Return the number of bytes in the created bio_vec array, or an error.
  */
-static struct page **
-dio_get_pages_alloc(const struct iov_iter *it, size_t nbytes,
-                   size_t *page_align, int *num_pages)
+static ssize_t iter_get_bvecs_alloc(struct iov_iter *iter, size_t maxsize,
+                                   struct bio_vec **bvecs, int *num_bvecs)
 {
-       struct iov_iter tmp_it = *it;
-       size_t align;
-       struct page **pages;
-       int ret = 0, idx, npages;
+       struct bio_vec *bv;
+       size_t orig_count = iov_iter_count(iter);
+       ssize_t bytes;
+       int npages;
 
-       align = (unsigned long)(it->iov->iov_base + it->iov_offset) &
-               (PAGE_SIZE - 1);
-       npages = calc_pages_for(align, nbytes);
-       pages = kvmalloc(sizeof(*pages) * npages, GFP_KERNEL);
-       if (!pages)
-               return ERR_PTR(-ENOMEM);
+       iov_iter_truncate(iter, maxsize);
+       npages = iov_iter_npages(iter, INT_MAX);
+       iov_iter_reexpand(iter, orig_count);
 
-       for (idx = 0; idx < npages; ) {
-               size_t start;
-               ret = iov_iter_get_pages(&tmp_it, pages + idx, nbytes,
-                                        npages - idx, &start);
-               if (ret < 0)
-                       goto fail;
+       /*
+        * __iter_get_bvecs() may populate only part of the array -- zero it
+        * out.
+        */
+       bv = kvmalloc_array(npages, sizeof(*bv), GFP_KERNEL | __GFP_ZERO);
+       if (!bv)
+               return -ENOMEM;
 
-               iov_iter_advance(&tmp_it, ret);
-               nbytes -= ret;
-               idx += (ret + start + PAGE_SIZE - 1) / PAGE_SIZE;
+       bytes = __iter_get_bvecs(iter, maxsize, bv);
+       if (bytes < 0) {
+               /*
+                * No pages were pinned -- just free the array.
+                */
+               kvfree(bv);
+               return bytes;
        }
 
-       BUG_ON(nbytes != 0);
-       *num_pages = npages;
-       *page_align = align;
-       dout("dio_get_pages_alloc: got %d pages align %zu\n", npages, align);
-       return pages;
-fail:
-       ceph_put_page_vector(pages, idx, false);
-       return ERR_PTR(ret);
+       *bvecs = bv;
+       *num_bvecs = npages;
+       return bytes;
+}
+
+static void put_bvecs(struct bio_vec *bvecs, int num_bvecs, bool should_dirty)
+{
+       int i;
+
+       for (i = 0; i < num_bvecs; i++) {
+               if (bvecs[i].bv_page) {
+                       if (should_dirty)
+                               set_page_dirty_lock(bvecs[i].bv_page);
+                       put_page(bvecs[i].bv_page);
+               }
+       }
+       kvfree(bvecs);
 }
 
 /*
@@ -746,11 +781,12 @@ static void ceph_aio_complete_req(struct ceph_osd_request *req)
        struct inode *inode = req->r_inode;
        struct ceph_aio_request *aio_req = req->r_priv;
        struct ceph_osd_data *osd_data = osd_req_op_extent_osd_data(req, 0);
-       int num_pages = calc_pages_for((u64)osd_data->alignment,
-                                      osd_data->length);
 
-       dout("ceph_aio_complete_req %p rc %d bytes %llu\n",
-            inode, rc, osd_data->length);
+       BUG_ON(osd_data->type != CEPH_OSD_DATA_TYPE_BVECS);
+       BUG_ON(!osd_data->num_bvecs);
+
+       dout("ceph_aio_complete_req %p rc %d bytes %u\n",
+            inode, rc, osd_data->bvec_pos.iter.bi_size);
 
        if (rc == -EOLDSNAPC) {
                struct ceph_aio_work *aio_work;
@@ -768,9 +804,10 @@ static void ceph_aio_complete_req(struct ceph_osd_request *req)
        } else if (!aio_req->write) {
                if (rc == -ENOENT)
                        rc = 0;
-               if (rc >= 0 && osd_data->length > rc) {
-                       int zoff = osd_data->alignment + rc;
-                       int zlen = osd_data->length - rc;
+               if (rc >= 0 && osd_data->bvec_pos.iter.bi_size > rc) {
+                       struct iov_iter i;
+                       int zlen = osd_data->bvec_pos.iter.bi_size - rc;
+
                        /*
                         * If read is satisfied by single OSD request,
                         * it can pass EOF. Otherwise read is within
@@ -785,13 +822,16 @@ static void ceph_aio_complete_req(struct ceph_osd_request *req)
                                aio_req->total_len = rc + zlen;
                        }
 
-                       if (zlen > 0)
-                               ceph_zero_page_vector_range(zoff, zlen,
-                                                           osd_data->pages);
+                       iov_iter_bvec(&i, ITER_BVEC, osd_data->bvec_pos.bvecs,
+                                     osd_data->num_bvecs,
+                                     osd_data->bvec_pos.iter.bi_size);
+                       iov_iter_advance(&i, rc);
+                       iov_iter_zero(zlen, &i);
                }
        }
 
-       ceph_put_page_vector(osd_data->pages, num_pages, aio_req->should_dirty);
+       put_bvecs(osd_data->bvec_pos.bvecs, osd_data->num_bvecs,
+                 aio_req->should_dirty);
        ceph_osdc_put_request(req);
 
        if (rc < 0)
@@ -879,7 +919,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
        struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        struct ceph_vino vino;
        struct ceph_osd_request *req;
-       struct page **pages;
+       struct bio_vec *bvecs;
        struct ceph_aio_request *aio_req = NULL;
        int num_pages = 0;
        int flags;
@@ -914,10 +954,14 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
        }
 
        while (iov_iter_count(iter) > 0) {
-               u64 size = dio_get_pagev_size(iter);
-               size_t start = 0;
+               u64 size = iov_iter_count(iter);
                ssize_t len;
 
+               if (write)
+                       size = min_t(u64, size, fsc->mount_options->wsize);
+               else
+                       size = min_t(u64, size, fsc->mount_options->rsize);
+
                vino = ceph_vino(inode);
                req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
                                            vino, pos, &size, 0,
@@ -933,18 +977,14 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
                        break;
                }
 
-               if (write)
-                       size = min_t(u64, size, fsc->mount_options->wsize);
-               else
-                       size = min_t(u64, size, fsc->mount_options->rsize);
-
-               len = size;
-               pages = dio_get_pages_alloc(iter, len, &start, &num_pages);
-               if (IS_ERR(pages)) {
+               len = iter_get_bvecs_alloc(iter, size, &bvecs, &num_pages);
+               if (len < 0) {
                        ceph_osdc_put_request(req);
-                       ret = PTR_ERR(pages);
+                       ret = len;
                        break;
                }
+               if (len != size)
+                       osd_req_op_extent_update(req, 0, len);
 
                /*
                 * To simplify error handling, allow AIO when IO within i_size
@@ -977,8 +1017,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
                        req->r_mtime = mtime;
                }
 
-               osd_req_op_extent_osd_data_pages(req, 0, pages, len, start,
-                                                false, false);
+               osd_req_op_extent_osd_data_bvecs(req, 0, bvecs, num_pages, len);
 
                if (aio_req) {
                        aio_req->total_len += len;
@@ -991,7 +1030,6 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
                        list_add_tail(&req->r_unsafe_item, &aio_req->osd_reqs);
 
                        pos += len;
-                       iov_iter_advance(iter, len);
                        continue;
                }
 
@@ -1004,25 +1042,26 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
                        if (ret == -ENOENT)
                                ret = 0;
                        if (ret >= 0 && ret < len && pos + ret < size) {
+                               struct iov_iter i;
                                int zlen = min_t(size_t, len - ret,
                                                 size - pos - ret);
-                               ceph_zero_page_vector_range(start + ret, zlen,
-                                                           pages);
+
+                               iov_iter_bvec(&i, ITER_BVEC, bvecs, num_pages,
+                                             len);
+                               iov_iter_advance(&i, ret);
+                               iov_iter_zero(zlen, &i);
                                ret += zlen;
                        }
                        if (ret >= 0)
                                len = ret;
                }
 
-               ceph_put_page_vector(pages, num_pages, should_dirty);
-
+               put_bvecs(bvecs, num_pages, should_dirty);
                ceph_osdc_put_request(req);
                if (ret < 0)
                        break;
 
                pos += len;
-               iov_iter_advance(iter, len);
-
                if (!write && pos >= size)
                        break;
 
index f715609b13f34a412de9f0486750a05cf73340b6..5a5a0158cc8f5085cda312d25c10b21e49bd8d1d 100644 (file)
@@ -1047,6 +1047,18 @@ out:
        return rc;
 }
 
+/*
+ * Directory operations under CIFS/SMB2/SMB3 are synchronous, so fsync()
+ * is a dummy operation.
+ */
+static int cifs_dir_fsync(struct file *file, loff_t start, loff_t end, int datasync)
+{
+       cifs_dbg(FYI, "Sync directory - name: %pD datasync: 0x%x\n",
+                file, datasync);
+
+       return 0;
+}
+
 static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off,
                                struct file *dst_file, loff_t destoff,
                                size_t len, unsigned int flags)
@@ -1181,6 +1193,7 @@ const struct file_operations cifs_dir_ops = {
        .copy_file_range = cifs_copy_file_range,
        .clone_file_range = cifs_clone_file_range,
        .llseek = generic_file_llseek,
+       .fsync = cifs_dir_fsync,
 };
 
 static void
index a5aa158d535a70a2247419152d01b64d553c1596..7a10a5d0731f078247d5636d3e00aae169b48345 100644 (file)
@@ -1977,14 +1977,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                goto cifs_parse_mount_err;
        }
 
-#ifdef CONFIG_CIFS_SMB_DIRECT
-       if (vol->rdma && vol->sign) {
-               cifs_dbg(VFS, "Currently SMB direct doesn't support signing."
-                       " This is being fixed\n");
-               goto cifs_parse_mount_err;
-       }
-#endif
-
 #ifndef CONFIG_KEYS
        /* Muliuser mounts require CONFIG_KEYS support */
        if (vol->multiuser) {
index b76b85881dcc668e87f99ee55b6bb4463f25510e..9c6d95ffca97de94d0763d7fde9b952f4a26fb3d 100644 (file)
@@ -589,9 +589,15 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
 
        SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
 
+       /*
+        * If ea_name is NULL (listxattr) and there are no EAs, return 0 as it's
+        * not an error. Otherwise, the specified ea_name was not found.
+        */
        if (!rc)
                rc = move_smb2_ea_to_cifs(ea_data, buf_size, smb2_data,
                                          SMB2_MAX_EA_BUF, ea_name);
+       else if (!ea_name && rc == -ENODATA)
+               rc = 0;
 
        kfree(smb2_data);
        return rc;
index 60db51bae0e3a88cec2147cf9d7e709bebb0c7fd..0f48741a0130d35286fec1e031b5eea45e367699 100644 (file)
@@ -730,19 +730,14 @@ neg_exit:
 
 int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
 {
-       int rc = 0;
-       struct validate_negotiate_info_req vneg_inbuf;
+       int rc;
+       struct validate_negotiate_info_req *pneg_inbuf;
        struct validate_negotiate_info_rsp *pneg_rsp = NULL;
        u32 rsplen;
        u32 inbuflen; /* max of 4 dialects */
 
        cifs_dbg(FYI, "validate negotiate\n");
 
-#ifdef CONFIG_CIFS_SMB_DIRECT
-       if (tcon->ses->server->rdma)
-               return 0;
-#endif
-
        /* In SMB3.11 preauth integrity supersedes validate negotiate */
        if (tcon->ses->server->dialect == SMB311_PROT_ID)
                return 0;
@@ -765,63 +760,69 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
        if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
                cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n");
 
-       vneg_inbuf.Capabilities =
+       pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS);
+       if (!pneg_inbuf)
+               return -ENOMEM;
+
+       pneg_inbuf->Capabilities =
                        cpu_to_le32(tcon->ses->server->vals->req_capabilities);
-       memcpy(vneg_inbuf.Guid, tcon->ses->server->client_guid,
+       memcpy(pneg_inbuf->Guid, tcon->ses->server->client_guid,
                                        SMB2_CLIENT_GUID_SIZE);
 
        if (tcon->ses->sign)
-               vneg_inbuf.SecurityMode =
+               pneg_inbuf->SecurityMode =
                        cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED);
        else if (global_secflags & CIFSSEC_MAY_SIGN)
-               vneg_inbuf.SecurityMode =
+               pneg_inbuf->SecurityMode =
                        cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED);
        else
-               vneg_inbuf.SecurityMode = 0;
+               pneg_inbuf->SecurityMode = 0;
 
 
        if (strcmp(tcon->ses->server->vals->version_string,
                SMB3ANY_VERSION_STRING) == 0) {
-               vneg_inbuf.Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
-               vneg_inbuf.Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
-               vneg_inbuf.DialectCount = cpu_to_le16(2);
+               pneg_inbuf->Dialects[0] = cpu_to_le16(SMB30_PROT_ID);
+               pneg_inbuf->Dialects[1] = cpu_to_le16(SMB302_PROT_ID);
+               pneg_inbuf->DialectCount = cpu_to_le16(2);
                /* structure is big enough for 3 dialects, sending only 2 */
-               inbuflen = sizeof(struct validate_negotiate_info_req) - 2;
+               inbuflen = sizeof(*pneg_inbuf) -
+                               sizeof(pneg_inbuf->Dialects[0]);
        } else if (strcmp(tcon->ses->server->vals->version_string,
                SMBDEFAULT_VERSION_STRING) == 0) {
-               vneg_inbuf.Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
-               vneg_inbuf.Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
-               vneg_inbuf.Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
-               vneg_inbuf.DialectCount = cpu_to_le16(3);
+               pneg_inbuf->Dialects[0] = cpu_to_le16(SMB21_PROT_ID);
+               pneg_inbuf->Dialects[1] = cpu_to_le16(SMB30_PROT_ID);
+               pneg_inbuf->Dialects[2] = cpu_to_le16(SMB302_PROT_ID);
+               pneg_inbuf->DialectCount = cpu_to_le16(3);
                /* structure is big enough for 3 dialects */
-               inbuflen = sizeof(struct validate_negotiate_info_req);
+               inbuflen = sizeof(*pneg_inbuf);
        } else {
                /* otherwise specific dialect was requested */
-               vneg_inbuf.Dialects[0] =
+               pneg_inbuf->Dialects[0] =
                        cpu_to_le16(tcon->ses->server->vals->protocol_id);
-               vneg_inbuf.DialectCount = cpu_to_le16(1);
+               pneg_inbuf->DialectCount = cpu_to_le16(1);
                /* structure is big enough for 3 dialects, sending only 1 */
-               inbuflen = sizeof(struct validate_negotiate_info_req) - 4;
+               inbuflen = sizeof(*pneg_inbuf) -
+                               sizeof(pneg_inbuf->Dialects[0]) * 2;
        }
 
        rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
                FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */,
-               (char *)&vneg_inbuf, sizeof(struct validate_negotiate_info_req),
-               (char **)&pneg_rsp, &rsplen);
+               (char *)pneg_inbuf, inbuflen, (char **)&pneg_rsp, &rsplen);
 
        if (rc != 0) {
                cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", rc);
-               return -EIO;
+               rc = -EIO;
+               goto out_free_inbuf;
        }
 
-       if (rsplen != sizeof(struct validate_negotiate_info_rsp)) {
+       rc = -EIO;
+       if (rsplen != sizeof(*pneg_rsp)) {
                cifs_dbg(VFS, "invalid protocol negotiate response size: %d\n",
                         rsplen);
 
                /* relax check since Mac returns max bufsize allowed on ioctl */
-               if ((rsplen > CIFSMaxBufSize)
-                    || (rsplen < sizeof(struct validate_negotiate_info_rsp)))
-                       goto err_rsp_free;
+               if (rsplen > CIFSMaxBufSize || rsplen < sizeof(*pneg_rsp))
+                       goto out_free_rsp;
        }
 
        /* check validate negotiate info response matches what we got earlier */
@@ -838,15 +839,17 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
                goto vneg_out;
 
        /* validate negotiate successful */
+       rc = 0;
        cifs_dbg(FYI, "validate negotiate info successful\n");
-       kfree(pneg_rsp);
-       return 0;
+       goto out_free_rsp;
 
 vneg_out:
        cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n");
-err_rsp_free:
+out_free_rsp:
        kfree(pneg_rsp);
-       return -EIO;
+out_free_inbuf:
+       kfree(pneg_inbuf);
+       return rc;
 }
 
 enum securityEnum
index 513c357c734b0d838f331bebc71b1deeb9f8f57f..a6c0f54c48c30f25315865f8080d412fb428c00a 100644 (file)
@@ -588,6 +588,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
        return 0;
 
 out_put_hidden_dir:
+       cancel_delayed_work_sync(&sbi->sync_work);
        iput(sbi->hidden_dir);
 out_put_root:
        dput(sb->s_root);
index 01c6b3894406e0b9c51ede0086ca7633dd1f5044..7869622af22a2cd2ea0dfd164b1a5b3fba31cd25 100644 (file)
@@ -4250,10 +4250,11 @@ out:
 static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir,
                         struct dentry *new_dentry, bool preserve)
 {
-       int error;
+       int error, had_lock;
        struct inode *inode = d_inode(old_dentry);
        struct buffer_head *old_bh = NULL;
        struct inode *new_orphan_inode = NULL;
+       struct ocfs2_lock_holder oh;
 
        if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb)))
                return -EOPNOTSUPP;
@@ -4295,6 +4296,14 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir,
                goto out;
        }
 
+       had_lock = ocfs2_inode_lock_tracker(new_orphan_inode, NULL, 1,
+                                           &oh);
+       if (had_lock < 0) {
+               error = had_lock;
+               mlog_errno(error);
+               goto out;
+       }
+
        /* If the security isn't preserved, we need to re-initialize them. */
        if (!preserve) {
                error = ocfs2_init_security_and_acl(dir, new_orphan_inode,
@@ -4302,14 +4311,15 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir,
                if (error)
                        mlog_errno(error);
        }
-out:
        if (!error) {
                error = ocfs2_mv_orphaned_inode_to_new(dir, new_orphan_inode,
                                                       new_dentry);
                if (error)
                        mlog_errno(error);
        }
+       ocfs2_inode_unlock_tracker(new_orphan_inode, 1, &oh, had_lock);
 
+out:
        if (new_orphan_inode) {
                /*
                 * We need to open_unlock the inode no matter whether we
index 1b2ede6abcdfc97f1ab87244a18e0cb4c9035e5f..1a76d751cf3c24c2f4271b1a855ff5d7bca9ee85 100644 (file)
@@ -261,7 +261,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
         * Inherently racy -- command line shares address space
         * with code and data.
         */
-       rv = access_remote_vm(mm, arg_end - 1, &c, 1, 0);
+       rv = access_remote_vm(mm, arg_end - 1, &c, 1, FOLL_ANON);
        if (rv <= 0)
                goto out_free_page;
 
@@ -279,7 +279,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
                        int nr_read;
 
                        _count = min3(count, len, PAGE_SIZE);
-                       nr_read = access_remote_vm(mm, p, page, _count, 0);
+                       nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
                        if (nr_read < 0)
                                rv = nr_read;
                        if (nr_read <= 0)
@@ -325,7 +325,7 @@ static ssize_t proc_pid_cmdline_read(struct file *file, char __user *buf,
                                bool final;
 
                                _count = min3(count, len, PAGE_SIZE);
-                               nr_read = access_remote_vm(mm, p, page, _count, 0);
+                               nr_read = access_remote_vm(mm, p, page, _count, FOLL_ANON);
                                if (nr_read < 0)
                                        rv = nr_read;
                                if (nr_read <= 0)
@@ -946,7 +946,7 @@ static ssize_t environ_read(struct file *file, char __user *buf,
                max_len = min_t(size_t, PAGE_SIZE, count);
                this_len = min(max_len, this_len);
 
-               retval = access_remote_vm(mm, (env_start + src), page, this_len, 0);
+               retval = access_remote_vm(mm, (env_start + src), page, this_len, FOLL_ANON);
 
                if (retval <= 0) {
                        ret = retval;
index d1e82761de813abb95af0faac99194dba5821538..e64ecb9f272090bf6b23772a0d36e56b63b8106a 100644 (file)
@@ -209,25 +209,34 @@ kclist_add_private(unsigned long pfn, unsigned long nr_pages, void *arg)
 {
        struct list_head *head = (struct list_head *)arg;
        struct kcore_list *ent;
+       struct page *p;
+
+       if (!pfn_valid(pfn))
+               return 1;
+
+       p = pfn_to_page(pfn);
+       if (!memmap_valid_within(pfn, p, page_zone(p)))
+               return 1;
 
        ent = kmalloc(sizeof(*ent), GFP_KERNEL);
        if (!ent)
                return -ENOMEM;
-       ent->addr = (unsigned long)__va((pfn << PAGE_SHIFT));
+       ent->addr = (unsigned long)page_to_virt(p);
        ent->size = nr_pages << PAGE_SHIFT;
 
-       /* Sanity check: Can happen in 32bit arch...maybe */
-       if (ent->addr < (unsigned long) __va(0))
+       if (!virt_addr_valid(ent->addr))
                goto free_out;
 
        /* cut not-mapped area. ....from ppc-32 code. */
        if (ULONG_MAX - ent->addr < ent->size)
                ent->size = ULONG_MAX - ent->addr;
 
-       /* cut when vmalloc() area is higher than direct-map area */
-       if (VMALLOC_START > (unsigned long)__va(0)) {
-               if (ent->addr > VMALLOC_START)
-                       goto free_out;
+       /*
+        * We've already checked virt_addr_valid so we know this address
+        * is a valid pointer, therefore we can check against it to determine
+        * if we need to trim
+        */
+       if (VMALLOC_START > ent->addr) {
                if (VMALLOC_START - ent->addr < ent->size)
                        ent->size = VMALLOC_START - ent->addr;
        }
index 24f03941ada8e2d07803765c5770d5beb9e1a7a6..e7efe12a81bdfae67d4f5709e34b14831bd594ac 100644 (file)
@@ -131,6 +131,7 @@ struct vgic_irq {
                u32 mpidr;                      /* GICv3 target VCPU */
        };
        u8 source;                      /* GICv2 SGIs only */
+       u8 active_source;               /* GICv2 SGIs only */
        u8 priority;
        enum vgic_irq_config config;    /* Level or edge */
 
index d3339dd48b1ab4224d512a4f3c47b85b48da51d6..b324e01ccf2da6a3a06142d7e1ae960ccb1b1e3e 100644 (file)
@@ -25,6 +25,7 @@
 #define PHY_ID_BCM54612E               0x03625e60
 #define PHY_ID_BCM54616S               0x03625d10
 #define PHY_ID_BCM57780                        0x03625d90
+#define PHY_ID_BCM89610                        0x03625cd0
 
 #define PHY_ID_BCM7250                 0xae025280
 #define PHY_ID_BCM7260                 0xae025190
index 528ccc943cee0a5da4bc95e5d200a8591debe836..96bb3228598927c0cb089b5f4fa88da445cd1b26 100644 (file)
@@ -77,7 +77,10 @@ struct ceph_osd_data {
                        u32                     bio_length;
                };
 #endif /* CONFIG_BLOCK */
-               struct ceph_bvec_iter   bvec_pos;
+               struct {
+                       struct ceph_bvec_iter   bvec_pos;
+                       u32                     num_bvecs;
+               };
        };
 };
 
@@ -412,6 +415,10 @@ void osd_req_op_extent_osd_data_bio(struct ceph_osd_request *osd_req,
                                    struct ceph_bio_iter *bio_pos,
                                    u32 bio_length);
 #endif /* CONFIG_BLOCK */
+void osd_req_op_extent_osd_data_bvecs(struct ceph_osd_request *osd_req,
+                                     unsigned int which,
+                                     struct bio_vec *bvecs, u32 num_bvecs,
+                                     u32 bytes);
 void osd_req_op_extent_osd_data_bvec_pos(struct ceph_osd_request *osd_req,
                                         unsigned int which,
                                         struct ceph_bvec_iter *bvec_pos);
@@ -426,7 +433,8 @@ extern void osd_req_op_cls_request_data_pages(struct ceph_osd_request *,
                                        bool own_pages);
 void osd_req_op_cls_request_data_bvecs(struct ceph_osd_request *osd_req,
                                       unsigned int which,
-                                      struct bio_vec *bvecs, u32 bytes);
+                                      struct bio_vec *bvecs, u32 num_bvecs,
+                                      u32 bytes);
 extern void osd_req_op_cls_response_data_pages(struct ceph_osd_request *,
                                        unsigned int which,
                                        struct page **pages, u64 length,
index c1961761311dbfd5968d6ed64ea91ca3c7d25b0e..2803264c512f8f6bf80dffc462c4a7ab079ce5f3 100644 (file)
@@ -62,6 +62,7 @@ void *kthread_probe_data(struct task_struct *k);
 int kthread_park(struct task_struct *k);
 void kthread_unpark(struct task_struct *k);
 void kthread_parkme(void);
+void kthread_park_complete(struct task_struct *k);
 
 int kthreadd(void *unused);
 extern struct task_struct *kthreadd_task;
index 6930c63126c78a9ef665b5b5653a60a8773b4d4c..6d6e79c59e68fa7fd5387f48814341082d6b8526 100644 (file)
@@ -1045,13 +1045,7 @@ static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq)
 
 #ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
 
-#ifdef CONFIG_S390
-#define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that...
-#elif defined(CONFIG_ARM64)
-#define KVM_MAX_IRQ_ROUTES 4096
-#else
-#define KVM_MAX_IRQ_ROUTES 1024
-#endif
+#define KVM_MAX_IRQ_ROUTES 4096 /* might need extension/rework in the future */
 
 bool kvm_arch_can_set_irq_routing(struct kvm *kvm);
 int kvm_set_irq_routing(struct kvm *kvm,
index 1ac1f06a4be6b22faf3883c760515a042a6d347e..c6fa9a255dbf63a9ec938c5c6be3f926917bd502 100644 (file)
@@ -2466,6 +2466,13 @@ static inline vm_fault_t vmf_insert_pfn(struct vm_area_struct *vma,
        return VM_FAULT_NOPAGE;
 }
 
+static inline vm_fault_t vmf_error(int err)
+{
+       if (err == -ENOMEM)
+               return VM_FAULT_OOM;
+       return VM_FAULT_SIGBUS;
+}
+
 struct page *follow_page_mask(struct vm_area_struct *vma,
                              unsigned long address, unsigned int foll_flags,
                              unsigned int *page_mask);
@@ -2493,6 +2500,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma,
 #define FOLL_MLOCK     0x1000  /* lock present pages */
 #define FOLL_REMOTE    0x2000  /* we are working on non-current tsk/mm */
 #define FOLL_COW       0x4000  /* internal GUP flag */
+#define FOLL_ANON      0x8000  /* don't do file mappings */
 
 static inline int vm_fault_to_errno(int vm_fault, int foll_flags)
 {
index b5b43f94f311626ee364157515c4342aba976e6f..01b990e4b228a90ef26bc302d8b8476293a81869 100644 (file)
@@ -312,7 +312,7 @@ void map_destroy(struct mtd_info *mtd);
 ({                                                                     \
        int i, ret = 1;                                                 \
        for (i = 0; i < map_words(map); i++) {                          \
-               if (((val1).x[i] & (val2).x[i]) != (val2).x[i]) {       \
+               if (((val1).x[i] & (val2).x[i]) != (val3).x[i]) {       \
                        ret = 0;                                        \
                        break;                                          \
                }                                                       \
index 5dad59b312440a9c6cf44160276f162a82130738..17c919436f48726450069ca1e589ccd3fc48e712 100644 (file)
@@ -867,12 +867,18 @@ struct nand_op_instr {
  * tBERS (during an erase) which all of them are u64 values that cannot be
  * divided by usual kernel macros and must be handled with the special
  * DIV_ROUND_UP_ULL() macro.
+ *
+ * Cast to type of dividend is needed here to guarantee that the result won't
+ * be an unsigned long long when the dividend is an unsigned long (or smaller),
+ * which is what the compiler does when it sees ternary operator with 2
+ * different return types (picks the largest type to make sure there's no
+ * loss).
  */
-#define __DIVIDE(dividend, divisor) ({                                 \
-       sizeof(dividend) == sizeof(u32) ?                               \
-               DIV_ROUND_UP(dividend, divisor) :                       \
-               DIV_ROUND_UP_ULL(dividend, divisor);                    \
-               })
+#define __DIVIDE(dividend, divisor) ({                                         \
+       (__typeof__(dividend))(sizeof(dividend) <= sizeof(unsigned long) ?      \
+                              DIV_ROUND_UP(dividend, divisor) :                \
+                              DIV_ROUND_UP_ULL(dividend, divisor));            \
+       })
 #define PSEC_TO_NSEC(x) __DIVIDE(x, 1000)
 #define PSEC_TO_MSEC(x) __DIVIDE(x, 1000000000)
 
index 5bad038ac012e6e3047fd6a63a625c6814966d51..6adac113e96d29b5059ed65ac0522237c9b94388 100644 (file)
@@ -95,6 +95,8 @@ static inline int check_stable_address_space(struct mm_struct *mm)
        return 0;
 }
 
+void __oom_reap_task_mm(struct mm_struct *mm);
+
 extern unsigned long oom_badness(struct task_struct *p,
                struct mem_cgroup *memcg, const nodemask_t *nodemask,
                unsigned long totalpages);
index 6bfd2b581f75a464e13d3d749ebe5d639a32551f..af8a61be2d8d500206687249f1e428c23dceb5fe 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <linux/compiler.h>
 #include <linux/rbtree.h>
+#include <linux/rcupdate.h>
 
 /*
  * Please note - only struct rb_augment_callbacks and the prototypes for
index ece43e882b56df3c119b97d26e69f388cc348499..7d012faa509a44c775b8835d409fb1ac3933d3c8 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <linux/rbtree.h>
 #include <linux/seqlock.h>
+#include <linux/rcupdate.h>
 
 struct latch_tree_node {
        struct rb_node node[2];
index b3d697f3b5731b4c45986fb10e8afb2d00ecf6e4..c2413703f45dcf005c7601b1e8c8c24c51d2a844 100644 (file)
@@ -112,17 +112,36 @@ struct task_group;
 
 #ifdef CONFIG_DEBUG_ATOMIC_SLEEP
 
+/*
+ * Special states are those that do not use the normal wait-loop pattern. See
+ * the comment with set_special_state().
+ */
+#define is_special_task_state(state)                           \
+       ((state) & (__TASK_STOPPED | __TASK_TRACED | TASK_DEAD))
+
 #define __set_current_state(state_value)                       \
        do {                                                    \
+               WARN_ON_ONCE(is_special_task_state(state_value));\
                current->task_state_change = _THIS_IP_;         \
                current->state = (state_value);                 \
        } while (0)
+
 #define set_current_state(state_value)                         \
        do {                                                    \
+               WARN_ON_ONCE(is_special_task_state(state_value));\
                current->task_state_change = _THIS_IP_;         \
                smp_store_mb(current->state, (state_value));    \
        } while (0)
 
+#define set_special_state(state_value)                                 \
+       do {                                                            \
+               unsigned long flags; /* may shadow */                   \
+               WARN_ON_ONCE(!is_special_task_state(state_value));      \
+               raw_spin_lock_irqsave(&current->pi_lock, flags);        \
+               current->task_state_change = _THIS_IP_;                 \
+               current->state = (state_value);                         \
+               raw_spin_unlock_irqrestore(&current->pi_lock, flags);   \
+       } while (0)
 #else
 /*
  * set_current_state() includes a barrier so that the write of current->state
@@ -144,8 +163,8 @@ struct task_group;
  *
  * The above is typically ordered against the wakeup, which does:
  *
- *     need_sleep = false;
- *     wake_up_state(p, TASK_UNINTERRUPTIBLE);
+ *   need_sleep = false;
+ *   wake_up_state(p, TASK_UNINTERRUPTIBLE);
  *
  * Where wake_up_state() (and all other wakeup primitives) imply enough
  * barriers to order the store of the variable against wakeup.
@@ -154,12 +173,33 @@ struct task_group;
  * once it observes the TASK_UNINTERRUPTIBLE store the waking CPU can issue a
  * TASK_RUNNING store which can collide with __set_current_state(TASK_RUNNING).
  *
- * This is obviously fine, since they both store the exact same value.
+ * However, with slightly different timing the wakeup TASK_RUNNING store can
+ * also collide with the TASK_UNINTERRUPTIBLE store. Loosing that store is not
+ * a problem either because that will result in one extra go around the loop
+ * and our @cond test will save the day.
  *
  * Also see the comments of try_to_wake_up().
  */
-#define __set_current_state(state_value) do { current->state = (state_value); } while (0)
-#define set_current_state(state_value)  smp_store_mb(current->state, (state_value))
+#define __set_current_state(state_value)                               \
+       current->state = (state_value)
+
+#define set_current_state(state_value)                                 \
+       smp_store_mb(current->state, (state_value))
+
+/*
+ * set_special_state() should be used for those states when the blocking task
+ * can not use the regular condition based wait-loop. In that case we must
+ * serialize against wakeups such that any possible in-flight TASK_RUNNING stores
+ * will not collide with our state change.
+ */
+#define set_special_state(state_value)                                 \
+       do {                                                            \
+               unsigned long flags; /* may shadow */                   \
+               raw_spin_lock_irqsave(&current->pi_lock, flags);        \
+               current->state = (state_value);                         \
+               raw_spin_unlock_irqrestore(&current->pi_lock, flags);   \
+       } while (0)
+
 #endif
 
 /* Task command name length: */
index a7ce74c74e494ae05ba687bf9ad0497a690faed2..113d1ad1ced76e0c138c9dd05d1420ff28c71616 100644 (file)
@@ -280,7 +280,7 @@ static inline void kernel_signal_stop(void)
 {
        spin_lock_irq(&current->sighand->siglock);
        if (current->jobctl & JOBCTL_STOP_DEQUEUED)
-               __set_current_state(TASK_STOPPED);
+               set_special_state(TASK_STOPPED);
        spin_unlock_irq(&current->sighand->siglock);
 
        schedule();
index f801fc940b298cb3180584b039a9605d3ee9f23e..b522351588360107d8eeb25c7ff4670f78b5cbd6 100644 (file)
@@ -198,6 +198,7 @@ struct bonding {
        struct   slave __rcu *primary_slave;
        struct   bond_up_slave __rcu *slave_arr; /* Array of usable slaves */
        bool     force_primary;
+       u32      nest_level;
        s32      slave_cnt; /* never change this value outside the attach/detach wrappers */
        int     (*recv_probe)(const struct sk_buff *, struct bonding *,
                              struct slave *);
index 9a074776f70b6606496bc921dcaaea069e7f8696..d1fcf2442a423bd7de7649c869647484aeeeb92b 100644 (file)
@@ -251,7 +251,7 @@ extern struct flow_dissector flow_keys_buf_dissector;
  * This structure is used to hold a digest of the full flow keys. This is a
  * larger "hash" of a flow to allow definitively matching specific flows where
  * the 32 bit skb->hash is not large enough. The size is limited to 16 bytes so
- * that it can by used in CB of skb (see sch_choke for an example).
+ * that it can be used in CB of skb (see sch_choke for an example).
  */
 #define FLOW_KEYS_DIGEST_LEN   16
 struct flow_keys_digest {
index d2279b2d61aa98ca4bee0f338f00dbca13f6b2cf..b2f3a0c018e78c43cebb3a70cf2e357fdd6ea355 100644 (file)
@@ -2080,7 +2080,7 @@ struct ieee80211_txq {
  *     virtual interface might not be given air time for the transmission of
  *     the frame, as it is not synced with the AP/P2P GO yet, and thus the
  *     deauthentication frame might not be transmitted.
- >
+ *
  * @IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP: The driver (or firmware) doesn't
  *     support QoS NDP for AP probing - that's most likely a driver bug.
  *
index a872379b69da4e8e03a2b07d98f0ef4ce45cdcf7..45e75c36b738bf647584db536c22eddd6dd439cc 100644 (file)
@@ -375,6 +375,7 @@ struct xfrm_input_afinfo {
 int xfrm_input_register_afinfo(const struct xfrm_input_afinfo *afinfo);
 int xfrm_input_unregister_afinfo(const struct xfrm_input_afinfo *afinfo);
 
+void xfrm_flush_gc(void);
 void xfrm_state_delete_tunnel(struct xfrm_state *x);
 
 struct xfrm_type {
index f0820554caa9d0630410dc12fbd06bae76f4eeac..d0a341bc45404b06c08f434d26030dd8be3138db 100644 (file)
@@ -575,6 +575,48 @@ TRACE_EVENT(afs_protocol_error,
                      __entry->call, __entry->error, __entry->where)
            );
 
+TRACE_EVENT(afs_cm_no_server,
+           TP_PROTO(struct afs_call *call, struct sockaddr_rxrpc *srx),
+
+           TP_ARGS(call, srx),
+
+           TP_STRUCT__entry(
+                   __field(unsigned int,                       call    )
+                   __field(unsigned int,                       op_id   )
+                   __field_struct(struct sockaddr_rxrpc,       srx     )
+                            ),
+
+           TP_fast_assign(
+                   __entry->call = call->debug_id;
+                   __entry->op_id = call->operation_ID;
+                   memcpy(&__entry->srx, srx, sizeof(__entry->srx));
+                          ),
+
+           TP_printk("c=%08x op=%u %pISpc",
+                     __entry->call, __entry->op_id, &__entry->srx.transport)
+           );
+
+TRACE_EVENT(afs_cm_no_server_u,
+           TP_PROTO(struct afs_call *call, const uuid_t *uuid),
+
+           TP_ARGS(call, uuid),
+
+           TP_STRUCT__entry(
+                   __field(unsigned int,                       call    )
+                   __field(unsigned int,                       op_id   )
+                   __field_struct(uuid_t,                      uuid    )
+                            ),
+
+           TP_fast_assign(
+                   __entry->call = call->debug_id;
+                   __entry->op_id = call->operation_ID;
+                   memcpy(&__entry->uuid, uuid, sizeof(__entry->uuid));
+                          ),
+
+           TP_printk("c=%08x op=%u %pU",
+                     __entry->call, __entry->op_id, &__entry->uuid)
+           );
+
 #endif /* _TRACE_AFS_H */
 
 /* This part must be outside protection */
index 9e96c2fe2793e5286d1cb8882cf87da5075f6f0d..077e664ac9a20986eebf07fc829339738882f8a9 100644 (file)
@@ -15,6 +15,7 @@
 #define _TRACE_RXRPC_H
 
 #include <linux/tracepoint.h>
+#include <linux/errqueue.h>
 
 /*
  * Define enums for tracing information.
@@ -210,6 +211,20 @@ enum rxrpc_congest_change {
        rxrpc_cong_saw_nack,
 };
 
+enum rxrpc_tx_fail_trace {
+       rxrpc_tx_fail_call_abort,
+       rxrpc_tx_fail_call_ack,
+       rxrpc_tx_fail_call_data_frag,
+       rxrpc_tx_fail_call_data_nofrag,
+       rxrpc_tx_fail_call_final_resend,
+       rxrpc_tx_fail_conn_abort,
+       rxrpc_tx_fail_conn_challenge,
+       rxrpc_tx_fail_conn_response,
+       rxrpc_tx_fail_reject,
+       rxrpc_tx_fail_version_keepalive,
+       rxrpc_tx_fail_version_reply,
+};
+
 #endif /* end __RXRPC_DECLARE_TRACE_ENUMS_ONCE_ONLY */
 
 /*
@@ -437,6 +452,19 @@ enum rxrpc_congest_change {
        EM(RXRPC_CALL_LOCAL_ERROR,              "LocalError") \
        E_(RXRPC_CALL_NETWORK_ERROR,            "NetError")
 
+#define rxrpc_tx_fail_traces \
+       EM(rxrpc_tx_fail_call_abort,            "CallAbort") \
+       EM(rxrpc_tx_fail_call_ack,              "CallAck") \
+       EM(rxrpc_tx_fail_call_data_frag,        "CallDataFrag") \
+       EM(rxrpc_tx_fail_call_data_nofrag,      "CallDataNofrag") \
+       EM(rxrpc_tx_fail_call_final_resend,     "CallFinalResend") \
+       EM(rxrpc_tx_fail_conn_abort,            "ConnAbort") \
+       EM(rxrpc_tx_fail_conn_challenge,        "ConnChall") \
+       EM(rxrpc_tx_fail_conn_response,         "ConnResp") \
+       EM(rxrpc_tx_fail_reject,                "Reject") \
+       EM(rxrpc_tx_fail_version_keepalive,     "VerKeepalive") \
+       E_(rxrpc_tx_fail_version_reply,         "VerReply")
+
 /*
  * Export enum symbols via userspace.
  */
@@ -460,6 +488,7 @@ rxrpc_propose_ack_traces;
 rxrpc_propose_ack_outcomes;
 rxrpc_congest_modes;
 rxrpc_congest_changes;
+rxrpc_tx_fail_traces;
 
 /*
  * Now redefine the EM() and E_() macros to map the enums to the strings that
@@ -1374,6 +1403,62 @@ TRACE_EVENT(rxrpc_resend,
                      __entry->anno)
            );
 
+TRACE_EVENT(rxrpc_rx_icmp,
+           TP_PROTO(struct rxrpc_peer *peer, struct sock_extended_err *ee,
+                    struct sockaddr_rxrpc *srx),
+
+           TP_ARGS(peer, ee, srx),
+
+           TP_STRUCT__entry(
+                   __field(unsigned int,                       peer    )
+                   __field_struct(struct sock_extended_err,    ee      )
+                   __field_struct(struct sockaddr_rxrpc,       srx     )
+                            ),
+
+           TP_fast_assign(
+                   __entry->peer = peer->debug_id;
+                   memcpy(&__entry->ee, ee, sizeof(__entry->ee));
+                   memcpy(&__entry->srx, srx, sizeof(__entry->srx));
+                          ),
+
+           TP_printk("P=%08x o=%u t=%u c=%u i=%u d=%u e=%d %pISp",
+                     __entry->peer,
+                     __entry->ee.ee_origin,
+                     __entry->ee.ee_type,
+                     __entry->ee.ee_code,
+                     __entry->ee.ee_info,
+                     __entry->ee.ee_data,
+                     __entry->ee.ee_errno,
+                     &__entry->srx.transport)
+           );
+
+TRACE_EVENT(rxrpc_tx_fail,
+           TP_PROTO(unsigned int debug_id, rxrpc_serial_t serial, int ret,
+                    enum rxrpc_tx_fail_trace what),
+
+           TP_ARGS(debug_id, serial, ret, what),
+
+           TP_STRUCT__entry(
+                   __field(unsigned int,               debug_id        )
+                   __field(rxrpc_serial_t,             serial          )
+                   __field(int,                        ret             )
+                   __field(enum rxrpc_tx_fail_trace,   what            )
+                            ),
+
+           TP_fast_assign(
+                   __entry->debug_id = debug_id;
+                   __entry->serial = serial;
+                   __entry->ret = ret;
+                   __entry->what = what;
+                          ),
+
+           TP_printk("c=%08x r=%x ret=%d %s",
+                     __entry->debug_id,
+                     __entry->serial,
+                     __entry->ret,
+                     __print_symbolic(__entry->what, rxrpc_tx_fail_traces))
+           );
+
 #endif /* _TRACE_RXRPC_H */
 
 /* This part must be outside protection */
index 335d87242439db1b64d2ed7ad0c167844d0c5dad..bbb08a3ef5ccce100d2551580b35f6b42fa1fa9e 100644 (file)
@@ -224,6 +224,8 @@ TRACE_EVENT(rpc_stats_latency,
        TP_ARGS(task, backlog, rtt, execute),
 
        TP_STRUCT__entry(
+               __field(unsigned int, task_id)
+               __field(unsigned int, client_id)
                __field(u32, xid)
                __field(int, version)
                __string(progname, task->tk_client->cl_program->name)
@@ -231,13 +233,11 @@ TRACE_EVENT(rpc_stats_latency,
                __field(unsigned long, backlog)
                __field(unsigned long, rtt)
                __field(unsigned long, execute)
-               __string(addr,
-                        task->tk_xprt->address_strings[RPC_DISPLAY_ADDR])
-               __string(port,
-                        task->tk_xprt->address_strings[RPC_DISPLAY_PORT])
        ),
 
        TP_fast_assign(
+               __entry->client_id = task->tk_client->cl_clid;
+               __entry->task_id = task->tk_pid;
                __entry->xid = be32_to_cpu(task->tk_rqstp->rq_xid);
                __entry->version = task->tk_client->cl_vers;
                __assign_str(progname, task->tk_client->cl_program->name)
@@ -245,14 +245,10 @@ TRACE_EVENT(rpc_stats_latency,
                __entry->backlog = ktime_to_us(backlog);
                __entry->rtt = ktime_to_us(rtt);
                __entry->execute = ktime_to_us(execute);
-               __assign_str(addr,
-                            task->tk_xprt->address_strings[RPC_DISPLAY_ADDR]);
-               __assign_str(port,
-                            task->tk_xprt->address_strings[RPC_DISPLAY_PORT]);
        ),
 
-       TP_printk("peer=[%s]:%s xid=0x%08x %sv%d %s backlog=%lu rtt=%lu execute=%lu",
-               __get_str(addr), __get_str(port), __entry->xid,
+       TP_printk("task:%u@%d xid=0x%08x %sv%d %s backlog=%lu rtt=%lu execute=%lu",
+               __entry->task_id, __entry->client_id, __entry->xid,
                __get_str(progname), __entry->version, __get_str(procname),
                __entry->backlog, __entry->rtt, __entry->execute)
 );
index 7dd8f34c37dfea26f8ec460d3937a46c8f109f4d..fdcf88bcf0ea3dec3df105aa7e7d40fe2aaaaf0c 100644 (file)
@@ -352,22 +352,6 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd,
 DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin);
 DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin);
 
-TRACE_EVENT(xen_mmu_flush_tlb_all,
-           TP_PROTO(int x),
-           TP_ARGS(x),
-           TP_STRUCT__entry(__array(char, x, 0)),
-           TP_fast_assign((void)x),
-           TP_printk("%s", "")
-       );
-
-TRACE_EVENT(xen_mmu_flush_tlb,
-           TP_PROTO(int x),
-           TP_ARGS(x),
-           TP_STRUCT__entry(__array(char, x, 0)),
-           TP_fast_assign((void)x),
-           TP_printk("%s", "")
-       );
-
 TRACE_EVENT(xen_mmu_flush_tlb_one_user,
            TP_PROTO(unsigned long addr),
            TP_ARGS(addr),
index 15daf5e2638d9bbcb6ad8b5d104b520dc81678fe..9c3630146cec0f739a0c3cea6ec98e95e69e44bb 100644 (file)
@@ -2698,6 +2698,8 @@ enum nl80211_attrs {
 #define NL80211_ATTR_KEYS NL80211_ATTR_KEYS
 #define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS
 
+#define NL80211_WIPHY_NAME_MAXLEN              128
+
 #define NL80211_MAX_SUPP_RATES                 32
 #define NL80211_MAX_SUPP_HT_RATES              77
 #define NL80211_MAX_SUPP_REG_RULES             64
index b795aa341a3a30528f878db01f79907a2ac3e5b1..fd37315835b4ae18235af293cc689b6cdd055850 100644 (file)
@@ -423,7 +423,7 @@ static noinline void __ref rest_init(void)
 
        /*
         * Enable might_sleep() and smp_processor_id() checks.
-        * They cannot be enabled earlier because with CONFIG_PRREMPT=y
+        * They cannot be enabled earlier because with CONFIG_PREEMPT=y
         * kernel_thread() would trigger might_sleep() splats. With
         * CONFIG_PREEMPT_VOLUNTARY=y the init task might have scheduled
         * already, but it's stuck on the kthreadd_done completion.
@@ -1034,6 +1034,13 @@ __setup("rodata=", set_debug_rodata);
 static void mark_readonly(void)
 {
        if (rodata_enabled) {
+               /*
+                * load_module() results in W+X mappings, which are cleaned up
+                * with call_rcu_sched().  Let's make sure that queued work is
+                * flushed so that we don't hit false positives looking for
+                * insecure pages which are W+X.
+                */
+               rcu_barrier_sched();
                mark_rodata_ro();
                rodata_test();
        } else
index ebfe9f29dae8e7380dd50e817c75efc15767ba10..016ef90258274425f5af2a5f62c7d426760423c4 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/cred.h>
 #include <linux/timekeeping.h>
 #include <linux/ctype.h>
+#include <linux/nospec.h>
 
 #define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PROG_ARRAY || \
                           (map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \
@@ -102,12 +103,14 @@ const struct bpf_map_ops bpf_map_offload_ops = {
 static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
 {
        const struct bpf_map_ops *ops;
+       u32 type = attr->map_type;
        struct bpf_map *map;
        int err;
 
-       if (attr->map_type >= ARRAY_SIZE(bpf_map_types))
+       if (type >= ARRAY_SIZE(bpf_map_types))
                return ERR_PTR(-EINVAL);
-       ops = bpf_map_types[attr->map_type];
+       type = array_index_nospec(type, ARRAY_SIZE(bpf_map_types));
+       ops = bpf_map_types[type];
        if (!ops)
                return ERR_PTR(-EINVAL);
 
@@ -122,7 +125,7 @@ static struct bpf_map *find_and_alloc_map(union bpf_attr *attr)
        if (IS_ERR(map))
                return map;
        map->ops = ops;
-       map->map_type = attr->map_type;
+       map->map_type = type;
        return map;
 }
 
@@ -871,11 +874,17 @@ static const struct bpf_prog_ops * const bpf_prog_types[] = {
 
 static int find_prog_type(enum bpf_prog_type type, struct bpf_prog *prog)
 {
-       if (type >= ARRAY_SIZE(bpf_prog_types) || !bpf_prog_types[type])
+       const struct bpf_prog_ops *ops;
+
+       if (type >= ARRAY_SIZE(bpf_prog_types))
+               return -EINVAL;
+       type = array_index_nospec(type, ARRAY_SIZE(bpf_prog_types));
+       ops = bpf_prog_types[type];
+       if (!ops)
                return -EINVAL;
 
        if (!bpf_prog_is_dev_bound(prog->aux))
-               prog->aux->ops = bpf_prog_types[type];
+               prog->aux->ops = ops;
        else
                prog->aux->ops = &bpf_offload_prog_ops;
        prog->type = type;
index 6d21894806b46f6a4a2aa7e2d2a9f43c324ca1d8..92d8c98c0f57ac92aacd888d9342debcdec46cdb 100644 (file)
@@ -34,6 +34,7 @@ int compat_get_timex(struct timex *txc, const struct compat_timex __user *utp)
 {
        struct compat_timex tx32;
 
+       memset(txc, 0, sizeof(struct timex));
        if (copy_from_user(&tx32, utp, sizeof(struct compat_timex)))
                return -EFAULT;
 
index 6c6b3c48db7159c57035964d5a3403be475b6d83..1d8ca9ea997975e99af8aa5c73fd831dca0a22b4 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/circ_buf.h>
 #include <linux/poll.h>
+#include <linux/nospec.h>
 
 #include "internal.h"
 
@@ -867,8 +868,10 @@ perf_mmap_to_page(struct ring_buffer *rb, unsigned long pgoff)
                        return NULL;
 
                /* AUX space */
-               if (pgoff >= rb->aux_pgoff)
-                       return virt_to_page(rb->aux_pages[pgoff - rb->aux_pgoff]);
+               if (pgoff >= rb->aux_pgoff) {
+                       int aux_pgoff = array_index_nospec(pgoff - rb->aux_pgoff, rb->aux_nr_pages);
+                       return virt_to_page(rb->aux_pages[aux_pgoff]);
+               }
        }
 
        return __perf_mmap_to_page(rb, pgoff);
index cd50e99202b011dfdb847dd2772f14e818d268bb..2017a39ab4904e8e2fffd648718aa7d05ecb8932 100644 (file)
@@ -55,7 +55,6 @@ enum KTHREAD_BITS {
        KTHREAD_IS_PER_CPU = 0,
        KTHREAD_SHOULD_STOP,
        KTHREAD_SHOULD_PARK,
-       KTHREAD_IS_PARKED,
 };
 
 static inline void set_kthread_struct(void *kthread)
@@ -177,14 +176,12 @@ void *kthread_probe_data(struct task_struct *task)
 
 static void __kthread_parkme(struct kthread *self)
 {
-       __set_current_state(TASK_PARKED);
-       while (test_bit(KTHREAD_SHOULD_PARK, &self->flags)) {
-               if (!test_and_set_bit(KTHREAD_IS_PARKED, &self->flags))
-                       complete(&self->parked);
+       for (;;) {
+               set_current_state(TASK_PARKED);
+               if (!test_bit(KTHREAD_SHOULD_PARK, &self->flags))
+                       break;
                schedule();
-               __set_current_state(TASK_PARKED);
        }
-       clear_bit(KTHREAD_IS_PARKED, &self->flags);
        __set_current_state(TASK_RUNNING);
 }
 
@@ -194,6 +191,11 @@ void kthread_parkme(void)
 }
 EXPORT_SYMBOL_GPL(kthread_parkme);
 
+void kthread_park_complete(struct task_struct *k)
+{
+       complete(&to_kthread(k)->parked);
+}
+
 static int kthread(void *_create)
 {
        /* Copy data: it's on kthread's stack */
@@ -450,22 +452,15 @@ void kthread_unpark(struct task_struct *k)
 {
        struct kthread *kthread = to_kthread(k);
 
-       clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
        /*
-        * We clear the IS_PARKED bit here as we don't wait
-        * until the task has left the park code. So if we'd
-        * park before that happens we'd see the IS_PARKED bit
-        * which might be about to be cleared.
+        * Newly created kthread was parked when the CPU was offline.
+        * The binding was lost and we need to set it again.
         */
-       if (test_and_clear_bit(KTHREAD_IS_PARKED, &kthread->flags)) {
-               /*
-                * Newly created kthread was parked when the CPU was offline.
-                * The binding was lost and we need to set it again.
-                */
-               if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags))
-                       __kthread_bind(k, kthread->cpu, TASK_PARKED);
-               wake_up_state(k, TASK_PARKED);
-       }
+       if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags))
+               __kthread_bind(k, kthread->cpu, TASK_PARKED);
+
+       clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
+       wake_up_state(k, TASK_PARKED);
 }
 EXPORT_SYMBOL_GPL(kthread_unpark);
 
@@ -488,12 +483,13 @@ int kthread_park(struct task_struct *k)
        if (WARN_ON(k->flags & PF_EXITING))
                return -ENOSYS;
 
-       if (!test_bit(KTHREAD_IS_PARKED, &kthread->flags)) {
-               set_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
-               if (k != current) {
-                       wake_up_process(k);
-                       wait_for_completion(&kthread->parked);
-               }
+       if (WARN_ON_ONCE(test_bit(KTHREAD_SHOULD_PARK, &kthread->flags)))
+               return -EBUSY;
+
+       set_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
+       if (k != current) {
+               wake_up_process(k);
+               wait_for_completion(&kthread->parked);
        }
 
        return 0;
index ce8066b881782f9db47c7fc85d8659e1b9cfe9ac..c9bea7f2b43e3b2568f2adeaa299a6545df41df8 100644 (file)
@@ -3517,6 +3517,11 @@ static noinline int do_init_module(struct module *mod)
         * walking this with preempt disabled.  In all the failure paths, we
         * call synchronize_sched(), but we don't want to slow down the success
         * path, so use actual RCU here.
+        * Note that module_alloc() on most architectures creates W+X page
+        * mappings which won't be cleaned up until do_free_init() runs.  Any
+        * code such as mark_rodata_ro() which depends on those mappings to
+        * be cleaned up needs to sync with the queued work - ie
+        * rcu_barrier_sched()
         */
        call_rcu_sched(&freeinit->rcu, do_free_init);
        mutex_unlock(&module_mutex);
index 6be6c575b6cd1d7c20ea72900849b95404066641..2d4ff5353ded618a9b08e1d3b1c9da0fa7d148af 100644 (file)
@@ -2,6 +2,7 @@
 /*
  * Auto-group scheduling implementation:
  */
+#include <linux/nospec.h>
 #include "sched.h"
 
 unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1;
@@ -209,7 +210,7 @@ int proc_sched_autogroup_set_nice(struct task_struct *p, int nice)
        static unsigned long next = INITIAL_JIFFIES;
        struct autogroup *ag;
        unsigned long shares;
-       int err;
+       int err, idx;
 
        if (nice < MIN_NICE || nice > MAX_NICE)
                return -EINVAL;
@@ -227,7 +228,9 @@ int proc_sched_autogroup_set_nice(struct task_struct *p, int nice)
 
        next = HZ / 10 + jiffies;
        ag = autogroup_task_get(p);
-       shares = scale_load(sched_prio_to_weight[nice + 20]);
+
+       idx = array_index_nospec(nice + 20, 40);
+       shares = scale_load(sched_prio_to_weight[idx]);
 
        down_write(&ag->lock);
        err = sched_group_set_shares(ag->tg, shares);
index 5e10aaeebfcc55af83a4ee2e65ff9bbc3b6c0e5d..092f7c4de9036667981ffff80e4e150e113a53c0 100644 (file)
@@ -7,6 +7,9 @@
  */
 #include "sched.h"
 
+#include <linux/kthread.h>
+#include <linux/nospec.h>
+
 #include <asm/switch_to.h>
 #include <asm/tlb.h>
 
@@ -2718,20 +2721,28 @@ static struct rq *finish_task_switch(struct task_struct *prev)
                membarrier_mm_sync_core_before_usermode(mm);
                mmdrop(mm);
        }
-       if (unlikely(prev_state == TASK_DEAD)) {
-               if (prev->sched_class->task_dead)
-                       prev->sched_class->task_dead(prev);
+       if (unlikely(prev_state & (TASK_DEAD|TASK_PARKED))) {
+               switch (prev_state) {
+               case TASK_DEAD:
+                       if (prev->sched_class->task_dead)
+                               prev->sched_class->task_dead(prev);
 
-               /*
-                * Remove function-return probe instances associated with this
-                * task and put them back on the free list.
-                */
-               kprobe_flush_task(prev);
+                       /*
+                        * Remove function-return probe instances associated with this
+                        * task and put them back on the free list.
+                        */
+                       kprobe_flush_task(prev);
+
+                       /* Task is done with its stack. */
+                       put_task_stack(prev);
 
-               /* Task is done with its stack. */
-               put_task_stack(prev);
+                       put_task_struct(prev);
+                       break;
 
-               put_task_struct(prev);
+               case TASK_PARKED:
+                       kthread_park_complete(prev);
+                       break;
+               }
        }
 
        tick_nohz_task_switch();
@@ -3498,23 +3509,8 @@ static void __sched notrace __schedule(bool preempt)
 
 void __noreturn do_task_dead(void)
 {
-       /*
-        * The setting of TASK_RUNNING by try_to_wake_up() may be delayed
-        * when the following two conditions become true.
-        *   - There is race condition of mmap_sem (It is acquired by
-        *     exit_mm()), and
-        *   - SMI occurs before setting TASK_RUNINNG.
-        *     (or hypervisor of virtual machine switches to other guest)
-        *  As a result, we may become TASK_RUNNING after becoming TASK_DEAD
-        *
-        * To avoid it, we have to wait for releasing tsk->pi_lock which
-        * is held by try_to_wake_up()
-        */
-       raw_spin_lock_irq(&current->pi_lock);
-       raw_spin_unlock_irq(&current->pi_lock);
-
        /* Causes final put_task_struct in finish_task_switch(): */
-       __set_current_state(TASK_DEAD);
+       set_special_state(TASK_DEAD);
 
        /* Tell freezer to ignore us: */
        current->flags |= PF_NOFREEZE;
@@ -6928,11 +6924,15 @@ static int cpu_weight_nice_write_s64(struct cgroup_subsys_state *css,
                                     struct cftype *cft, s64 nice)
 {
        unsigned long weight;
+       int idx;
 
        if (nice < MIN_NICE || nice > MAX_NICE)
                return -ERANGE;
 
-       weight = sched_prio_to_weight[NICE_TO_PRIO(nice) - MAX_RT_PRIO];
+       idx = NICE_TO_PRIO(nice) - MAX_RT_PRIO;
+       idx = array_index_nospec(idx, 40);
+       weight = sched_prio_to_weight[idx];
+
        return sched_group_set_shares(css_tg(css), scale_load(weight));
 }
 #endif
index d2c6083304b484352855bdc64262a33e952be9a9..e13df951aca7151225d316da25874b28c6e57d72 100644 (file)
@@ -305,7 +305,8 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
         * Do not reduce the frequency if the CPU has not been idle
         * recently, as the reduction is likely to be premature then.
         */
-       if (busy && next_f < sg_policy->next_freq) {
+       if (busy && next_f < sg_policy->next_freq &&
+           sg_policy->next_freq != UINT_MAX) {
                next_f = sg_policy->next_freq;
 
                /* Reset cached freq as next_freq has changed */
@@ -396,19 +397,6 @@ static void sugov_irq_work(struct irq_work *irq_work)
 
        sg_policy = container_of(irq_work, struct sugov_policy, irq_work);
 
-       /*
-        * For RT tasks, the schedutil governor shoots the frequency to maximum.
-        * Special care must be taken to ensure that this kthread doesn't result
-        * in the same behavior.
-        *
-        * This is (mostly) guaranteed by the work_in_progress flag. The flag is
-        * updated only at the end of the sugov_work() function and before that
-        * the schedutil governor rejects all other frequency scaling requests.
-        *
-        * There is a very rare case though, where the RT thread yields right
-        * after the work_in_progress flag is cleared. The effects of that are
-        * neglected for now.
-        */
        kthread_queue_work(&sg_policy->worker, &sg_policy->work);
 }
 
index 54dc31e7ab9b2b56bc24932740a18a49a9666065..79f574dba09657316468174e478ea9dcda7b1230 100644 (file)
@@ -1854,7 +1854,6 @@ static int task_numa_migrate(struct task_struct *p)
 static void numa_migrate_preferred(struct task_struct *p)
 {
        unsigned long interval = HZ;
-       unsigned long numa_migrate_retry;
 
        /* This task has no NUMA fault statistics yet */
        if (unlikely(p->numa_preferred_nid == -1 || !p->numa_faults))
@@ -1862,18 +1861,7 @@ static void numa_migrate_preferred(struct task_struct *p)
 
        /* Periodically retry migrating the task to the preferred node */
        interval = min(interval, msecs_to_jiffies(p->numa_scan_period) / 16);
-       numa_migrate_retry = jiffies + interval;
-
-       /*
-        * Check that the new retry threshold is after the current one. If
-        * the retry is in the future, it implies that wake_affine has
-        * temporarily asked NUMA balancing to backoff from placement.
-        */
-       if (numa_migrate_retry > p->numa_migrate_retry)
-               return;
-
-       /* Safe to try placing the task on the preferred node */
-       p->numa_migrate_retry = numa_migrate_retry;
+       p->numa_migrate_retry = jiffies + interval;
 
        /* Success if task is already running on preferred CPU */
        if (task_node(p) == p->numa_preferred_nid)
@@ -5922,48 +5910,6 @@ wake_affine_weight(struct sched_domain *sd, struct task_struct *p,
        return this_eff_load < prev_eff_load ? this_cpu : nr_cpumask_bits;
 }
 
-#ifdef CONFIG_NUMA_BALANCING
-static void
-update_wa_numa_placement(struct task_struct *p, int prev_cpu, int target)
-{
-       unsigned long interval;
-
-       if (!static_branch_likely(&sched_numa_balancing))
-               return;
-
-       /* If balancing has no preference then continue gathering data */
-       if (p->numa_preferred_nid == -1)
-               return;
-
-       /*
-        * If the wakeup is not affecting locality then it is neutral from
-        * the perspective of NUMA balacing so continue gathering data.
-        */
-       if (cpu_to_node(prev_cpu) == cpu_to_node(target))
-               return;
-
-       /*
-        * Temporarily prevent NUMA balancing trying to place waker/wakee after
-        * wakee has been moved by wake_affine. This will potentially allow
-        * related tasks to converge and update their data placement. The
-        * 4 * numa_scan_period is to allow the two-pass filter to migrate
-        * hot data to the wakers node.
-        */
-       interval = max(sysctl_numa_balancing_scan_delay,
-                        p->numa_scan_period << 2);
-       p->numa_migrate_retry = jiffies + msecs_to_jiffies(interval);
-
-       interval = max(sysctl_numa_balancing_scan_delay,
-                        current->numa_scan_period << 2);
-       current->numa_migrate_retry = jiffies + msecs_to_jiffies(interval);
-}
-#else
-static void
-update_wa_numa_placement(struct task_struct *p, int prev_cpu, int target)
-{
-}
-#endif
-
 static int wake_affine(struct sched_domain *sd, struct task_struct *p,
                       int this_cpu, int prev_cpu, int sync)
 {
@@ -5979,7 +5925,6 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p,
        if (target == nr_cpumask_bits)
                return prev_cpu;
 
-       update_wa_numa_placement(p, prev_cpu, target);
        schedstat_inc(sd->ttwu_move_affine);
        schedstat_inc(p->se.statistics.nr_wakeups_affine);
        return target;
@@ -9847,6 +9792,7 @@ static int idle_balance(struct rq *this_rq, struct rq_flags *rf)
        if (curr_cost > this_rq->max_idle_balance_cost)
                this_rq->max_idle_balance_cost = curr_cost;
 
+out:
        /*
         * While browsing the domains, we released the rq lock, a task could
         * have been enqueued in the meantime. Since we're not going idle,
@@ -9855,7 +9801,6 @@ static int idle_balance(struct rq *this_rq, struct rq_flags *rf)
        if (this_rq->cfs.h_nr_running && !pulled_task)
                pulled_task = 1;
 
-out:
        /* Move the next balance forward */
        if (time_after(this_rq->next_balance, next_balance))
                this_rq->next_balance = next_balance;
index d4ccea599692397e7526212480d73df3494d3554..9c33163a6165ad847d3a7d3baa71a7f358307503 100644 (file)
@@ -1961,14 +1961,27 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
                        return;
        }
 
+       set_special_state(TASK_TRACED);
+
        /*
         * We're committing to trapping.  TRACED should be visible before
         * TRAPPING is cleared; otherwise, the tracer might fail do_wait().
         * Also, transition to TRACED and updates to ->jobctl should be
         * atomic with respect to siglock and should be done after the arch
         * hook as siglock is released and regrabbed across it.
+        *
+        *     TRACER                               TRACEE
+        *
+        *     ptrace_attach()
+        * [L]   wait_on_bit(JOBCTL_TRAPPING)   [S] set_special_state(TRACED)
+        *     do_wait()
+        *       set_current_state()                smp_wmb();
+        *       ptrace_do_wait()
+        *         wait_task_stopped()
+        *           task_stopped_code()
+        * [L]         task_is_traced()         [S] task_clear_jobctl_trapping();
         */
-       set_current_state(TASK_TRACED);
+       smp_wmb();
 
        current->last_siginfo = info;
        current->exit_code = exit_code;
@@ -2176,7 +2189,7 @@ static bool do_signal_stop(int signr)
                if (task_participate_group_stop(current))
                        notify = CLD_STOPPED;
 
-               __set_current_state(TASK_STOPPED);
+               set_special_state(TASK_STOPPED);
                spin_unlock_irq(&current->sighand->siglock);
 
                /*
index b7591261652d3ea88811f9d2af2a3ce188fb3320..64c0291b579c9a1ce240e5eb941f2f6fcbff5f29 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/smpboot.h>
 #include <linux/atomic.h>
 #include <linux/nmi.h>
+#include <linux/sched/wake_q.h>
 
 /*
  * Structure to determine completion condition and record errors.  May
@@ -65,27 +66,31 @@ static void cpu_stop_signal_done(struct cpu_stop_done *done)
 }
 
 static void __cpu_stop_queue_work(struct cpu_stopper *stopper,
-                                       struct cpu_stop_work *work)
+                                       struct cpu_stop_work *work,
+                                       struct wake_q_head *wakeq)
 {
        list_add_tail(&work->list, &stopper->works);
-       wake_up_process(stopper->thread);
+       wake_q_add(wakeq, stopper->thread);
 }
 
 /* queue @work to @stopper.  if offline, @work is completed immediately */
 static bool cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
 {
        struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
+       DEFINE_WAKE_Q(wakeq);
        unsigned long flags;
        bool enabled;
 
        spin_lock_irqsave(&stopper->lock, flags);
        enabled = stopper->enabled;
        if (enabled)
-               __cpu_stop_queue_work(stopper, work);
+               __cpu_stop_queue_work(stopper, work, &wakeq);
        else if (work->done)
                cpu_stop_signal_done(work->done);
        spin_unlock_irqrestore(&stopper->lock, flags);
 
+       wake_up_q(&wakeq);
+
        return enabled;
 }
 
@@ -229,6 +234,7 @@ static int cpu_stop_queue_two_works(int cpu1, struct cpu_stop_work *work1,
 {
        struct cpu_stopper *stopper1 = per_cpu_ptr(&cpu_stopper, cpu1);
        struct cpu_stopper *stopper2 = per_cpu_ptr(&cpu_stopper, cpu2);
+       DEFINE_WAKE_Q(wakeq);
        int err;
 retry:
        spin_lock_irq(&stopper1->lock);
@@ -252,8 +258,8 @@ retry:
                        goto unlock;
 
        err = 0;
-       __cpu_stop_queue_work(stopper1, work1);
-       __cpu_stop_queue_work(stopper2, work2);
+       __cpu_stop_queue_work(stopper1, work1, &wakeq);
+       __cpu_stop_queue_work(stopper2, work2, &wakeq);
 unlock:
        spin_unlock(&stopper2->lock);
        spin_unlock_irq(&stopper1->lock);
@@ -263,6 +269,9 @@ unlock:
                        cpu_relax();
                goto retry;
        }
+
+       wake_up_q(&wakeq);
+
        return err;
 }
 /**
index 0e974cface0b170761896e320cbb3be908e577dc..84f37420fcf544c09e12f730f05a8a85411b36f1 100644 (file)
@@ -119,6 +119,16 @@ static DEFINE_SPINLOCK(watchdog_lock);
 static int watchdog_running;
 static atomic_t watchdog_reset_pending;
 
+static void inline clocksource_watchdog_lock(unsigned long *flags)
+{
+       spin_lock_irqsave(&watchdog_lock, *flags);
+}
+
+static void inline clocksource_watchdog_unlock(unsigned long *flags)
+{
+       spin_unlock_irqrestore(&watchdog_lock, *flags);
+}
+
 static int clocksource_watchdog_kthread(void *data);
 static void __clocksource_change_rating(struct clocksource *cs, int rating);
 
@@ -142,9 +152,19 @@ static void __clocksource_unstable(struct clocksource *cs)
        cs->flags &= ~(CLOCK_SOURCE_VALID_FOR_HRES | CLOCK_SOURCE_WATCHDOG);
        cs->flags |= CLOCK_SOURCE_UNSTABLE;
 
+       /*
+        * If the clocksource is registered clocksource_watchdog_kthread() will
+        * re-rate and re-select.
+        */
+       if (list_empty(&cs->list)) {
+               cs->rating = 0;
+               return;
+       }
+
        if (cs->mark_unstable)
                cs->mark_unstable(cs);
 
+       /* kick clocksource_watchdog_kthread() */
        if (finished_booting)
                schedule_work(&watchdog_work);
 }
@@ -153,10 +173,8 @@ static void __clocksource_unstable(struct clocksource *cs)
  * clocksource_mark_unstable - mark clocksource unstable via watchdog
  * @cs:                clocksource to be marked unstable
  *
- * This function is called instead of clocksource_change_rating from
- * cpu hotplug code to avoid a deadlock between the clocksource mutex
- * and the cpu hotplug mutex. It defers the update of the clocksource
- * to the watchdog thread.
+ * This function is called by the x86 TSC code to mark clocksources as unstable;
+ * it defers demotion and re-selection to a kthread.
  */
 void clocksource_mark_unstable(struct clocksource *cs)
 {
@@ -164,7 +182,7 @@ void clocksource_mark_unstable(struct clocksource *cs)
 
        spin_lock_irqsave(&watchdog_lock, flags);
        if (!(cs->flags & CLOCK_SOURCE_UNSTABLE)) {
-               if (list_empty(&cs->wd_list))
+               if (!list_empty(&cs->list) && list_empty(&cs->wd_list))
                        list_add(&cs->wd_list, &watchdog_list);
                __clocksource_unstable(cs);
        }
@@ -319,9 +337,8 @@ static void clocksource_resume_watchdog(void)
 
 static void clocksource_enqueue_watchdog(struct clocksource *cs)
 {
-       unsigned long flags;
+       INIT_LIST_HEAD(&cs->wd_list);
 
-       spin_lock_irqsave(&watchdog_lock, flags);
        if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) {
                /* cs is a clocksource to be watched. */
                list_add(&cs->wd_list, &watchdog_list);
@@ -331,7 +348,6 @@ static void clocksource_enqueue_watchdog(struct clocksource *cs)
                if (cs->flags & CLOCK_SOURCE_IS_CONTINUOUS)
                        cs->flags |= CLOCK_SOURCE_VALID_FOR_HRES;
        }
-       spin_unlock_irqrestore(&watchdog_lock, flags);
 }
 
 static void clocksource_select_watchdog(bool fallback)
@@ -373,9 +389,6 @@ static void clocksource_select_watchdog(bool fallback)
 
 static void clocksource_dequeue_watchdog(struct clocksource *cs)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&watchdog_lock, flags);
        if (cs != watchdog) {
                if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) {
                        /* cs is a watched clocksource. */
@@ -384,21 +397,19 @@ static void clocksource_dequeue_watchdog(struct clocksource *cs)
                        clocksource_stop_watchdog();
                }
        }
-       spin_unlock_irqrestore(&watchdog_lock, flags);
 }
 
 static int __clocksource_watchdog_kthread(void)
 {
        struct clocksource *cs, *tmp;
        unsigned long flags;
-       LIST_HEAD(unstable);
        int select = 0;
 
        spin_lock_irqsave(&watchdog_lock, flags);
        list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) {
                if (cs->flags & CLOCK_SOURCE_UNSTABLE) {
                        list_del_init(&cs->wd_list);
-                       list_add(&cs->wd_list, &unstable);
+                       __clocksource_change_rating(cs, 0);
                        select = 1;
                }
                if (cs->flags & CLOCK_SOURCE_RESELECT) {
@@ -410,11 +421,6 @@ static int __clocksource_watchdog_kthread(void)
        clocksource_stop_watchdog();
        spin_unlock_irqrestore(&watchdog_lock, flags);
 
-       /* Needs to be done outside of watchdog lock */
-       list_for_each_entry_safe(cs, tmp, &unstable, wd_list) {
-               list_del_init(&cs->wd_list);
-               __clocksource_change_rating(cs, 0);
-       }
        return select;
 }
 
@@ -447,6 +453,9 @@ static inline int __clocksource_watchdog_kthread(void) { return 0; }
 static bool clocksource_is_watchdog(struct clocksource *cs) { return false; }
 void clocksource_mark_unstable(struct clocksource *cs) { }
 
+static void inline clocksource_watchdog_lock(unsigned long *flags) { }
+static void inline clocksource_watchdog_unlock(unsigned long *flags) { }
+
 #endif /* CONFIG_CLOCKSOURCE_WATCHDOG */
 
 /**
@@ -779,14 +788,19 @@ EXPORT_SYMBOL_GPL(__clocksource_update_freq_scale);
  */
 int __clocksource_register_scale(struct clocksource *cs, u32 scale, u32 freq)
 {
+       unsigned long flags;
 
        /* Initialize mult/shift and max_idle_ns */
        __clocksource_update_freq_scale(cs, scale, freq);
 
        /* Add clocksource to the clocksource list */
        mutex_lock(&clocksource_mutex);
+
+       clocksource_watchdog_lock(&flags);
        clocksource_enqueue(cs);
        clocksource_enqueue_watchdog(cs);
+       clocksource_watchdog_unlock(&flags);
+
        clocksource_select();
        clocksource_select_watchdog(false);
        mutex_unlock(&clocksource_mutex);
@@ -808,8 +822,13 @@ static void __clocksource_change_rating(struct clocksource *cs, int rating)
  */
 void clocksource_change_rating(struct clocksource *cs, int rating)
 {
+       unsigned long flags;
+
        mutex_lock(&clocksource_mutex);
+       clocksource_watchdog_lock(&flags);
        __clocksource_change_rating(cs, rating);
+       clocksource_watchdog_unlock(&flags);
+
        clocksource_select();
        clocksource_select_watchdog(false);
        mutex_unlock(&clocksource_mutex);
@@ -821,6 +840,8 @@ EXPORT_SYMBOL(clocksource_change_rating);
  */
 static int clocksource_unbind(struct clocksource *cs)
 {
+       unsigned long flags;
+
        if (clocksource_is_watchdog(cs)) {
                /* Select and try to install a replacement watchdog. */
                clocksource_select_watchdog(true);
@@ -834,8 +855,12 @@ static int clocksource_unbind(struct clocksource *cs)
                if (curr_clocksource == cs)
                        return -EBUSY;
        }
+
+       clocksource_watchdog_lock(&flags);
        clocksource_dequeue_watchdog(cs);
        list_del_init(&cs->list);
+       clocksource_watchdog_unlock(&flags);
+
        return 0;
 }
 
index 1f951b3df60c59051fdeec23d0257fe2b2487e1b..7d306b74230fac88385e9e64648bcdb4a340faf5 100644 (file)
@@ -762,6 +762,9 @@ static int regex_match_full(char *str, struct regex *r, int len)
 
 static int regex_match_front(char *str, struct regex *r, int len)
 {
+       if (len < r->len)
+               return 0;
+
        if (strncmp(str, r->pattern, r->len) == 0)
                return 1;
        return 0;
index 5985a25e6cbcff7392c50a27a4beea379ab5d62b..5367ffa5c18f9cf98a811dc0e1a2fa15433fa401 100644 (file)
@@ -132,7 +132,12 @@ static int __init find_bit_test(void)
        test_find_next_bit(bitmap, BITMAP_LEN);
        test_find_next_zero_bit(bitmap, BITMAP_LEN);
        test_find_last_bit(bitmap, BITMAP_LEN);
-       test_find_first_bit(bitmap, BITMAP_LEN);
+
+       /*
+        * test_find_first_bit() may take some time, so
+        * traverse only part of bitmap to avoid soft lockup.
+        */
+       test_find_first_bit(bitmap, BITMAP_LEN / 10);
        test_find_next_and_bit(bitmap, bitmap2, BITMAP_LEN);
 
        pr_err("\nStart testing find_bit() with sparse bitmap\n");
index da9e10c827df554040b8c5eac71badbd2b588a95..43e0cbedc3a0ce1adf0d7807b623c9f8b60f3e53 100644 (file)
@@ -1612,11 +1612,9 @@ static void set_iter_tags(struct radix_tree_iter *iter,
 static void __rcu **skip_siblings(struct radix_tree_node **nodep,
                        void __rcu **slot, struct radix_tree_iter *iter)
 {
-       void *sib = node_to_entry(slot - 1);
-
        while (iter->index < iter->next_index) {
                *nodep = rcu_dereference_raw(*slot);
-               if (*nodep && *nodep != sib)
+               if (*nodep && !is_sibling_entry(iter->node, *nodep))
                        return slot;
                slot++;
                iter->index = __radix_tree_iter_add(iter, 1);
@@ -1631,7 +1629,7 @@ void __rcu **__radix_tree_next_slot(void __rcu **slot,
                                struct radix_tree_iter *iter, unsigned flags)
 {
        unsigned tag = flags & RADIX_TREE_ITER_TAG_MASK;
-       struct radix_tree_node *node = rcu_dereference_raw(*slot);
+       struct radix_tree_node *node;
 
        slot = skip_siblings(&node, slot, iter);
 
index 12fbaa4456375a4078eae581e46ad6e73ed0e139..cc640588f1457337217586c4ed5fd1ff072933c7 100644 (file)
@@ -714,7 +714,7 @@ swiotlb_alloc_buffer(struct device *dev, size_t size, dma_addr_t *dma_handle,
 
        phys_addr = swiotlb_tbl_map_single(dev,
                        __phys_to_dma(dev, io_tlb_start),
-                       0, size, DMA_FROM_DEVICE, 0);
+                       0, size, DMA_FROM_DEVICE, attrs);
        if (phys_addr == SWIOTLB_MAP_ERROR)
                goto out_warn;
 
index de16f7869fb19b72b6db134fbc13f8d3b4495f90..6cd7d0740005954ed37f33617298faee60816386 100644 (file)
@@ -331,23 +331,32 @@ static void noinline __init test_mem_optimisations(void)
        unsigned int start, nbits;
 
        for (start = 0; start < 1024; start += 8) {
-               memset(bmap1, 0x5a, sizeof(bmap1));
-               memset(bmap2, 0x5a, sizeof(bmap2));
                for (nbits = 0; nbits < 1024 - start; nbits += 8) {
+                       memset(bmap1, 0x5a, sizeof(bmap1));
+                       memset(bmap2, 0x5a, sizeof(bmap2));
+
                        bitmap_set(bmap1, start, nbits);
                        __bitmap_set(bmap2, start, nbits);
-                       if (!bitmap_equal(bmap1, bmap2, 1024))
+                       if (!bitmap_equal(bmap1, bmap2, 1024)) {
                                printk("set not equal %d %d\n", start, nbits);
-                       if (!__bitmap_equal(bmap1, bmap2, 1024))
+                               failed_tests++;
+                       }
+                       if (!__bitmap_equal(bmap1, bmap2, 1024)) {
                                printk("set not __equal %d %d\n", start, nbits);
+                               failed_tests++;
+                       }
 
                        bitmap_clear(bmap1, start, nbits);
                        __bitmap_clear(bmap2, start, nbits);
-                       if (!bitmap_equal(bmap1, bmap2, 1024))
+                       if (!bitmap_equal(bmap1, bmap2, 1024)) {
                                printk("clear not equal %d %d\n", start, nbits);
-                       if (!__bitmap_equal(bmap1, bmap2, 1024))
+                               failed_tests++;
+                       }
+                       if (!__bitmap_equal(bmap1, bmap2, 1024)) {
                                printk("clear not __equal %d %d\n", start,
                                                                        nbits);
+                               failed_tests++;
+                       }
                }
        }
 }
index 30c0cb8cc9bce78089cb6ad48bcb6b3d5d02e6b2..23920c5ff72859c79f4f50e8e267b56c8f230c7c 100644 (file)
@@ -1669,19 +1669,22 @@ char *pointer_string(char *buf, char *end, const void *ptr,
        return number(buf, end, (unsigned long int)ptr, spec);
 }
 
-static bool have_filled_random_ptr_key __read_mostly;
+static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key);
 static siphash_key_t ptr_key __read_mostly;
 
-static void fill_random_ptr_key(struct random_ready_callback *unused)
+static void enable_ptr_key_workfn(struct work_struct *work)
 {
        get_random_bytes(&ptr_key, sizeof(ptr_key));
-       /*
-        * have_filled_random_ptr_key==true is dependent on get_random_bytes().
-        * ptr_to_id() needs to see have_filled_random_ptr_key==true
-        * after get_random_bytes() returns.
-        */
-       smp_mb();
-       WRITE_ONCE(have_filled_random_ptr_key, true);
+       /* Needs to run from preemptible context */
+       static_branch_disable(&not_filled_random_ptr_key);
+}
+
+static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn);
+
+static void fill_random_ptr_key(struct random_ready_callback *unused)
+{
+       /* This may be in an interrupt handler. */
+       queue_work(system_unbound_wq, &enable_ptr_key_work);
 }
 
 static struct random_ready_callback random_ready = {
@@ -1695,7 +1698,8 @@ static int __init initialize_ptr_random(void)
        if (!ret) {
                return 0;
        } else if (ret == -EALREADY) {
-               fill_random_ptr_key(&random_ready);
+               /* This is in preemptible context */
+               enable_ptr_key_workfn(&enable_ptr_key_work);
                return 0;
        }
 
@@ -1709,7 +1713,7 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec)
        unsigned long hashval;
        const int default_width = 2 * sizeof(ptr);
 
-       if (unlikely(!have_filled_random_ptr_key)) {
+       if (static_branch_unlikely(&not_filled_random_ptr_key)) {
                spec.field_width = default_width;
                /* string length must be less than default_width */
                return string(buf, end, "(ptrval)", spec);
index d5004d82a1d6d7f9b7ec8bc994bd9320f7ea8ced..e14c01513bfd0777baec40a0a3555571c1621b11 100644 (file)
@@ -636,6 +636,7 @@ config DEFERRED_STRUCT_PAGE_INIT
        default n
        depends on NO_BOOTMEM
        depends on !FLATMEM
+       depends on !NEED_PER_CPU_KM
        help
          Ordinarily all struct pages are initialised during early boot in a
          single thread. On very large machines this can take a considerable
index 76af4cfeaf68149f365cf9b29bef64ebe6f1474b..541904a7c60fd596b1f5bc432fc7932bc005fadf 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -544,6 +544,9 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags)
        if (vm_flags & (VM_IO | VM_PFNMAP))
                return -EFAULT;
 
+       if (gup_flags & FOLL_ANON && !vma_is_anonymous(vma))
+               return -EFAULT;
+
        if (write) {
                if (!(vm_flags & VM_WRITE)) {
                        if (!(gup_flags & FOLL_FORCE))
index 568433023831ae098dd5a9d3c1dd209d7dd04be7..8c0af0f7cab18a8e01af67142887abd0ca3c0b81 100644 (file)
@@ -528,14 +528,12 @@ int migrate_page_move_mapping(struct address_space *mapping,
                int i;
                int index = page_index(page);
 
-               for (i = 0; i < HPAGE_PMD_NR; i++) {
+               for (i = 1; i < HPAGE_PMD_NR; i++) {
                        pslot = radix_tree_lookup_slot(&mapping->i_pages,
                                                       index + i);
                        radix_tree_replace_slot(&mapping->i_pages, pslot,
                                                newpage + i);
                }
-       } else {
-               radix_tree_replace_slot(&mapping->i_pages, pslot, newpage);
        }
 
        /*
index 9d5968d1e8e3360ecd1dd9a095139090a1a1f107..78e14facdb6ed281f736450fb434905c0fc7a6c1 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1324,6 +1324,35 @@ static inline int mlock_future_check(struct mm_struct *mm,
        return 0;
 }
 
+static inline u64 file_mmap_size_max(struct file *file, struct inode *inode)
+{
+       if (S_ISREG(inode->i_mode))
+               return inode->i_sb->s_maxbytes;
+
+       if (S_ISBLK(inode->i_mode))
+               return MAX_LFS_FILESIZE;
+
+       /* Special "we do even unsigned file positions" case */
+       if (file->f_mode & FMODE_UNSIGNED_OFFSET)
+               return 0;
+
+       /* Yes, random drivers might want more. But I'm tired of buggy drivers */
+       return ULONG_MAX;
+}
+
+static inline bool file_mmap_ok(struct file *file, struct inode *inode,
+                               unsigned long pgoff, unsigned long len)
+{
+       u64 maxsize = file_mmap_size_max(file, inode);
+
+       if (maxsize && len > maxsize)
+               return false;
+       maxsize -= len;
+       if (pgoff > maxsize >> PAGE_SHIFT)
+               return false;
+       return true;
+}
+
 /*
  * The caller must hold down_write(&current->mm->mmap_sem).
  */
@@ -1409,6 +1438,9 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
                struct inode *inode = file_inode(file);
                unsigned long flags_mask;
 
+               if (!file_mmap_ok(file, inode, pgoff, len))
+                       return -EOVERFLOW;
+
                flags_mask = LEGACY_MAP_MASK | file->f_op->mmap_supported_flags;
 
                switch (flags & MAP_TYPE) {
@@ -3024,6 +3056,32 @@ void exit_mmap(struct mm_struct *mm)
        /* mm's last user has gone, and its about to be pulled down */
        mmu_notifier_release(mm);
 
+       if (unlikely(mm_is_oom_victim(mm))) {
+               /*
+                * Manually reap the mm to free as much memory as possible.
+                * Then, as the oom reaper does, set MMF_OOM_SKIP to disregard
+                * this mm from further consideration.  Taking mm->mmap_sem for
+                * write after setting MMF_OOM_SKIP will guarantee that the oom
+                * reaper will not run on this mm again after mmap_sem is
+                * dropped.
+                *
+                * Nothing can be holding mm->mmap_sem here and the above call
+                * to mmu_notifier_release(mm) ensures mmu notifier callbacks in
+                * __oom_reap_task_mm() will not block.
+                *
+                * This needs to be done before calling munlock_vma_pages_all(),
+                * which clears VM_LOCKED, otherwise the oom reaper cannot
+                * reliably test it.
+                */
+               mutex_lock(&oom_lock);
+               __oom_reap_task_mm(mm);
+               mutex_unlock(&oom_lock);
+
+               set_bit(MMF_OOM_SKIP, &mm->flags);
+               down_write(&mm->mmap_sem);
+               up_write(&mm->mmap_sem);
+       }
+
        if (mm->locked_vm) {
                vma = mm->mmap;
                while (vma) {
@@ -3045,24 +3103,6 @@ void exit_mmap(struct mm_struct *mm)
        /* update_hiwater_rss(mm) here? but nobody should be looking */
        /* Use -1 here to ensure all VMAs in the mm are unmapped */
        unmap_vmas(&tlb, vma, 0, -1);
-
-       if (unlikely(mm_is_oom_victim(mm))) {
-               /*
-                * Wait for oom_reap_task() to stop working on this
-                * mm. Because MMF_OOM_SKIP is already set before
-                * calling down_read(), oom_reap_task() will not run
-                * on this "mm" post up_write().
-                *
-                * mm_is_oom_victim() cannot be set from under us
-                * either because victim->mm is already set to NULL
-                * under task_lock before calling mmput and oom_mm is
-                * set not NULL by the OOM killer only if victim->mm
-                * is found not NULL while holding the task_lock.
-                */
-               set_bit(MMF_OOM_SKIP, &mm->flags);
-               down_write(&mm->mmap_sem);
-               up_write(&mm->mmap_sem);
-       }
        free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, USER_PGTABLES_CEILING);
        tlb_finish_mmu(&tlb, 0, -1);
 
index ff992fa8760aa1e22fc8d5d07df12e293690e877..8ba6cb88cf58a3d48396f7900ac92e467a2207f0 100644 (file)
@@ -469,7 +469,6 @@ bool process_shares_mm(struct task_struct *p, struct mm_struct *mm)
        return false;
 }
 
-
 #ifdef CONFIG_MMU
 /*
  * OOM Reaper kernel thread which tries to reap the memory used by the OOM
@@ -480,16 +479,54 @@ static DECLARE_WAIT_QUEUE_HEAD(oom_reaper_wait);
 static struct task_struct *oom_reaper_list;
 static DEFINE_SPINLOCK(oom_reaper_lock);
 
-static bool __oom_reap_task_mm(struct task_struct *tsk, struct mm_struct *mm)
+void __oom_reap_task_mm(struct mm_struct *mm)
 {
-       struct mmu_gather tlb;
        struct vm_area_struct *vma;
+
+       /*
+        * Tell all users of get_user/copy_from_user etc... that the content
+        * is no longer stable. No barriers really needed because unmapping
+        * should imply barriers already and the reader would hit a page fault
+        * if it stumbled over a reaped memory.
+        */
+       set_bit(MMF_UNSTABLE, &mm->flags);
+
+       for (vma = mm->mmap ; vma; vma = vma->vm_next) {
+               if (!can_madv_dontneed_vma(vma))
+                       continue;
+
+               /*
+                * Only anonymous pages have a good chance to be dropped
+                * without additional steps which we cannot afford as we
+                * are OOM already.
+                *
+                * We do not even care about fs backed pages because all
+                * which are reclaimable have already been reclaimed and
+                * we do not want to block exit_mmap by keeping mm ref
+                * count elevated without a good reason.
+                */
+               if (vma_is_anonymous(vma) || !(vma->vm_flags & VM_SHARED)) {
+                       const unsigned long start = vma->vm_start;
+                       const unsigned long end = vma->vm_end;
+                       struct mmu_gather tlb;
+
+                       tlb_gather_mmu(&tlb, mm, start, end);
+                       mmu_notifier_invalidate_range_start(mm, start, end);
+                       unmap_page_range(&tlb, vma, start, end, NULL);
+                       mmu_notifier_invalidate_range_end(mm, start, end);
+                       tlb_finish_mmu(&tlb, start, end);
+               }
+       }
+}
+
+static bool oom_reap_task_mm(struct task_struct *tsk, struct mm_struct *mm)
+{
        bool ret = true;
 
        /*
         * We have to make sure to not race with the victim exit path
         * and cause premature new oom victim selection:
-        * __oom_reap_task_mm           exit_mm
+        * oom_reap_task_mm             exit_mm
         *   mmget_not_zero
         *                                mmput
         *                                  atomic_dec_and_test
@@ -534,39 +571,8 @@ static bool __oom_reap_task_mm(struct task_struct *tsk, struct mm_struct *mm)
 
        trace_start_task_reaping(tsk->pid);
 
-       /*
-        * Tell all users of get_user/copy_from_user etc... that the content
-        * is no longer stable. No barriers really needed because unmapping
-        * should imply barriers already and the reader would hit a page fault
-        * if it stumbled over a reaped memory.
-        */
-       set_bit(MMF_UNSTABLE, &mm->flags);
-
-       for (vma = mm->mmap ; vma; vma = vma->vm_next) {
-               if (!can_madv_dontneed_vma(vma))
-                       continue;
+       __oom_reap_task_mm(mm);
 
-               /*
-                * Only anonymous pages have a good chance to be dropped
-                * without additional steps which we cannot afford as we
-                * are OOM already.
-                *
-                * We do not even care about fs backed pages because all
-                * which are reclaimable have already been reclaimed and
-                * we do not want to block exit_mmap by keeping mm ref
-                * count elevated without a good reason.
-                */
-               if (vma_is_anonymous(vma) || !(vma->vm_flags & VM_SHARED)) {
-                       const unsigned long start = vma->vm_start;
-                       const unsigned long end = vma->vm_end;
-
-                       tlb_gather_mmu(&tlb, mm, start, end);
-                       mmu_notifier_invalidate_range_start(mm, start, end);
-                       unmap_page_range(&tlb, vma, start, end, NULL);
-                       mmu_notifier_invalidate_range_end(mm, start, end);
-                       tlb_finish_mmu(&tlb, start, end);
-               }
-       }
        pr_info("oom_reaper: reaped process %d (%s), now anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB\n",
                        task_pid_nr(tsk), tsk->comm,
                        K(get_mm_counter(mm, MM_ANONPAGES)),
@@ -587,14 +593,13 @@ static void oom_reap_task(struct task_struct *tsk)
        struct mm_struct *mm = tsk->signal->oom_mm;
 
        /* Retry the down_read_trylock(mmap_sem) a few times */
-       while (attempts++ < MAX_OOM_REAP_RETRIES && !__oom_reap_task_mm(tsk, mm))
+       while (attempts++ < MAX_OOM_REAP_RETRIES && !oom_reap_task_mm(tsk, mm))
                schedule_timeout_idle(HZ/10);
 
        if (attempts <= MAX_OOM_REAP_RETRIES ||
            test_bit(MMF_OOM_SKIP, &mm->flags))
                goto done;
 
-
        pr_info("oom_reaper: unable to reap pid:%d (%s)\n",
                task_pid_nr(tsk), tsk->comm);
        debug_show_all_locks();
index 62eef264a7bd38313aa6855f90b4fa7fd52b0b76..73dc2fcc0eab280f5c5f3620d126c18443b40b31 100644 (file)
@@ -629,7 +629,7 @@ void offline_mem_sections(unsigned long start_pfn, unsigned long end_pfn)
        unsigned long pfn;
 
        for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
-               unsigned long section_nr = pfn_to_section_nr(start_pfn);
+               unsigned long section_nr = pfn_to_section_nr(pfn);
                struct mem_section *ms;
 
                /*
index 536332e988b872973b1e4dc663eebf0c3f595802..a2b9518980ce47c4219a7f28bc705bdf93ae1d68 100644 (file)
@@ -1161,7 +1161,7 @@ const char * const vmstat_text[] = {
        "nr_vmscan_immediate_reclaim",
        "nr_dirtied",
        "nr_written",
-       "nr_indirectly_reclaimable",
+       "", /* nr_indirectly_reclaimable */
 
        /* enum writeback_stat_item counters */
        "nr_dirty_threshold",
@@ -1740,6 +1740,10 @@ static int vmstat_show(struct seq_file *m, void *arg)
        unsigned long *l = arg;
        unsigned long off = l - (unsigned long *)m->private;
 
+       /* Skip hidden vmstat items. */
+       if (*vmstat_text[off] == '\0')
+               return 0;
+
        seq_puts(m, vmstat_text[off]);
        seq_put_decimal_ull(m, " ", *l);
        seq_putc(m, '\n');
index c0bca6153b95d2257333fabe9c1b3eb398d66488..4b366d181f35d12f9a1e600bb7083bbf4dfe7fff 100644 (file)
@@ -144,7 +144,8 @@ enum z3fold_page_flags {
        PAGE_HEADLESS = 0,
        MIDDLE_CHUNK_MAPPED,
        NEEDS_COMPACTING,
-       PAGE_STALE
+       PAGE_STALE,
+       UNDER_RECLAIM
 };
 
 /*****************
@@ -173,6 +174,7 @@ static struct z3fold_header *init_z3fold_page(struct page *page,
        clear_bit(MIDDLE_CHUNK_MAPPED, &page->private);
        clear_bit(NEEDS_COMPACTING, &page->private);
        clear_bit(PAGE_STALE, &page->private);
+       clear_bit(UNDER_RECLAIM, &page->private);
 
        spin_lock_init(&zhdr->page_lock);
        kref_init(&zhdr->refcount);
@@ -756,6 +758,10 @@ static void z3fold_free(struct z3fold_pool *pool, unsigned long handle)
                atomic64_dec(&pool->pages_nr);
                return;
        }
+       if (test_bit(UNDER_RECLAIM, &page->private)) {
+               z3fold_page_unlock(zhdr);
+               return;
+       }
        if (test_and_set_bit(NEEDS_COMPACTING, &page->private)) {
                z3fold_page_unlock(zhdr);
                return;
@@ -840,6 +846,8 @@ static int z3fold_reclaim_page(struct z3fold_pool *pool, unsigned int retries)
                        kref_get(&zhdr->refcount);
                        list_del_init(&zhdr->buddy);
                        zhdr->cpu = -1;
+                       set_bit(UNDER_RECLAIM, &page->private);
+                       break;
                }
 
                list_del_init(&page->lru);
@@ -887,25 +895,35 @@ static int z3fold_reclaim_page(struct z3fold_pool *pool, unsigned int retries)
                                goto next;
                }
 next:
-               spin_lock(&pool->lock);
                if (test_bit(PAGE_HEADLESS, &page->private)) {
                        if (ret == 0) {
-                               spin_unlock(&pool->lock);
                                free_z3fold_page(page);
                                return 0;
                        }
-               } else if (kref_put(&zhdr->refcount, release_z3fold_page)) {
-                       atomic64_dec(&pool->pages_nr);
+                       spin_lock(&pool->lock);
+                       list_add(&page->lru, &pool->lru);
+                       spin_unlock(&pool->lock);
+               } else {
+                       z3fold_page_lock(zhdr);
+                       clear_bit(UNDER_RECLAIM, &page->private);
+                       if (kref_put(&zhdr->refcount,
+                                       release_z3fold_page_locked)) {
+                               atomic64_dec(&pool->pages_nr);
+                               return 0;
+                       }
+                       /*
+                        * if we are here, the page is still not completely
+                        * free. Take the global pool lock then to be able
+                        * to add it back to the lru list
+                        */
+                       spin_lock(&pool->lock);
+                       list_add(&page->lru, &pool->lru);
                        spin_unlock(&pool->lock);
-                       return 0;
+                       z3fold_page_unlock(zhdr);
                }
 
-               /*
-                * Add to the beginning of LRU.
-                * Pool lock has to be kept here to ensure the page has
-                * not already been released
-                */
-               list_add(&page->lru, &pool->lru);
+               /* We started off locked to we need to lock the pool back */
+               spin_lock(&pool->lock);
        }
        spin_unlock(&pool->lock);
        return -EAGAIN;
index 38aa6345bdfa2ec9fc52155e5b0eb3b369fdf463..b718db2085b21c8583601a3c9aa23414dc16ef3b 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/module.h>
 
 /**
- *  p9_release_req_pages - Release pages after the transaction.
+ *  p9_release_pages - Release pages after the transaction.
  */
 void p9_release_pages(struct page **pages, int nr_pages)
 {
index 0cfba919d167db9042dcf3fc2b4be7d1c8eaa852..848969fe797904aae1eb3cac7bd18f00382761cd 100644 (file)
@@ -1092,8 +1092,8 @@ static struct p9_trans_module p9_fd_trans = {
 };
 
 /**
- * p9_poll_proc - poll worker thread
- * @a: thread state and arguments
+ * p9_poll_workfn - poll worker thread
+ * @work: work queue
  *
  * polls all v9fs transports for new events and queues the appropriate
  * work to the work queue
index 6d8e3031978f3493edb123a51b58b30b1c2807c5..3d414acb7015d8fc73f20bec381e6200ce3d3d53 100644 (file)
@@ -68,8 +68,6 @@
  * @pd: Protection Domain pointer
  * @qp: Queue Pair pointer
  * @cq: Completion Queue pointer
- * @dm_mr: DMA Memory Region pointer
- * @lkey: The local access only memory region key
  * @timeout: Number of uSecs to wait for connection management events
  * @privport: Whether a privileged port may be used
  * @port: The port to use
@@ -632,7 +630,7 @@ static int p9_rdma_bind_privport(struct p9_trans_rdma *rdma)
 }
 
 /**
- * trans_create_rdma - Transport method for creating atransport instance
+ * rdma_create_trans - Transport method for creating a transport instance
  * @client: client instance
  * @addr: IP address string
  * @args: Mount options string
index 3aa5a93ad107c1490146240a112e3a9bf3a89b62..4d0372263e5d3057f0b300fbacb6f50a3c58e6ad 100644 (file)
@@ -60,7 +60,6 @@ static atomic_t vp_pinned = ATOMIC_INIT(0);
 
 /**
  * struct virtio_chan - per-instance transport information
- * @initialized: whether the channel is initialized
  * @inuse: whether the channel is in use
  * @lock: protects multiple elements within this structure
  * @client: client instance
@@ -385,8 +384,8 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
  * @uidata: user bffer that should be ued for zero copy read
  * @uodata: user buffer that shoud be user for zero copy write
  * @inlen: read buffer size
- * @olen: write buffer size
- * @hdrlen: reader header size, This is the size of response protocol data
+ * @outlen: write buffer size
+ * @in_hdr_len: reader header size, This is the size of response protocol data
  *
  */
 static int
index 086a4abdfa7cfcfad4934eb52613f4fe57723eb2..0f19960390a671dc1929575537ff5ad803add2ff 100644 (file)
@@ -485,7 +485,7 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev,
 
 static int xen_9pfs_front_resume(struct xenbus_device *dev)
 {
-       dev_warn(&dev->dev, "suspsend/resume unsupported\n");
+       dev_warn(&dev->dev, "suspend/resume unsupported\n");
        return 0;
 }
 
index 01d5d20a6eb1a51dceb99b7617faa339e1fd13d8..3138a869b5c0ce1c2bf47ec80b1f1781645ce303 100644 (file)
@@ -41,6 +41,9 @@ static unsigned char bridge_ula_lec[] = { 0x01, 0x80, 0xc2, 0x00, 0x00 };
 #include <linux/module.h>
 #include <linux/init.h>
 
+/* Hardening for Spectre-v1 */
+#include <linux/nospec.h>
+
 #include "lec.h"
 #include "lec_arpc.h"
 #include "resources.h"
@@ -687,8 +690,10 @@ static int lec_vcc_attach(struct atm_vcc *vcc, void __user *arg)
        bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc));
        if (bytes_left != 0)
                pr_info("copy from user failed for %d bytes\n", bytes_left);
-       if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF ||
-           !dev_lec[ioc_data.dev_num])
+       if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF)
+               return -EINVAL;
+       ioc_data.dev_num = array_index_nospec(ioc_data.dev_num, MAX_LEC_ITF);
+       if (!dev_lec[ioc_data.dev_num])
                return -EINVAL;
        vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL);
        if (!vpriv)
index ea2a6c9fb7cef01b54eb86a1a7c580625feb4b1e..d2667e5dddc3acf4524ae280bee3ac832accdf0f 100644 (file)
@@ -157,10 +157,12 @@ static void ceph_osd_data_bio_init(struct ceph_osd_data *osd_data,
 #endif /* CONFIG_BLOCK */
 
 static void ceph_osd_data_bvecs_init(struct ceph_osd_data *osd_data,
-                                    struct ceph_bvec_iter *bvec_pos)
+                                    struct ceph_bvec_iter *bvec_pos,
+                                    u32 num_bvecs)
 {
        osd_data->type = CEPH_OSD_DATA_TYPE_BVECS;
        osd_data->bvec_pos = *bvec_pos;
+       osd_data->num_bvecs = num_bvecs;
 }
 
 #define osd_req_op_data(oreq, whch, typ, fld)                          \
@@ -237,6 +239,22 @@ void osd_req_op_extent_osd_data_bio(struct ceph_osd_request *osd_req,
 EXPORT_SYMBOL(osd_req_op_extent_osd_data_bio);
 #endif /* CONFIG_BLOCK */
 
+void osd_req_op_extent_osd_data_bvecs(struct ceph_osd_request *osd_req,
+                                     unsigned int which,
+                                     struct bio_vec *bvecs, u32 num_bvecs,
+                                     u32 bytes)
+{
+       struct ceph_osd_data *osd_data;
+       struct ceph_bvec_iter it = {
+               .bvecs = bvecs,
+               .iter = { .bi_size = bytes },
+       };
+
+       osd_data = osd_req_op_data(osd_req, which, extent, osd_data);
+       ceph_osd_data_bvecs_init(osd_data, &it, num_bvecs);
+}
+EXPORT_SYMBOL(osd_req_op_extent_osd_data_bvecs);
+
 void osd_req_op_extent_osd_data_bvec_pos(struct ceph_osd_request *osd_req,
                                         unsigned int which,
                                         struct ceph_bvec_iter *bvec_pos)
@@ -244,7 +262,7 @@ void osd_req_op_extent_osd_data_bvec_pos(struct ceph_osd_request *osd_req,
        struct ceph_osd_data *osd_data;
 
        osd_data = osd_req_op_data(osd_req, which, extent, osd_data);
-       ceph_osd_data_bvecs_init(osd_data, bvec_pos);
+       ceph_osd_data_bvecs_init(osd_data, bvec_pos, 0);
 }
 EXPORT_SYMBOL(osd_req_op_extent_osd_data_bvec_pos);
 
@@ -287,7 +305,8 @@ EXPORT_SYMBOL(osd_req_op_cls_request_data_pages);
 
 void osd_req_op_cls_request_data_bvecs(struct ceph_osd_request *osd_req,
                                       unsigned int which,
-                                      struct bio_vec *bvecs, u32 bytes)
+                                      struct bio_vec *bvecs, u32 num_bvecs,
+                                      u32 bytes)
 {
        struct ceph_osd_data *osd_data;
        struct ceph_bvec_iter it = {
@@ -296,7 +315,7 @@ void osd_req_op_cls_request_data_bvecs(struct ceph_osd_request *osd_req,
        };
 
        osd_data = osd_req_op_data(osd_req, which, cls, request_data);
-       ceph_osd_data_bvecs_init(osd_data, &it);
+       ceph_osd_data_bvecs_init(osd_data, &it, num_bvecs);
        osd_req->r_ops[which].cls.indata_len += bytes;
        osd_req->r_ops[which].indata_len += bytes;
 }
index b8d95cb71c25dd69c8a88b2c886a3f0d2ce1174f..44a7e16bf3b5e14c03b99a806145203fc2a4af01 100644 (file)
@@ -20,8 +20,8 @@ typedef unsigned __bitwise lowpan_rx_result;
 struct frag_lowpan_compare_key {
        u16 tag;
        u16 d_size;
-       const struct ieee802154_addr src;
-       const struct ieee802154_addr dst;
+       struct ieee802154_addr src;
+       struct ieee802154_addr dst;
 };
 
 /* Equivalent of ipv4 struct ipq
index 1790b65944b3ee188608b1a76d4f9a42fb1479d5..2cc224106b6928bafd92460ba59ea69db0778761 100644 (file)
@@ -75,14 +75,14 @@ fq_find(struct net *net, const struct lowpan_802154_cb *cb,
 {
        struct netns_ieee802154_lowpan *ieee802154_lowpan =
                net_ieee802154_lowpan(net);
-       struct frag_lowpan_compare_key key = {
-               .tag = cb->d_tag,
-               .d_size = cb->d_size,
-               .src = *src,
-               .dst = *dst,
-       };
+       struct frag_lowpan_compare_key key = {};
        struct inet_frag_queue *q;
 
+       key.tag = cb->d_tag;
+       key.d_size = cb->d_size;
+       key.src = *src;
+       key.dst = *dst;
+
        q = inet_frag_find(&ieee802154_lowpan->frags, &key);
        if (!q)
                return NULL;
@@ -372,7 +372,7 @@ int lowpan_frag_rcv(struct sk_buff *skb, u8 frag_type)
        struct lowpan_frag_queue *fq;
        struct net *net = dev_net(skb->dev);
        struct lowpan_802154_cb *cb = lowpan_802154_cb(skb);
-       struct ieee802154_hdr hdr;
+       struct ieee802154_hdr hdr = {};
        int err;
 
        if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
index 05e47d77700993568a507d8e3b8bf30d5f843d8f..56a010622f70d08ccf541f51c83e8a601c07646a 100644 (file)
@@ -775,8 +775,10 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        ipc.addr = faddr = daddr;
 
        if (ipc.opt && ipc.opt->opt.srr) {
-               if (!daddr)
-                       return -EINVAL;
+               if (!daddr) {
+                       err = -EINVAL;
+                       goto out_free;
+               }
                faddr = ipc.opt->opt.faddr;
        }
        tos = get_rttos(&ipc, inet);
@@ -842,6 +844,7 @@ back_from_confirm:
 
 out:
        ip_rt_put(rt);
+out_free:
        if (free)
                kfree(ipc.opt);
        if (!err) {
index 1412a7baf0b9c214d4ae006abb306b499369a09e..29268efad24777b6839923e25d7bf138c9cf0643 100644 (file)
@@ -1375,6 +1375,7 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
                        fnhe->fnhe_gw = 0;
                        fnhe->fnhe_pmtu = 0;
                        fnhe->fnhe_expires = 0;
+                       fnhe->fnhe_mtu_locked = false;
                        fnhe_flush_routes(fnhe);
                        orig = NULL;
                }
index 24b5c59b1c533a9793042c134f23891953527752..b61a770884fa81a92fb503adb08299677a322498 100644 (file)
@@ -401,9 +401,9 @@ static int compute_score(struct sock *sk, struct net *net,
                bool dev_match = (sk->sk_bound_dev_if == dif ||
                                  sk->sk_bound_dev_if == sdif);
 
-               if (exact_dif && !dev_match)
+               if (!dev_match)
                        return -1;
-               if (sk->sk_bound_dev_if && dev_match)
+               if (sk->sk_bound_dev_if)
                        score += 4;
        }
 
@@ -952,8 +952,10 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        sock_tx_timestamp(sk, ipc.sockc.tsflags, &ipc.tx_flags);
 
        if (ipc.opt && ipc.opt->opt.srr) {
-               if (!daddr)
-                       return -EINVAL;
+               if (!daddr) {
+                       err = -EINVAL;
+                       goto out_free;
+               }
                faddr = ipc.opt->opt.faddr;
                connected = 0;
        }
@@ -1074,6 +1076,7 @@ do_append_data:
 
 out:
        ip_rt_put(rt);
+out_free:
        if (free)
                kfree(ipc.opt);
        if (!err)
index 6794ddf0547cd0bec8b5ac7e4069b6f746809a49..11e4e80cf7e981826ade121bfe9c4559724c0f40 100644 (file)
@@ -34,16 +34,15 @@ config IPV6_ROUTE_INFO
        bool "IPv6: Route Information (RFC 4191) support"
        depends on IPV6_ROUTER_PREF
        ---help---
-         This is experimental support of Route Information.
+         Support of Route Information.
 
          If unsure, say N.
 
 config IPV6_OPTIMISTIC_DAD
        bool "IPv6: Enable RFC 4429 Optimistic DAD"
        ---help---
-         This is experimental support for optimistic Duplicate
-         Address Detection.  It allows for autoconfigured addresses
-         to be used more quickly.
+         Support for optimistic Duplicate Address Detection. It allows for
+         autoconfigured addresses to be used more quickly.
 
          If unsure, say N.
 
@@ -280,7 +279,7 @@ config IPV6_MROUTE
        depends on IPV6
        select IP_MROUTE_COMMON
        ---help---
-         Experimental support for IPv6 multicast forwarding.
+         Support for IPv6 multicast forwarding.
          If unsure, say N.
 
 config IPV6_MROUTE_MULTIPLE_TABLES
index c214ffec02f06f6dccfb9769fc8640e5e56da618..ca957dd93a2989431a8b97c49b0592471b18bd78 100644 (file)
@@ -669,7 +669,7 @@ static void vti6_link_config(struct ip6_tnl *t, bool keep_mtu)
        else
                mtu = ETH_DATA_LEN - LL_MAX_HEADER - sizeof(struct ipv6hdr);
 
-       dev->mtu = max_t(int, mtu, IPV6_MIN_MTU);
+       dev->mtu = max_t(int, mtu, IPV4_MIN_MTU);
 }
 
 /**
@@ -881,7 +881,7 @@ static void vti6_dev_setup(struct net_device *dev)
        dev->priv_destructor = vti6_dev_free;
 
        dev->type = ARPHRD_TUNNEL6;
-       dev->min_mtu = IPV6_MIN_MTU;
+       dev->min_mtu = IPV4_MIN_MTU;
        dev->max_mtu = IP_MAX_MTU - sizeof(struct ipv6hdr);
        dev->flags |= IFF_NOARP;
        dev->addr_len = sizeof(struct in6_addr);
index 4ec76a87aeb869050022d71c8095d840526cef70..ea0730028e5d6fb386094590ab5c45233835de7b 100644 (file)
@@ -148,9 +148,9 @@ static int compute_score(struct sock *sk, struct net *net,
                bool dev_match = (sk->sk_bound_dev_if == dif ||
                                  sk->sk_bound_dev_if == sdif);
 
-               if (exact_dif && !dev_match)
+               if (!dev_match)
                        return -1;
-               if (sk->sk_bound_dev_if && dev_match)
+               if (sk->sk_bound_dev_if)
                        score++;
        }
 
index f85f0d7480acf48074a7d53557c3c50ca59973cf..4a46df8441c9fabd96c1a10e1b74e8821760c6e4 100644 (file)
@@ -341,6 +341,9 @@ static void __net_exit xfrm6_tunnel_net_exit(struct net *net)
        struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net);
        unsigned int i;
 
+       xfrm_state_flush(net, IPSEC_PROTO_ANY, false);
+       xfrm_flush_gc();
+
        for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
                WARN_ON_ONCE(!hlist_empty(&xfrm6_tn->spi_byaddr[i]));
 
index 7e2e7188e7f4a28aa45c26848364ab0c297161a2..e62e52e8f1415f711133a97c357ae3da570ab781 100644 (file)
@@ -437,6 +437,24 @@ static int verify_address_len(const void *p)
        return 0;
 }
 
+static inline int sadb_key_len(const struct sadb_key *key)
+{
+       int key_bytes = DIV_ROUND_UP(key->sadb_key_bits, 8);
+
+       return DIV_ROUND_UP(sizeof(struct sadb_key) + key_bytes,
+                           sizeof(uint64_t));
+}
+
+static int verify_key_len(const void *p)
+{
+       const struct sadb_key *key = p;
+
+       if (sadb_key_len(key) > key->sadb_key_len)
+               return -EINVAL;
+
+       return 0;
+}
+
 static inline int pfkey_sec_ctx_len(const struct sadb_x_sec_ctx *sec_ctx)
 {
        return DIV_ROUND_UP(sizeof(struct sadb_x_sec_ctx) +
@@ -533,16 +551,25 @@ static int parse_exthdrs(struct sk_buff *skb, const struct sadb_msg *hdr, void *
                                return -EINVAL;
                        if (ext_hdrs[ext_type-1] != NULL)
                                return -EINVAL;
-                       if (ext_type == SADB_EXT_ADDRESS_SRC ||
-                           ext_type == SADB_EXT_ADDRESS_DST ||
-                           ext_type == SADB_EXT_ADDRESS_PROXY ||
-                           ext_type == SADB_X_EXT_NAT_T_OA) {
+                       switch (ext_type) {
+                       case SADB_EXT_ADDRESS_SRC:
+                       case SADB_EXT_ADDRESS_DST:
+                       case SADB_EXT_ADDRESS_PROXY:
+                       case SADB_X_EXT_NAT_T_OA:
                                if (verify_address_len(p))
                                        return -EINVAL;
-                       }
-                       if (ext_type == SADB_X_EXT_SEC_CTX) {
+                               break;
+                       case SADB_X_EXT_SEC_CTX:
                                if (verify_sec_ctx_len(p))
                                        return -EINVAL;
+                               break;
+                       case SADB_EXT_KEY_AUTH:
+                       case SADB_EXT_KEY_ENCRYPT:
+                               if (verify_key_len(p))
+                                       return -EINVAL;
+                               break;
+                       default:
+                               break;
                        }
                        ext_hdrs[ext_type-1] = (void *) p;
                }
@@ -1104,14 +1131,12 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
        key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
        if (key != NULL &&
            sa->sadb_sa_auth != SADB_X_AALG_NULL &&
-           ((key->sadb_key_bits+7) / 8 == 0 ||
-            (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t)))
+           key->sadb_key_bits == 0)
                return ERR_PTR(-EINVAL);
        key = ext_hdrs[SADB_EXT_KEY_ENCRYPT-1];
        if (key != NULL &&
            sa->sadb_sa_encrypt != SADB_EALG_NULL &&
-           ((key->sadb_key_bits+7) / 8 == 0 ||
-            (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t)))
+           key->sadb_key_bits == 0)
                return ERR_PTR(-EINVAL);
 
        x = xfrm_state_alloc(net);
index cb80ebb38311e7db1e91881cdec59bc33724d856..1beeea9549fa6ec1f7b0e5f9af8ff3250a316f59 100644 (file)
@@ -930,6 +930,9 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
        if (size > llc->dev->mtu)
                size = llc->dev->mtu;
        copied = size - hdrlen;
+       rc = -EINVAL;
+       if (copied < 0)
+               goto release;
        release_sock(sk);
        skb = sock_alloc_send_skb(sk, size, noblock, &rc);
        lock_sock(sk);
index 595c662a61e87bd7621c9336df8a81b5080c1d1f..ac4295296514365ad1972ddc22754be1cdb8384a 100644 (file)
@@ -8,6 +8,7 @@
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007-2010, Intel Corporation
  * Copyright(c) 2015-2017 Intel Deutschland GmbH
+ * Copyright (C) 2018 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -970,6 +971,9 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
 
                sta->ampdu_mlme.addba_req_num[tid] = 0;
 
+               tid_tx->timeout =
+                       le16_to_cpu(mgmt->u.action.u.addba_resp.timeout);
+
                if (tid_tx->timeout) {
                        mod_timer(&tid_tx->session_timer,
                                  TU_TO_EXP_TIME(tid_tx->timeout));
index 69449db7e283316197a4d900f6cd9159e3185ea5..233068756502b733520190835bff56b5f869be10 100644 (file)
@@ -36,6 +36,7 @@
 #define IEEE80211_AUTH_TIMEOUT         (HZ / 5)
 #define IEEE80211_AUTH_TIMEOUT_LONG    (HZ / 2)
 #define IEEE80211_AUTH_TIMEOUT_SHORT   (HZ / 10)
+#define IEEE80211_AUTH_TIMEOUT_SAE     (HZ * 2)
 #define IEEE80211_AUTH_MAX_TRIES       3
 #define IEEE80211_AUTH_WAIT_ASSOC      (HZ * 5)
 #define IEEE80211_ASSOC_TIMEOUT                (HZ / 5)
@@ -1787,7 +1788,7 @@ static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
                params[ac].acm = acm;
                params[ac].uapsd = uapsd;
 
-               if (params->cw_min == 0 ||
+               if (params[ac].cw_min == 0 ||
                    params[ac].cw_min > params[ac].cw_max) {
                        sdata_info(sdata,
                                   "AP has invalid WMM params (CWmin/max=%d/%d for ACI %d), using defaults\n",
@@ -3814,16 +3815,19 @@ static int ieee80211_auth(struct ieee80211_sub_if_data *sdata)
                            tx_flags);
 
        if (tx_flags == 0) {
-               auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
-               auth_data->timeout_started = true;
-               run_again(sdata, auth_data->timeout);
+               if (auth_data->algorithm == WLAN_AUTH_SAE)
+                       auth_data->timeout = jiffies +
+                               IEEE80211_AUTH_TIMEOUT_SAE;
+               else
+                       auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
        } else {
                auth_data->timeout =
                        round_jiffies_up(jiffies + IEEE80211_AUTH_TIMEOUT_LONG);
-               auth_data->timeout_started = true;
-               run_again(sdata, auth_data->timeout);
        }
 
+       auth_data->timeout_started = true;
+       run_again(sdata, auth_data->timeout);
+
        return 0;
 }
 
@@ -3894,8 +3898,15 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
                ifmgd->status_received = false;
                if (ifmgd->auth_data && ieee80211_is_auth(fc)) {
                        if (status_acked) {
-                               ifmgd->auth_data->timeout =
-                                       jiffies + IEEE80211_AUTH_TIMEOUT_SHORT;
+                               if (ifmgd->auth_data->algorithm ==
+                                   WLAN_AUTH_SAE)
+                                       ifmgd->auth_data->timeout =
+                                               jiffies +
+                                               IEEE80211_AUTH_TIMEOUT_SAE;
+                               else
+                                       ifmgd->auth_data->timeout =
+                                               jiffies +
+                                               IEEE80211_AUTH_TIMEOUT_SHORT;
                                run_again(sdata, ifmgd->auth_data->timeout);
                        } else {
                                ifmgd->auth_data->timeout = jiffies - 1;
index 535de3161a781f90ea9a91e97fdc4aa46db0eac6..05a265cd573d4b5d9c5263dd4f8659ad83d327fb 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
+ * Copyright (C) 2018 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -1135,7 +1136,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
        }
 
        /* reset session timer */
-       if (reset_agg_timer && tid_tx->timeout)
+       if (reset_agg_timer)
                tid_tx->last_tx = jiffies;
 
        return queued;
index 55342c4d5cec6a999065aa1c9607bdf476c59d36..2e2dd88fc79ffd460fdc54d305b6380da2653568 100644 (file)
@@ -2606,13 +2606,13 @@ static int netlink_seq_show(struct seq_file *seq, void *v)
 {
        if (v == SEQ_START_TOKEN) {
                seq_puts(seq,
-                        "sk       Eth Pid    Groups   "
-                        "Rmem     Wmem     Dump     Locks     Drops     Inode\n");
+                        "sk               Eth Pid        Groups   "
+                        "Rmem     Wmem     Dump  Locks    Drops    Inode\n");
        } else {
                struct sock *s = v;
                struct netlink_sock *nlk = nlk_sk(s);
 
-               seq_printf(seq, "%pK %-3d %-6u %08x %-8d %-8d %d %-8d %-8d %-8lu\n",
+               seq_printf(seq, "%pK %-3d %-10u %08x %-8d %-8d %-5d %-8d %-8d %-8lu\n",
                           s,
                           s->sk_protocol,
                           nlk->portid,
index d7da99a0b0b852d7459eed9ac6d3cdf3d49a1a1c..9696ef96b719bf24625adea2a959deac1d2a975f 100644 (file)
@@ -57,6 +57,8 @@ int nsh_pop(struct sk_buff *skb)
                return -ENOMEM;
        nh = (struct nshhdr *)(skb->data);
        length = nsh_hdr_len(nh);
+       if (length < NSH_BASE_HDR_LEN)
+               return -EINVAL;
        inner_proto = tun_p_to_eth_p(nh->np);
        if (!pskb_may_pull(skb, length))
                return -ENOMEM;
@@ -90,6 +92,8 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
        if (unlikely(!pskb_may_pull(skb, NSH_BASE_HDR_LEN)))
                goto out;
        nsh_len = nsh_hdr_len(nsh_hdr(skb));
+       if (nsh_len < NSH_BASE_HDR_LEN)
+               goto out;
        if (unlikely(!pskb_may_pull(skb, nsh_len)))
                goto out;
 
index 7322aa1e382e4ba476243ef47801a50df2efb7f1..492ab0c36f7c9e3caf6de7e7d77368028716e09c 100644 (file)
@@ -1712,13 +1712,10 @@ static void nlattr_set(struct nlattr *attr, u8 val,
 
        /* The nlattr stream should already have been validated */
        nla_for_each_nested(nla, attr, rem) {
-               if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED) {
-                       if (tbl[nla_type(nla)].next)
-                               tbl = tbl[nla_type(nla)].next;
-                       nlattr_set(nla, val, tbl);
-               } else {
+               if (tbl[nla_type(nla)].len == OVS_ATTR_NESTED)
+                       nlattr_set(nla, val, tbl[nla_type(nla)].next ? : tbl);
+               else
                        memset(nla_data(nla), val, nla_len(nla));
-               }
 
                if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE)
                        *(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK;
index 41bd496531d45e8d43428584605bfb55ef249169..00192a996be0eab95be229f801ada687cca0f71a 100644 (file)
@@ -137,13 +137,18 @@ static int rfkill_gpio_probe(struct platform_device *pdev)
 
        ret = rfkill_register(rfkill->rfkill_dev);
        if (ret < 0)
-               return ret;
+               goto err_destroy;
 
        platform_set_drvdata(pdev, rfkill);
 
        dev_info(&pdev->dev, "%s device registered.\n", rfkill->name);
 
        return 0;
+
+err_destroy:
+       rfkill_destroy(rfkill->rfkill_dev);
+
+       return ret;
 }
 
 static int rfkill_gpio_remove(struct platform_device *pdev)
index 9a2c8e7c000e6ad21858b082fa2e8aa5a295114e..2b463047dd7ba93267feb584e1ffda280449a0b3 100644 (file)
@@ -313,7 +313,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
        memset(&cp, 0, sizeof(cp));
        cp.local                = rx->local;
        cp.key                  = key;
-       cp.security_level       = 0;
+       cp.security_level       = rx->min_sec_level;
        cp.exclusive            = false;
        cp.upgrade              = upgrade;
        cp.service_id           = srx->srx_service;
index 90d7079e0aa99327ced07c61d4c8e315fbe26f8d..19975d2ca9a20367d900f14ab8b776953e3d5ba1 100644 (file)
@@ -476,6 +476,7 @@ enum rxrpc_call_flag {
        RXRPC_CALL_SEND_PING,           /* A ping will need to be sent */
        RXRPC_CALL_PINGING,             /* Ping in process */
        RXRPC_CALL_RETRANS_TIMEOUT,     /* Retransmission due to timeout occurred */
+       RXRPC_CALL_BEGAN_RX_TIMER,      /* We began the expect_rx_by timer */
 };
 
 /*
index c717152070dff2906d15aa53bd1c488bd42cf2c8..1350f1be8037b7655a9ba9ebc46ff898e043ff5c 100644 (file)
@@ -40,7 +40,7 @@ static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
        } __attribute__((packed)) pkt;
        struct rxrpc_ackinfo ack_info;
        size_t len;
-       int ioc;
+       int ret, ioc;
        u32 serial, mtu, call_id, padding;
 
        _enter("%d", conn->debug_id);
@@ -135,10 +135,13 @@ static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
                break;
        }
 
-       kernel_sendmsg(conn->params.local->socket, &msg, iov, ioc, len);
+       ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, ioc, len);
        conn->params.peer->last_tx_at = ktime_get_real();
+       if (ret < 0)
+               trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
+                                   rxrpc_tx_fail_call_final_resend);
+
        _leave("");
-       return;
 }
 
 /*
@@ -236,6 +239,8 @@ static int rxrpc_abort_connection(struct rxrpc_connection *conn,
 
        ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
        if (ret < 0) {
+               trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
+                                   rxrpc_tx_fail_conn_abort);
                _debug("sendmsg failed: %d", ret);
                return -EAGAIN;
        }
index 0410d2277ca28bcf0259df897581b947f707fac1..b5fd6381313d06b1b02ad6e6f6ca5c0dcc74b10d 100644 (file)
@@ -971,7 +971,7 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call,
        if (timo) {
                unsigned long now = jiffies, expect_rx_by;
 
-               expect_rx_by = jiffies + timo;
+               expect_rx_by = now + timo;
                WRITE_ONCE(call->expect_rx_by, expect_rx_by);
                rxrpc_reduce_call_timer(call, expect_rx_by, now,
                                        rxrpc_timer_set_for_normal);
index 93b5d910b4a130a8f2641f1a20f0d2e83b60ed56..8325f1b868404690d54a6e98d70b6896c3537f72 100644 (file)
@@ -71,7 +71,8 @@ static void rxrpc_send_version_request(struct rxrpc_local *local,
 
        ret = kernel_sendmsg(local->socket, &msg, iov, 2, len);
        if (ret < 0)
-               _debug("sendmsg failed: %d", ret);
+               trace_rxrpc_tx_fail(local->debug_id, 0, ret,
+                                   rxrpc_tx_fail_version_reply);
 
        _leave("");
 }
index 8b54e9531d52b63c0afd0989b1fbb641d147e6f3..b493e6b6274043e07b15c5a0481f0e92a4478ea4 100644 (file)
@@ -134,22 +134,49 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
                }
        }
 
-       /* we want to receive ICMP errors */
-       opt = 1;
-       ret = kernel_setsockopt(local->socket, SOL_IP, IP_RECVERR,
-                               (char *) &opt, sizeof(opt));
-       if (ret < 0) {
-               _debug("setsockopt failed");
-               goto error;
-       }
+       switch (local->srx.transport.family) {
+       case AF_INET:
+               /* we want to receive ICMP errors */
+               opt = 1;
+               ret = kernel_setsockopt(local->socket, SOL_IP, IP_RECVERR,
+                                       (char *) &opt, sizeof(opt));
+               if (ret < 0) {
+                       _debug("setsockopt failed");
+                       goto error;
+               }
 
-       /* we want to set the don't fragment bit */
-       opt = IP_PMTUDISC_DO;
-       ret = kernel_setsockopt(local->socket, SOL_IP, IP_MTU_DISCOVER,
-                               (char *) &opt, sizeof(opt));
-       if (ret < 0) {
-               _debug("setsockopt failed");
-               goto error;
+               /* we want to set the don't fragment bit */
+               opt = IP_PMTUDISC_DO;
+               ret = kernel_setsockopt(local->socket, SOL_IP, IP_MTU_DISCOVER,
+                                       (char *) &opt, sizeof(opt));
+               if (ret < 0) {
+                       _debug("setsockopt failed");
+                       goto error;
+               }
+               break;
+
+       case AF_INET6:
+               /* we want to receive ICMP errors */
+               opt = 1;
+               ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_RECVERR,
+                                       (char *) &opt, sizeof(opt));
+               if (ret < 0) {
+                       _debug("setsockopt failed");
+                       goto error;
+               }
+
+               /* we want to set the don't fragment bit */
+               opt = IPV6_PMTUDISC_DO;
+               ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_MTU_DISCOVER,
+                                       (char *) &opt, sizeof(opt));
+               if (ret < 0) {
+                       _debug("setsockopt failed");
+                       goto error;
+               }
+               break;
+
+       default:
+               BUG();
        }
 
        /* set the socket up */
index 7f1fc04775b34e5abd8e24a450ae386e74bf194a..f03de1c59ba37678f36f3a5c0778f3f3f9274757 100644 (file)
@@ -210,6 +210,9 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
        if (ping)
                call->ping_time = now;
        conn->params.peer->last_tx_at = ktime_get_real();
+       if (ret < 0)
+               trace_rxrpc_tx_fail(call->debug_id, serial, ret,
+                                   rxrpc_tx_fail_call_ack);
 
        if (call->state < RXRPC_CALL_COMPLETE) {
                if (ret < 0) {
@@ -294,6 +297,10 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call)
        ret = kernel_sendmsg(conn->params.local->socket,
                             &msg, iov, 1, sizeof(pkt));
        conn->params.peer->last_tx_at = ktime_get_real();
+       if (ret < 0)
+               trace_rxrpc_tx_fail(call->debug_id, serial, ret,
+                                   rxrpc_tx_fail_call_abort);
+
 
        rxrpc_put_connection(conn);
        return ret;
@@ -387,6 +394,9 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
        conn->params.peer->last_tx_at = ktime_get_real();
 
        up_read(&conn->params.local->defrag_sem);
+       if (ret < 0)
+               trace_rxrpc_tx_fail(call->debug_id, serial, ret,
+                                   rxrpc_tx_fail_call_data_nofrag);
        if (ret == -EMSGSIZE)
                goto send_fragmentable;
 
@@ -414,6 +424,17 @@ done:
                                                        rxrpc_timer_set_for_lost_ack);
                        }
                }
+
+               if (sp->hdr.seq == 1 &&
+                   !test_and_set_bit(RXRPC_CALL_BEGAN_RX_TIMER,
+                                     &call->flags)) {
+                       unsigned long nowj = jiffies, expect_rx_by;
+
+                       expect_rx_by = nowj + call->next_rx_timo;
+                       WRITE_ONCE(call->expect_rx_by, expect_rx_by);
+                       rxrpc_reduce_call_timer(call, expect_rx_by, nowj,
+                                               rxrpc_timer_set_for_normal);
+               }
        }
 
        rxrpc_set_keepalive(call);
@@ -465,6 +486,10 @@ send_fragmentable:
 #endif
        }
 
+       if (ret < 0)
+               trace_rxrpc_tx_fail(call->debug_id, serial, ret,
+                                   rxrpc_tx_fail_call_data_frag);
+
        up_write(&conn->params.local->defrag_sem);
        goto done;
 }
@@ -482,6 +507,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
        struct kvec iov[2];
        size_t size;
        __be32 code;
+       int ret;
 
        _enter("%d", local->debug_id);
 
@@ -516,7 +542,10 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
                        whdr.flags      ^= RXRPC_CLIENT_INITIATED;
                        whdr.flags      &= RXRPC_CLIENT_INITIATED;
 
-                       kernel_sendmsg(local->socket, &msg, iov, 2, size);
+                       ret = kernel_sendmsg(local->socket, &msg, iov, 2, size);
+                       if (ret < 0)
+                               trace_rxrpc_tx_fail(local->debug_id, 0, ret,
+                                                   rxrpc_tx_fail_reject);
                }
 
                rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
@@ -567,7 +596,8 @@ void rxrpc_send_keepalive(struct rxrpc_peer *peer)
 
        ret = kernel_sendmsg(peer->local->socket, &msg, iov, 2, len);
        if (ret < 0)
-               _debug("sendmsg failed: %d", ret);
+               trace_rxrpc_tx_fail(peer->debug_id, 0, ret,
+                                   rxrpc_tx_fail_version_keepalive);
 
        peer->last_tx_at = ktime_get_real();
        _leave("");
index 78c2f95d1f221c808d541f40121f75a3e5126091..0ed8b651cec293e121e40cf05282bddc8c3f1171 100644 (file)
@@ -28,39 +28,39 @@ static void rxrpc_store_error(struct rxrpc_peer *, struct sock_exterr_skb *);
  * Find the peer associated with an ICMP packet.
  */
 static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
-                                                    const struct sk_buff *skb)
+                                                    const struct sk_buff *skb,
+                                                    struct sockaddr_rxrpc *srx)
 {
        struct sock_exterr_skb *serr = SKB_EXT_ERR(skb);
-       struct sockaddr_rxrpc srx;
 
        _enter("");
 
-       memset(&srx, 0, sizeof(srx));
-       srx.transport_type = local->srx.transport_type;
-       srx.transport_len = local->srx.transport_len;
-       srx.transport.family = local->srx.transport.family;
+       memset(srx, 0, sizeof(*srx));
+       srx->transport_type = local->srx.transport_type;
+       srx->transport_len = local->srx.transport_len;
+       srx->transport.family = local->srx.transport.family;
 
        /* Can we see an ICMP4 packet on an ICMP6 listening socket?  and vice
         * versa?
         */
-       switch (srx.transport.family) {
+       switch (srx->transport.family) {
        case AF_INET:
-               srx.transport.sin.sin_port = serr->port;
+               srx->transport.sin.sin_port = serr->port;
                switch (serr->ee.ee_origin) {
                case SO_EE_ORIGIN_ICMP:
                        _net("Rx ICMP");
-                       memcpy(&srx.transport.sin.sin_addr,
+                       memcpy(&srx->transport.sin.sin_addr,
                               skb_network_header(skb) + serr->addr_offset,
                               sizeof(struct in_addr));
                        break;
                case SO_EE_ORIGIN_ICMP6:
                        _net("Rx ICMP6 on v4 sock");
-                       memcpy(&srx.transport.sin.sin_addr,
+                       memcpy(&srx->transport.sin.sin_addr,
                               skb_network_header(skb) + serr->addr_offset + 12,
                               sizeof(struct in_addr));
                        break;
                default:
-                       memcpy(&srx.transport.sin.sin_addr, &ip_hdr(skb)->saddr,
+                       memcpy(&srx->transport.sin.sin_addr, &ip_hdr(skb)->saddr,
                               sizeof(struct in_addr));
                        break;
                }
@@ -68,25 +68,25 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
 
 #ifdef CONFIG_AF_RXRPC_IPV6
        case AF_INET6:
-               srx.transport.sin6.sin6_port = serr->port;
+               srx->transport.sin6.sin6_port = serr->port;
                switch (serr->ee.ee_origin) {
                case SO_EE_ORIGIN_ICMP6:
                        _net("Rx ICMP6");
-                       memcpy(&srx.transport.sin6.sin6_addr,
+                       memcpy(&srx->transport.sin6.sin6_addr,
                               skb_network_header(skb) + serr->addr_offset,
                               sizeof(struct in6_addr));
                        break;
                case SO_EE_ORIGIN_ICMP:
                        _net("Rx ICMP on v6 sock");
-                       srx.transport.sin6.sin6_addr.s6_addr32[0] = 0;
-                       srx.transport.sin6.sin6_addr.s6_addr32[1] = 0;
-                       srx.transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
-                       memcpy(srx.transport.sin6.sin6_addr.s6_addr + 12,
+                       srx->transport.sin6.sin6_addr.s6_addr32[0] = 0;
+                       srx->transport.sin6.sin6_addr.s6_addr32[1] = 0;
+                       srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
+                       memcpy(srx->transport.sin6.sin6_addr.s6_addr + 12,
                               skb_network_header(skb) + serr->addr_offset,
                               sizeof(struct in_addr));
                        break;
                default:
-                       memcpy(&srx.transport.sin6.sin6_addr,
+                       memcpy(&srx->transport.sin6.sin6_addr,
                               &ipv6_hdr(skb)->saddr,
                               sizeof(struct in6_addr));
                        break;
@@ -98,7 +98,7 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
                BUG();
        }
 
-       return rxrpc_lookup_peer_rcu(local, &srx);
+       return rxrpc_lookup_peer_rcu(local, srx);
 }
 
 /*
@@ -146,6 +146,7 @@ static void rxrpc_adjust_mtu(struct rxrpc_peer *peer, struct sock_exterr_skb *se
 void rxrpc_error_report(struct sock *sk)
 {
        struct sock_exterr_skb *serr;
+       struct sockaddr_rxrpc srx;
        struct rxrpc_local *local = sk->sk_user_data;
        struct rxrpc_peer *peer;
        struct sk_buff *skb;
@@ -166,7 +167,7 @@ void rxrpc_error_report(struct sock *sk)
        }
 
        rcu_read_lock();
-       peer = rxrpc_lookup_peer_icmp_rcu(local, skb);
+       peer = rxrpc_lookup_peer_icmp_rcu(local, skb, &srx);
        if (peer && !rxrpc_get_peer_maybe(peer))
                peer = NULL;
        if (!peer) {
@@ -176,6 +177,8 @@ void rxrpc_error_report(struct sock *sk)
                return;
        }
 
+       trace_rxrpc_rx_icmp(peer, &serr->ee, &srx);
+
        if ((serr->ee.ee_origin == SO_EE_ORIGIN_ICMP &&
             serr->ee.ee_type == ICMP_DEST_UNREACH &&
             serr->ee.ee_code == ICMP_FRAG_NEEDED)) {
@@ -209,9 +212,6 @@ static void rxrpc_store_error(struct rxrpc_peer *peer,
 
        ee = &serr->ee;
 
-       _net("Rx Error o=%d t=%d c=%d e=%d",
-            ee->ee_origin, ee->ee_type, ee->ee_code, ee->ee_errno);
-
        err = ee->ee_errno;
 
        switch (ee->ee_origin) {
index 588fea0dd3627e5ea6515963d9eabebca603831e..6c0ae27fff84e2312bdc6a7f84abc7ed288e05de 100644 (file)
@@ -664,7 +664,8 @@ static int rxkad_issue_challenge(struct rxrpc_connection *conn)
 
        ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
        if (ret < 0) {
-               _debug("sendmsg failed: %d", ret);
+               trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
+                                   rxrpc_tx_fail_conn_challenge);
                return -EAGAIN;
        }
 
@@ -719,7 +720,8 @@ static int rxkad_send_response(struct rxrpc_connection *conn,
 
        ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 3, len);
        if (ret < 0) {
-               _debug("sendmsg failed: %d", ret);
+               trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
+                                   rxrpc_tx_fail_conn_response);
                return -EAGAIN;
        }
 
index 206e802ccbdc1a588ad26e13ff5f7e66afa6c4bb..be01f9c5d963ddfc766fac811ace9a381b89a7f7 100644 (file)
@@ -223,6 +223,15 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
 
        ret = rxrpc_send_data_packet(call, skb, false);
        if (ret < 0) {
+               switch (ret) {
+               case -ENETUNREACH:
+               case -EHOSTUNREACH:
+               case -ECONNREFUSED:
+                       rxrpc_set_call_completion(call,
+                                                 RXRPC_CALL_LOCAL_ERROR,
+                                                 0, ret);
+                       goto out;
+               }
                _debug("need instant resend %d", ret);
                rxrpc_instant_resend(call, ix);
        } else {
@@ -241,6 +250,7 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
                                        rxrpc_timer_set_for_send);
        }
 
+out:
        rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
        _leave("");
 }
index ddf69fc01bdf8913260b63adb6de0bbbdcf90b25..6138d1d71900b561f50578bf22110902bb488bf4 100644 (file)
@@ -121,7 +121,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
                return 0;
 
        if (!flags) {
-               tcf_idr_release(*a, bind);
+               if (exists)
+                       tcf_idr_release(*a, bind);
                return -EINVAL;
        }
 
index bbcbdce732cc010f1a0cee47f1d2f42066dcb200..ad050d7d4b46a2d45f85e15bb7e68d28915f1d54 100644 (file)
@@ -131,8 +131,11 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
        if (exists && bind)
                return 0;
 
-       if (!lflags)
+       if (!lflags) {
+               if (exists)
+                       tcf_idr_release(*a, bind);
                return -EINVAL;
+       }
 
        if (!exists) {
                ret = tcf_idr_create(tn, parm->index, est, a,
index b66754f52a9f1cfd18fbddb807a67f015b7c6f0c..963e4bf0aab8ae23d999305208c757fbc0f49ebe 100644 (file)
@@ -152,8 +152,8 @@ static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
                        NL_SET_ERR_MSG(extack, "TC classifier not found");
                        err = -ENOENT;
                }
-               goto errout;
 #endif
+               goto errout;
        }
        tp->classify = tp->ops->classify;
        tp->protocol = protocol;
index 837806dd57990af4b39147045f8eb53b5f34ec61..a47179da24e61f976616631df60b875d5f719ddd 100644 (file)
@@ -1024,8 +1024,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
        struct sctp_endpoint *ep;
        struct sctp_chunk *chunk;
        struct sctp_inq *inqueue;
-       int state;
+       int first_time = 1;     /* is this the first time through the loop */
        int error = 0;
+       int state;
 
        /* The association should be held so we should be safe. */
        ep = asoc->ep;
@@ -1036,6 +1037,30 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
                state = asoc->state;
                subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
 
+               /* If the first chunk in the packet is AUTH, do special
+                * processing specified in Section 6.3 of SCTP-AUTH spec
+                */
+               if (first_time && subtype.chunk == SCTP_CID_AUTH) {
+                       struct sctp_chunkhdr *next_hdr;
+
+                       next_hdr = sctp_inq_peek(inqueue);
+                       if (!next_hdr)
+                               goto normal;
+
+                       /* If the next chunk is COOKIE-ECHO, skip the AUTH
+                        * chunk while saving a pointer to it so we can do
+                        * Authentication later (during cookie-echo
+                        * processing).
+                        */
+                       if (next_hdr->type == SCTP_CID_COOKIE_ECHO) {
+                               chunk->auth_chunk = skb_clone(chunk->skb,
+                                                             GFP_ATOMIC);
+                               chunk->auth = 1;
+                               continue;
+                       }
+               }
+
+normal:
                /* SCTP-AUTH, Section 6.3:
                 *    The receiver has a list of chunk types which it expects
                 *    to be received only after an AUTH-chunk.  This list has
@@ -1074,6 +1099,9 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
                /* If there is an error on chunk, discard this packet. */
                if (error && chunk)
                        chunk->pdiscard = 1;
+
+               if (first_time)
+                       first_time = 0;
        }
        sctp_association_put(asoc);
 }
index 5a4fb1dc8400a0316177ce65be8126857297eb5e..e62addb60434a4438e773691198297f6c600af9d 100644 (file)
@@ -1152,7 +1152,7 @@ struct sctp_chunk *sctp_make_violation_max_retrans(
                                        const struct sctp_association *asoc,
                                        const struct sctp_chunk *chunk)
 {
-       static const char error[] = "Association exceeded its max_retans count";
+       static const char error[] = "Association exceeded its max_retrans count";
        size_t payload_len = sizeof(error) + sizeof(struct sctp_errhdr);
        struct sctp_chunk *retval;
 
index 28c070e187c2ed84fc531622a8090888207844ba..c9ae3404b1bb11572e34255cb3eae86ca1dd8131 100644 (file)
@@ -153,10 +153,7 @@ static enum sctp_disposition sctp_sf_violation_chunk(
                                        struct sctp_cmd_seq *commands);
 
 static enum sctp_ierror sctp_sf_authenticate(
-                                       struct net *net,
-                                       const struct sctp_endpoint *ep,
                                        const struct sctp_association *asoc,
-                                       const union sctp_subtype type,
                                        struct sctp_chunk *chunk);
 
 static enum sctp_disposition __sctp_sf_do_9_1_abort(
@@ -626,6 +623,38 @@ enum sctp_disposition sctp_sf_do_5_1C_ack(struct net *net,
        return SCTP_DISPOSITION_CONSUME;
 }
 
+static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk,
+                                  const struct sctp_association *asoc)
+{
+       struct sctp_chunk auth;
+
+       if (!chunk->auth_chunk)
+               return true;
+
+       /* SCTP-AUTH:  auth_chunk pointer is only set when the cookie-echo
+        * is supposed to be authenticated and we have to do delayed
+        * authentication.  We've just recreated the association using
+        * the information in the cookie and now it's much easier to
+        * do the authentication.
+        */
+
+       /* Make sure that we and the peer are AUTH capable */
+       if (!net->sctp.auth_enable || !asoc->peer.auth_capable)
+               return false;
+
+       /* set-up our fake chunk so that we can process it */
+       auth.skb = chunk->auth_chunk;
+       auth.asoc = chunk->asoc;
+       auth.sctp_hdr = chunk->sctp_hdr;
+       auth.chunk_hdr = (struct sctp_chunkhdr *)
+                               skb_push(chunk->auth_chunk,
+                                        sizeof(struct sctp_chunkhdr));
+       skb_pull(chunk->auth_chunk, sizeof(struct sctp_chunkhdr));
+       auth.transport = chunk->transport;
+
+       return sctp_sf_authenticate(asoc, &auth) == SCTP_IERROR_NO_ERROR;
+}
+
 /*
  * Respond to a normal COOKIE ECHO chunk.
  * We are the side that is being asked for an association.
@@ -763,37 +792,9 @@ enum sctp_disposition sctp_sf_do_5_1D_ce(struct net *net,
        if (error)
                goto nomem_init;
 
-       /* SCTP-AUTH:  auth_chunk pointer is only set when the cookie-echo
-        * is supposed to be authenticated and we have to do delayed
-        * authentication.  We've just recreated the association using
-        * the information in the cookie and now it's much easier to
-        * do the authentication.
-        */
-       if (chunk->auth_chunk) {
-               struct sctp_chunk auth;
-               enum sctp_ierror ret;
-
-               /* Make sure that we and the peer are AUTH capable */
-               if (!net->sctp.auth_enable || !new_asoc->peer.auth_capable) {
-                       sctp_association_free(new_asoc);
-                       return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
-               }
-
-               /* set-up our fake chunk so that we can process it */
-               auth.skb = chunk->auth_chunk;
-               auth.asoc = chunk->asoc;
-               auth.sctp_hdr = chunk->sctp_hdr;
-               auth.chunk_hdr = (struct sctp_chunkhdr *)
-                                       skb_push(chunk->auth_chunk,
-                                                sizeof(struct sctp_chunkhdr));
-               skb_pull(chunk->auth_chunk, sizeof(struct sctp_chunkhdr));
-               auth.transport = chunk->transport;
-
-               ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth);
-               if (ret != SCTP_IERROR_NO_ERROR) {
-                       sctp_association_free(new_asoc);
-                       return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
-               }
+       if (!sctp_auth_chunk_verify(net, chunk, new_asoc)) {
+               sctp_association_free(new_asoc);
+               return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands);
        }
 
        repl = sctp_make_cookie_ack(new_asoc, chunk);
@@ -1797,13 +1798,15 @@ static enum sctp_disposition sctp_sf_do_dupcook_a(
        if (sctp_auth_asoc_init_active_key(new_asoc, GFP_ATOMIC))
                goto nomem;
 
+       if (!sctp_auth_chunk_verify(net, chunk, new_asoc))
+               return SCTP_DISPOSITION_DISCARD;
+
        /* Make sure no new addresses are being added during the
         * restart.  Though this is a pretty complicated attack
         * since you'd have to get inside the cookie.
         */
-       if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) {
+       if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands))
                return SCTP_DISPOSITION_CONSUME;
-       }
 
        /* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes
         * the peer has restarted (Action A), it MUST NOT setup a new
@@ -1912,6 +1915,9 @@ static enum sctp_disposition sctp_sf_do_dupcook_b(
        if (sctp_auth_asoc_init_active_key(new_asoc, GFP_ATOMIC))
                goto nomem;
 
+       if (!sctp_auth_chunk_verify(net, chunk, new_asoc))
+               return SCTP_DISPOSITION_DISCARD;
+
        /* Update the content of current association.  */
        sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
        sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
@@ -2009,6 +2015,9 @@ static enum sctp_disposition sctp_sf_do_dupcook_d(
         * a COOKIE ACK.
         */
 
+       if (!sctp_auth_chunk_verify(net, chunk, asoc))
+               return SCTP_DISPOSITION_DISCARD;
+
        /* Don't accidentally move back into established state. */
        if (asoc->state < SCTP_STATE_ESTABLISHED) {
                sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
@@ -4171,10 +4180,7 @@ gen_shutdown:
  * The return value is the disposition of the chunk.
  */
 static enum sctp_ierror sctp_sf_authenticate(
-                                       struct net *net,
-                                       const struct sctp_endpoint *ep,
                                        const struct sctp_association *asoc,
-                                       const union sctp_subtype type,
                                        struct sctp_chunk *chunk)
 {
        struct sctp_shared_key *sh_key = NULL;
@@ -4275,7 +4281,7 @@ enum sctp_disposition sctp_sf_eat_auth(struct net *net,
                                                  commands);
 
        auth_hdr = (struct sctp_authhdr *)chunk->skb->data;
-       error = sctp_sf_authenticate(net, ep, asoc, type, chunk);
+       error = sctp_sf_authenticate(asoc, chunk);
        switch (error) {
        case SCTP_IERROR_AUTH_BAD_HMAC:
                /* Generate the ERROR chunk and discard the rest
index 84207ad33e8e9270d0fa1ddf61a514cc9315656d..8cb7d9858270a617e46e32e988babf86196ef84c 100644 (file)
@@ -715,7 +715,6 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
        return event;
 
 fail_mark:
-       sctp_chunk_put(chunk);
        kfree_skb(skb);
 fail:
        return NULL;
index 5cc68a824f451b16d66a88c7cb43f2d16628ea38..f2f63959fddd3f5b6610fb9e566f06f42e5377b1 100644 (file)
@@ -72,6 +72,7 @@ fmr_op_init_mr(struct rpcrdma_ia *ia, struct rpcrdma_mr *mr)
        if (IS_ERR(mr->fmr.fm_mr))
                goto out_fmr_err;
 
+       INIT_LIST_HEAD(&mr->mr_list);
        return 0;
 
 out_fmr_err:
@@ -102,10 +103,6 @@ fmr_op_release_mr(struct rpcrdma_mr *mr)
        LIST_HEAD(unmap_list);
        int rc;
 
-       /* Ensure MW is not on any rl_registered list */
-       if (!list_empty(&mr->mr_list))
-               list_del(&mr->mr_list);
-
        kfree(mr->fmr.fm_physaddrs);
        kfree(mr->mr_sg);
 
index c5743a0960be46a10a67b6021ab5332d9a0b37a8..c59c5c788db0e8478ef06a7d7615dd2e813ef395 100644 (file)
@@ -110,6 +110,7 @@ frwr_op_init_mr(struct rpcrdma_ia *ia, struct rpcrdma_mr *mr)
        if (!mr->mr_sg)
                goto out_list_err;
 
+       INIT_LIST_HEAD(&mr->mr_list);
        sg_init_table(mr->mr_sg, depth);
        init_completion(&frwr->fr_linv_done);
        return 0;
@@ -133,10 +134,6 @@ frwr_op_release_mr(struct rpcrdma_mr *mr)
 {
        int rc;
 
-       /* Ensure MR is not on any rl_registered list */
-       if (!list_empty(&mr->mr_list))
-               list_del(&mr->mr_list);
-
        rc = ib_dereg_mr(mr->frwr.fr_mr);
        if (rc)
                pr_err("rpcrdma: final ib_dereg_mr for %p returned %i\n",
@@ -195,7 +192,7 @@ frwr_op_recover_mr(struct rpcrdma_mr *mr)
        return;
 
 out_release:
-       pr_err("rpcrdma: FRWR reset failed %d, %p release\n", rc, mr);
+       pr_err("rpcrdma: FRWR reset failed %d, %p released\n", rc, mr);
        r_xprt->rx_stats.mrs_orphaned++;
 
        spin_lock(&r_xprt->rx_buf.rb_mrlock);
@@ -476,7 +473,7 @@ frwr_op_reminv(struct rpcrdma_rep *rep, struct list_head *mrs)
 
        list_for_each_entry(mr, mrs, mr_list)
                if (mr->mr_handle == rep->rr_inv_rkey) {
-                       list_del(&mr->mr_list);
+                       list_del_init(&mr->mr_list);
                        trace_xprtrdma_remoteinv(mr);
                        mr->frwr.fr_state = FRWR_IS_INVALID;
                        rpcrdma_mr_unmap_and_put(mr);
index fe5eaca2d19744df58f0e240766048d4a8be25e9..c345d365af886514d61c35c79291718a77f155e7 100644 (file)
@@ -1254,6 +1254,11 @@ rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf)
                list_del(&mr->mr_all);
 
                spin_unlock(&buf->rb_mrlock);
+
+               /* Ensure MW is not on any rl_registered list */
+               if (!list_empty(&mr->mr_list))
+                       list_del(&mr->mr_list);
+
                ia->ri_ops->ro_release_mr(mr);
                count++;
                spin_lock(&buf->rb_mrlock);
index 3d3b423fa9c1d3a9cf8497d109c25599042bea68..cb41b12a3bf8d985ae155d7977cb69f043af4f1c 100644 (file)
@@ -380,7 +380,7 @@ rpcrdma_mr_pop(struct list_head *list)
        struct rpcrdma_mr *mr;
 
        mr = list_first_entry(list, struct rpcrdma_mr, mr_list);
-       list_del(&mr->mr_list);
+       list_del_init(&mr->mr_list);
        return mr;
 }
 
index baaf93f12cbd0de5b4ce002ac0bcbc818f7d03ac..f29549de9245f63229241cd63f798a114182b0f5 100644 (file)
@@ -1950,6 +1950,7 @@ out:
 int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info)
 {
        struct net *net = genl_info_net(info);
+       struct nlattr *attrs[TIPC_NLA_LINK_MAX + 1];
        struct tipc_nl_msg msg;
        char *name;
        int err;
@@ -1957,9 +1958,19 @@ int tipc_nl_node_get_link(struct sk_buff *skb, struct genl_info *info)
        msg.portid = info->snd_portid;
        msg.seq = info->snd_seq;
 
-       if (!info->attrs[TIPC_NLA_LINK_NAME])
+       if (!info->attrs[TIPC_NLA_LINK])
                return -EINVAL;
-       name = nla_data(info->attrs[TIPC_NLA_LINK_NAME]);
+
+       err = nla_parse_nested(attrs, TIPC_NLA_LINK_MAX,
+                              info->attrs[TIPC_NLA_LINK],
+                              tipc_nl_link_policy, info->extack);
+       if (err)
+               return err;
+
+       if (!attrs[TIPC_NLA_LINK_NAME])
+               return -EINVAL;
+
+       name = nla_data(attrs[TIPC_NLA_LINK_NAME]);
 
        msg.skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
        if (!msg.skb)
index 252a52ae0893261fc6f146ad81111c59f375fdce..6be21575503aa532014e7aa1415b2bf294757308 100644 (file)
@@ -1516,10 +1516,10 @@ static void tipc_sk_set_orig_addr(struct msghdr *m, struct sk_buff *skb)
 
        srcaddr->sock.family = AF_TIPC;
        srcaddr->sock.addrtype = TIPC_ADDR_ID;
+       srcaddr->sock.scope = 0;
        srcaddr->sock.addr.id.ref = msg_origport(hdr);
        srcaddr->sock.addr.id.node = msg_orignode(hdr);
        srcaddr->sock.addr.name.domain = 0;
-       srcaddr->sock.scope = 0;
        m->msg_namelen = sizeof(struct sockaddr_tipc);
 
        if (!msg_in_group(hdr))
@@ -1528,6 +1528,7 @@ static void tipc_sk_set_orig_addr(struct msghdr *m, struct sk_buff *skb)
        /* Group message users may also want to know sending member's id */
        srcaddr->member.family = AF_TIPC;
        srcaddr->member.addrtype = TIPC_ADDR_NAME;
+       srcaddr->member.scope = 0;
        srcaddr->member.addr.name.name.type = msg_nametype(hdr);
        srcaddr->member.addr.name.name.instance = TIPC_SKB_CB(skb)->orig_member;
        srcaddr->member.addr.name.domain = 0;
index cc03e00785c7ffefc8c37cac39aecc7e28cc86f9..20cd93be6236e03e2fbdbfc9e44cbb12d3261c84 100644 (file)
@@ -135,6 +135,7 @@ retry:
                        offset -= sg->offset;
                        ctx->partially_sent_offset = offset;
                        ctx->partially_sent_record = (void *)sg;
+                       ctx->in_tcp_sendpages = false;
                        return ret;
                }
 
@@ -248,16 +249,13 @@ static void tls_sk_proto_close(struct sock *sk, long timeout)
        struct tls_context *ctx = tls_get_ctx(sk);
        long timeo = sock_sndtimeo(sk, 0);
        void (*sk_proto_close)(struct sock *sk, long timeout);
+       bool free_ctx = false;
 
        lock_sock(sk);
        sk_proto_close = ctx->sk_proto_close;
 
-       if (ctx->conf == TLS_HW_RECORD)
-               goto skip_tx_cleanup;
-
-       if (ctx->conf == TLS_BASE) {
-               kfree(ctx);
-               ctx = NULL;
+       if (ctx->conf == TLS_BASE || ctx->conf == TLS_HW_RECORD) {
+               free_ctx = true;
                goto skip_tx_cleanup;
        }
 
@@ -294,7 +292,7 @@ skip_tx_cleanup:
        /* free ctx for TLS_HW_RECORD, used by tcp_set_state
         * for sk->sk_prot->unhash [tls_hw_unhash]
         */
-       if (ctx && ctx->conf == TLS_HW_RECORD)
+       if (free_ctx)
                kfree(ctx);
 }
 
index a6f3cac8c640e4cdb0eb4fb9d3c77bf3fd352576..c0fd8a85e7f72e59fa8e93be41a4dee1ee0a5104 100644 (file)
@@ -95,6 +95,9 @@ static int cfg80211_dev_check_name(struct cfg80211_registered_device *rdev,
 
        ASSERT_RTNL();
 
+       if (strlen(newname) > NL80211_WIPHY_NAME_MAXLEN)
+               return -EINVAL;
+
        /* prohibit calling the thing phy%d when %d is not its number */
        sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
        if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) {
index ff28f8feeb09270296bab5b086e928cc3a76bea0..a052693c2e852b856f96d304cb97b6ddd0ff5319 100644 (file)
@@ -9214,6 +9214,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
 
        if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
                if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
+                       kzfree(connkeys);
                        GENL_SET_ERR_MSG(info,
                                         "external auth requires connection ownership");
                        return -EINVAL;
index 16c7e4ef58207cc781b80ef9bb3242ead81001a0..ac3e12c32aa30053a110d6a46f5bb813d660c8b6 100644 (file)
@@ -1026,6 +1026,7 @@ static int regdb_query_country(const struct fwdb_header *db,
 
                        if (!tmp_rd) {
                                kfree(regdom);
+                               kfree(wmm_ptrs);
                                return -ENOMEM;
                        }
                        regdom = tmp_rd;
index f9d2f2233f09531697b35209fe86754d23971e3f..6c177ae7a6d92ff90966fe9895b4a9b69cc892ae 100644 (file)
@@ -2175,6 +2175,12 @@ struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
        return afinfo;
 }
 
+void xfrm_flush_gc(void)
+{
+       flush_work(&xfrm_state_gc_work);
+}
+EXPORT_SYMBOL(xfrm_flush_gc);
+
 /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
 void xfrm_state_delete_tunnel(struct xfrm_state *x)
 {
index c07ba4da9e36119bfb5c8732f5b2178a46b09997..815eaf140ab5c0724a27df752d92a49402022e0b 100644 (file)
@@ -787,10 +787,9 @@ static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *
                FAIL(c, dti, node, "incorrect #size-cells for PCI bridge");
 
        prop = get_property(node, "bus-range");
-       if (!prop) {
-               FAIL(c, dti, node, "missing bus-range for PCI bridge");
+       if (!prop)
                return;
-       }
+
        if (prop->val.len != (sizeof(cell_t) * 2)) {
                FAIL_PROP(c, dti, node, prop, "value must be 2 cells");
                return;
index 9e5735a4d3a57bf910ae2441a00a083e865f4136..1876a741087cc531645f4dc5383a7a234de6f5bd 100755 (executable)
@@ -170,7 +170,10 @@ __faddr2line() {
                echo "$file_lines" | while read -r line
                do
                        echo $line
-                       eval $(echo $line | awk -F "[ :]" '{printf("n1=%d;n2=%d;f=%s",$NF-5, $NF+5, $(NF-1))}')
+                       n=$(echo $line | sed 's/.*:\([0-9]\+\).*/\1/g')
+                       n1=$[$n-5]
+                       n2=$[$n+5]
+                       f=$(echo $line | sed 's/.*at \(.\+\):.*/\1/g')
                        awk 'NR>=strtonum("'$n1'") && NR<=strtonum("'$n2'") {printf("%d\t%s\n", NR, $0)}' $f
                done
 
index 4cafe6a19167613cb64b29ac59c895e91285b390..be5817df0a9d98eab91b059d814f27322d8e7665 100644 (file)
@@ -4576,6 +4576,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
 static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
 {
        struct sock *sk = sock->sk;
+       struct sk_security_struct *sksec = sk->sk_security;
        u16 family;
        int err;
 
@@ -4587,11 +4588,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
        family = sk->sk_family;
        if (family == PF_INET || family == PF_INET6) {
                char *addrp;
-               struct sk_security_struct *sksec = sk->sk_security;
                struct common_audit_data ad;
                struct lsm_network_audit net = {0,};
                struct sockaddr_in *addr4 = NULL;
                struct sockaddr_in6 *addr6 = NULL;
+               u16 family_sa = address->sa_family;
                unsigned short snum;
                u32 sid, node_perm;
 
@@ -4601,11 +4602,20 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                 * need to check address->sa_family as it is possible to have
                 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
                 */
-               switch (address->sa_family) {
+               switch (family_sa) {
+               case AF_UNSPEC:
                case AF_INET:
                        if (addrlen < sizeof(struct sockaddr_in))
                                return -EINVAL;
                        addr4 = (struct sockaddr_in *)address;
+                       if (family_sa == AF_UNSPEC) {
+                               /* see __inet_bind(), we only want to allow
+                                * AF_UNSPEC if the address is INADDR_ANY
+                                */
+                               if (addr4->sin_addr.s_addr != htonl(INADDR_ANY))
+                                       goto err_af;
+                               family_sa = AF_INET;
+                       }
                        snum = ntohs(addr4->sin_port);
                        addrp = (char *)&addr4->sin_addr.s_addr;
                        break;
@@ -4617,15 +4627,14 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                        addrp = (char *)&addr6->sin6_addr.s6_addr;
                        break;
                default:
-                       /* Note that SCTP services expect -EINVAL, whereas
-                        * others expect -EAFNOSUPPORT.
-                        */
-                       if (sksec->sclass == SECCLASS_SCTP_SOCKET)
-                               return -EINVAL;
-                       else
-                               return -EAFNOSUPPORT;
+                       goto err_af;
                }
 
+               ad.type = LSM_AUDIT_DATA_NET;
+               ad.u.net = &net;
+               ad.u.net->sport = htons(snum);
+               ad.u.net->family = family_sa;
+
                if (snum) {
                        int low, high;
 
@@ -4637,10 +4646,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                                                      snum, &sid);
                                if (err)
                                        goto out;
-                               ad.type = LSM_AUDIT_DATA_NET;
-                               ad.u.net = &net;
-                               ad.u.net->sport = htons(snum);
-                               ad.u.net->family = family;
                                err = avc_has_perm(&selinux_state,
                                                   sksec->sid, sid,
                                                   sksec->sclass,
@@ -4672,16 +4677,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                        break;
                }
 
-               err = sel_netnode_sid(addrp, family, &sid);
+               err = sel_netnode_sid(addrp, family_sa, &sid);
                if (err)
                        goto out;
 
-               ad.type = LSM_AUDIT_DATA_NET;
-               ad.u.net = &net;
-               ad.u.net->sport = htons(snum);
-               ad.u.net->family = family;
-
-               if (address->sa_family == AF_INET)
+               if (family_sa == AF_INET)
                        ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
                else
                        ad.u.net->v6info.saddr = addr6->sin6_addr;
@@ -4694,6 +4694,11 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
        }
 out:
        return err;
+err_af:
+       /* Note that SCTP services expect -EINVAL, others -EAFNOSUPPORT. */
+       if (sksec->sclass == SECCLASS_SCTP_SOCKET)
+               return -EINVAL;
+       return -EAFNOSUPPORT;
 }
 
 /* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
@@ -4771,7 +4776,7 @@ static int selinux_socket_connect_helper(struct socket *sock,
                ad.type = LSM_AUDIT_DATA_NET;
                ad.u.net = &net;
                ad.u.net->dport = htons(snum);
-               ad.u.net->family = sk->sk_family;
+               ad.u.net->family = address->sa_family;
                err = avc_has_perm(&selinux_state,
                                   sksec->sid, sid, sksec->sclass, perm, &ad);
                if (err)
@@ -5272,6 +5277,7 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
        while (walk_size < addrlen) {
                addr = addr_buf;
                switch (addr->sa_family) {
+               case AF_UNSPEC:
                case AF_INET:
                        len = sizeof(struct sockaddr_in);
                        break;
@@ -5279,7 +5285,7 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
                        len = sizeof(struct sockaddr_in6);
                        break;
                default:
-                       return -EAFNOSUPPORT;
+                       return -EINVAL;
                }
 
                err = -EINVAL;
index a848836a5de0468534d5eecfd24adf4bc743f9f2..507fd5210c1cd54d764e718ab00c7c657857ad6c 100644 (file)
@@ -396,8 +396,7 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
        if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) ||
            copy_from_user(&data->type, &data32->type, 3 * sizeof(u32)))
                goto error;
-       if (get_user(data->owner, &data32->owner) ||
-           get_user(data->type, &data32->type))
+       if (get_user(data->owner, &data32->owner))
                goto error;
        switch (data->type) {
        case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
index b0c8c79848a94fd9aae962207ed1c673e0d815ed..a0c93b9c9a283684ce1894c6d963c7917e4651d0 100644 (file)
@@ -2210,6 +2210,8 @@ static struct snd_pci_quirk power_save_blacklist[] = {
        SND_PCI_QUIRK(0x1849, 0x0c0c, "Asrock B85M-ITX", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0),
+       /* https://bugzilla.redhat.com/show_bug.cgi?id=1572975 */
+       SND_PCI_QUIRK(0x17aa, 0x36a7, "Lenovo C50 All in one", 0),
        /* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */
        SND_PCI_QUIRK(0x17aa, 0x2227, "Lenovo X1 Carbon 3rd Gen", 0),
        {}
index 2dd34dd7744788d507bfc4b3f7c3b1168a7fa959..01a6643fc7d4727818f5335a04b91f2ab45e4f29 100644 (file)
@@ -2363,6 +2363,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
        SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
index 344d7b069d5994ff242a9f0a3f9bf19f4201ffaa..bb5ab7a7dfa58b0d21cb08acfeff2cca29ba7865 100644 (file)
@@ -967,6 +967,14 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
                }
                break;
 
+       case USB_ID(0x0d8c, 0x0103):
+               if (!strcmp(kctl->id.name, "PCM Playback Volume")) {
+                       usb_audio_info(chip,
+                                "set volume quirk for CM102-A+/102S+\n");
+                       cval->min = -256;
+               }
+               break;
+
        case USB_ID(0x0471, 0x0101):
        case USB_ID(0x0471, 0x0104):
        case USB_ID(0x0471, 0x0105):
index 956be9f7c72a44e9326bd15c3df328540747124d..5ed334575fc73cd7f184a9be450f555f190a4d61 100644 (file)
@@ -576,7 +576,7 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
 
        if (protocol == UAC_VERSION_1) {
                attributes = csep->bmAttributes;
-       } else {
+       } else if (protocol == UAC_VERSION_2) {
                struct uac2_iso_endpoint_descriptor *csep2 =
                        (struct uac2_iso_endpoint_descriptor *) csep;
 
@@ -585,6 +585,13 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
                /* emulate the endpoint attributes of a v1 device */
                if (csep2->bmControls & UAC2_CONTROL_PITCH)
                        attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
+       } else { /* UAC_VERSION_3 */
+               struct uac3_iso_endpoint_descriptor *csep3 =
+                       (struct uac3_iso_endpoint_descriptor *) csep;
+
+               /* emulate the endpoint attributes of a v1 device */
+               if (le32_to_cpu(csep3->bmControls) & UAC2_CONTROL_PITCH)
+                       attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
        }
 
        return attributes;
index 2ba95d6fe852d7bed7460b022f1ed5b8409caacd..caae4843cb7001fbee1fa9b222850df7006850fb 100644 (file)
@@ -195,6 +195,12 @@ struct kvm_arch_memory_slot {
 #define KVM_REG_ARM_VFP_FPINST         0x1009
 #define KVM_REG_ARM_VFP_FPINST2                0x100A
 
+/* KVM-as-firmware specific pseudo-registers */
+#define KVM_REG_ARM_FW                 (0x0014 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_FW_REG(r)          (KVM_REG_ARM | KVM_REG_SIZE_U64 | \
+                                        KVM_REG_ARM_FW | ((r) & 0xffff))
+#define KVM_REG_ARM_PSCI_VERSION       KVM_REG_ARM_FW_REG(0)
+
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR      0
 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
index 9abbf30446545a0668083b0891461f015563bcb1..04b3256f8e6d5f8e3e368b043f0fdcfeb7c23164 100644 (file)
@@ -206,6 +206,12 @@ struct kvm_arch_memory_slot {
 #define KVM_REG_ARM_TIMER_CNT          ARM64_SYS_REG(3, 3, 14, 3, 2)
 #define KVM_REG_ARM_TIMER_CVAL         ARM64_SYS_REG(3, 3, 14, 0, 2)
 
+/* KVM-as-firmware specific pseudo-registers */
+#define KVM_REG_ARM_FW                 (0x0014 << KVM_REG_ARM_COPROC_SHIFT)
+#define KVM_REG_ARM_FW_REG(r)          (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
+                                        KVM_REG_ARM_FW | ((r) & 0xffff))
+#define KVM_REG_ARM_PSCI_VERSION       KVM_REG_ARM_FW_REG(0)
+
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR      0
 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
index d554c11e01ff46742d53148df0ffb9c3476e8d6e..578793e97431da25b0d5f3cbc20ae4c0655db075 100644 (file)
 #define X86_FEATURE_AVX512_VPOPCNTDQ   (16*32+14) /* POPCNT for vectors of DW/QW */
 #define X86_FEATURE_LA57               (16*32+16) /* 5-level page tables */
 #define X86_FEATURE_RDPID              (16*32+22) /* RDPID instruction */
+#define X86_FEATURE_CLDEMOTE           (16*32+25) /* CLDEMOTE instruction */
 
 /* AMD-defined CPU features, CPUID level 0x80000007 (EBX), word 17 */
 #define X86_FEATURE_OVERFLOW_RECOV     (17*32+ 0) /* MCA overflow recovery support */
index b21b586b985424a03338023f96a3e9e3d996b2af..1738c0391da4af73793716edb2d1109726c690f9 100644 (file)
@@ -6,8 +6,9 @@
 #include <stdbool.h>
 
 #define spinlock_t             pthread_mutex_t
-#define DEFINE_SPINLOCK(x)     pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER;
+#define DEFINE_SPINLOCK(x)     pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER
 #define __SPIN_LOCK_UNLOCKED(x)        (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER
+#define spin_lock_init(x)      pthread_mutex_init(x, NULL)
 
 #define spin_lock_irqsave(x, f)                (void)f, pthread_mutex_lock(x)
 #define spin_unlock_irqrestore(x, f)   (void)f, pthread_mutex_unlock(x)
index 1065006c9bf5890abdf99f9a4c444552af5542d1..b02c41e53d5616a3124e16dbec17250654a790b4 100644 (file)
@@ -676,6 +676,13 @@ struct kvm_ioeventfd {
        __u8  pad[36];
 };
 
+#define KVM_X86_DISABLE_EXITS_MWAIT          (1 << 0)
+#define KVM_X86_DISABLE_EXITS_HTL            (1 << 1)
+#define KVM_X86_DISABLE_EXITS_PAUSE          (1 << 2)
+#define KVM_X86_DISABLE_VALID_EXITS          (KVM_X86_DISABLE_EXITS_MWAIT | \
+                                              KVM_X86_DISABLE_EXITS_HTL | \
+                                              KVM_X86_DISABLE_EXITS_PAUSE)
+
 /* for KVM_ENABLE_CAP */
 struct kvm_enable_cap {
        /* in */
index 944070e98a2cd9dc4903e3be02278b1a7f8f3500..63eb49082774c94dfbabe7a18db73bdc2403fb6a 100644 (file)
@@ -175,7 +175,7 @@ static const struct option options[] = {
        OPT_UINTEGER('s', "nr_secs"     , &p0.nr_secs,          "max number of seconds to run (default: 5 secs)"),
        OPT_UINTEGER('u', "usleep"      , &p0.sleep_usecs,      "usecs to sleep per loop iteration"),
 
-       OPT_BOOLEAN('R', "data_reads"   , &p0.data_reads,       "access the data via writes (can be mixed with -W)"),
+       OPT_BOOLEAN('R', "data_reads"   , &p0.data_reads,       "access the data via reads (can be mixed with -W)"),
        OPT_BOOLEAN('W', "data_writes"  , &p0.data_writes,      "access the data via writes (can be mixed with -R)"),
        OPT_BOOLEAN('B', "data_backwards", &p0.data_backwards,  "access the data backwards as well"),
        OPT_BOOLEAN('Z', "data_zero_memset", &p0.data_zero_memset,"access the data via glibc bzero only"),
index 93656f2fd53a025a23ad88183bfc6da9e96023b1..7e3cce3bcf3b8c69bb0553c4caf700b81bb2e1bd 100644 (file)
@@ -29,7 +29,6 @@ GenuineIntel-6-4D,v13,silvermont,core
 GenuineIntel-6-4C,v13,silvermont,core
 GenuineIntel-6-2A,v15,sandybridge,core
 GenuineIntel-6-2C,v2,westmereep-dp,core
-GenuineIntel-6-2C,v2,westmereep-dp,core
 GenuineIntel-6-25,v2,westmereep-sp,core
 GenuineIntel-6-2F,v2,westmereex,core
 GenuineIntel-6-55,v1,skylakex,core
index d14464c42714b84d738e151eb9a71d4269cc37ab..7afeb80cc39eed61632940ea163165a6f7a11da7 100644 (file)
@@ -224,15 +224,15 @@ event_def: event_pmu |
           event_bpf_file
 
 event_pmu:
-PE_NAME '/' event_config '/'
+PE_NAME opt_event_config
 {
        struct list_head *list, *orig_terms, *terms;
 
-       if (parse_events_copy_term_list($3, &orig_terms))
+       if (parse_events_copy_term_list($2, &orig_terms))
                YYABORT;
 
        ALLOC_LIST(list);
-       if (parse_events_add_pmu(_parse_state, list, $1, $3, false)) {
+       if (parse_events_add_pmu(_parse_state, list, $1, $2, false)) {
                struct perf_pmu *pmu = NULL;
                int ok = 0;
                char *pattern;
@@ -262,7 +262,7 @@ PE_NAME '/' event_config '/'
                if (!ok)
                        YYABORT;
        }
-       parse_events_terms__delete($3);
+       parse_events_terms__delete($2);
        parse_events_terms__delete(orig_terms);
        $$ = list;
 }
index fa7ee369b3c919c534e610a621c1bdd54bf1e986..db66f8a0d4bed71aa581cdbf82c9acf422daef05 100644 (file)
@@ -17,7 +17,7 @@ ifeq ($(BUILD), 32)
        LDFLAGS += -m32
 endif
 
-targets: mapshift $(TARGETS)
+targets: generated/map-shift.h $(TARGETS)
 
 main:  $(OFILES)
 
@@ -42,9 +42,7 @@ radix-tree.c: ../../../lib/radix-tree.c
 idr.c: ../../../lib/idr.c
        sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@
 
-.PHONY: mapshift
-
-mapshift:
+generated/map-shift.h:
        @if ! grep -qws $(SHIFT) generated/map-shift.h; then            \
                echo "#define RADIX_TREE_MAP_SHIFT $(SHIFT)" >          \
                                generated/map-shift.h;                  \
index 59245b3d587c35c039c77e673bdd706319368167..7bf405638b0beef5d7ca578645e4918c02c06560 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/radix-tree.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
+#include <pthread.h>
 
 #include "test.h"
 
@@ -624,6 +625,67 @@ static void multiorder_account(void)
        item_kill_tree(&tree);
 }
 
+bool stop_iteration = false;
+
+static void *creator_func(void *ptr)
+{
+       /* 'order' is set up to ensure we have sibling entries */
+       unsigned int order = RADIX_TREE_MAP_SHIFT - 1;
+       struct radix_tree_root *tree = ptr;
+       int i;
+
+       for (i = 0; i < 10000; i++) {
+               item_insert_order(tree, 0, order);
+               item_delete_rcu(tree, 0);
+       }
+
+       stop_iteration = true;
+       return NULL;
+}
+
+static void *iterator_func(void *ptr)
+{
+       struct radix_tree_root *tree = ptr;
+       struct radix_tree_iter iter;
+       struct item *item;
+       void **slot;
+
+       while (!stop_iteration) {
+               rcu_read_lock();
+               radix_tree_for_each_slot(slot, tree, &iter, 0) {
+                       item = radix_tree_deref_slot(slot);
+
+                       if (!item)
+                               continue;
+                       if (radix_tree_deref_retry(item)) {
+                               slot = radix_tree_iter_retry(&iter);
+                               continue;
+                       }
+
+                       item_sanity(item, iter.index);
+               }
+               rcu_read_unlock();
+       }
+       return NULL;
+}
+
+static void multiorder_iteration_race(void)
+{
+       const int num_threads = sysconf(_SC_NPROCESSORS_ONLN);
+       pthread_t worker_thread[num_threads];
+       RADIX_TREE(tree, GFP_KERNEL);
+       int i;
+
+       pthread_create(&worker_thread[0], NULL, &creator_func, &tree);
+       for (i = 1; i < num_threads; i++)
+               pthread_create(&worker_thread[i], NULL, &iterator_func, &tree);
+
+       for (i = 0; i < num_threads; i++)
+               pthread_join(worker_thread[i], NULL);
+
+       item_kill_tree(&tree);
+}
+
 void multiorder_checks(void)
 {
        int i;
@@ -644,6 +706,7 @@ void multiorder_checks(void)
        multiorder_join();
        multiorder_split();
        multiorder_account();
+       multiorder_iteration_race();
 
        radix_tree_cpu_dead(0);
 }
index 5978ab1f403d97f135ae7f026a07caab71113212..def6015570b22a46274cd51b6f2135c6b6157090 100644 (file)
@@ -75,6 +75,25 @@ int item_delete(struct radix_tree_root *root, unsigned long index)
        return 0;
 }
 
+static void item_free_rcu(struct rcu_head *head)
+{
+       struct item *item = container_of(head, struct item, rcu_head);
+
+       free(item);
+}
+
+int item_delete_rcu(struct radix_tree_root *root, unsigned long index)
+{
+       struct item *item = radix_tree_delete(root, index);
+
+       if (item) {
+               item_sanity(item, index);
+               call_rcu(&item->rcu_head, item_free_rcu);
+               return 1;
+       }
+       return 0;
+}
+
 void item_check_present(struct radix_tree_root *root, unsigned long index)
 {
        struct item *item;
index d9c031dbeb1a9634451608a29592a74002958dc3..31f1d9b6f506ef884c978b568aa9dc5d89fd8312 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/rcupdate.h>
 
 struct item {
+       struct rcu_head rcu_head;
        unsigned long index;
        unsigned int order;
 };
@@ -12,9 +13,11 @@ struct item {
 struct item *item_create(unsigned long index, unsigned int order);
 int __item_insert(struct radix_tree_root *root, struct item *item);
 int item_insert(struct radix_tree_root *root, unsigned long index);
+void item_sanity(struct item *item, unsigned long index);
 int item_insert_order(struct radix_tree_root *root, unsigned long index,
                        unsigned order);
 int item_delete(struct radix_tree_root *root, unsigned long index);
+int item_delete_rcu(struct radix_tree_root *root, unsigned long index);
 struct item *item_lookup(struct radix_tree_root *root, unsigned long index);
 
 void item_check_present(struct radix_tree_root *root, unsigned long index);
index 2ddcc96ae4561acd3d773db814dffbb4c0acdb51..d9d00319b07cd691848a2f468c48e3bf10127284 100644 (file)
@@ -15,7 +15,7 @@ LIBKVM += $(LIBKVM_$(UNAME_M))
 
 INSTALL_HDR_PATH = $(top_srcdir)/usr
 LINUX_HDR_PATH = $(INSTALL_HDR_PATH)/include/
-CFLAGS += -O2 -g -std=gnu99 -I$(LINUX_HDR_PATH) -Iinclude -I$(<D)
+CFLAGS += -O2 -g -std=gnu99 -I$(LINUX_HDR_PATH) -Iinclude -I$(<D) -I..
 
 # After inclusion, $(OUTPUT) is defined and
 # $(TEST_GEN_PROGS) starts with $(OUTPUT)/
index 7ab98e41324ffd012720338e3a59074795f23ef7..ac53730b30aa48c9f9ecf54e3e6362f8cdf0e1c4 100644 (file)
@@ -19,6 +19,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include "kselftest.h"
 
 ssize_t test_write(int fd, const void *buf, size_t count);
 ssize_t test_read(int fd, void *buf, size_t count);
index 2cedfda181d4560dbc02ca0d2c5e44ab54326c61..37e2a787d2fcc6cc6cedcb30b9620456e99e43c0 100644 (file)
@@ -50,8 +50,8 @@ int kvm_check_cap(long cap)
        int kvm_fd;
 
        kvm_fd = open(KVM_DEV_PATH, O_RDONLY);
-       TEST_ASSERT(kvm_fd >= 0, "open %s failed, rc: %i errno: %i",
-               KVM_DEV_PATH, kvm_fd, errno);
+       if (kvm_fd < 0)
+               exit(KSFT_SKIP);
 
        ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, cap);
        TEST_ASSERT(ret != -1, "KVM_CHECK_EXTENSION IOCTL failed,\n"
@@ -91,8 +91,8 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
 
        vm->mode = mode;
        kvm_fd = open(KVM_DEV_PATH, perm);
-       TEST_ASSERT(kvm_fd >= 0, "open %s failed, rc: %i errno: %i",
-               KVM_DEV_PATH, kvm_fd, errno);
+       if (kvm_fd < 0)
+               exit(KSFT_SKIP);
 
        /* Create VM. */
        vm->fd = ioctl(kvm_fd, KVM_CREATE_VM, NULL);
@@ -418,8 +418,8 @@ struct kvm_cpuid2 *kvm_get_supported_cpuid(void)
 
        cpuid = allocate_kvm_cpuid2();
        kvm_fd = open(KVM_DEV_PATH, O_RDONLY);
-       TEST_ASSERT(kvm_fd >= 0, "open %s failed, rc: %i errno: %i",
-               KVM_DEV_PATH, kvm_fd, errno);
+       if (kvm_fd < 0)
+               exit(KSFT_SKIP);
 
        ret = ioctl(kvm_fd, KVM_GET_SUPPORTED_CPUID, cpuid);
        TEST_ASSERT(ret == 0, "KVM_GET_SUPPORTED_CPUID failed %d %d\n",
@@ -675,8 +675,8 @@ static int vcpu_mmap_sz(void)
        int dev_fd, ret;
 
        dev_fd = open(KVM_DEV_PATH, O_RDONLY);
-       TEST_ASSERT(dev_fd >= 0, "%s open %s failed, rc: %i errno: %i",
-               __func__, KVM_DEV_PATH, dev_fd, errno);
+       if (dev_fd < 0)
+               exit(KSFT_SKIP);
 
        ret = ioctl(dev_fd, KVM_GET_VCPU_MMAP_SIZE, NULL);
        TEST_ASSERT(ret >= sizeof(struct kvm_run),
index 428e9473f5e20cec7a3fe2df19d615c259491072..eae1ece3c31b8505e99877bf11d8fa8fb6907cdc 100644 (file)
@@ -85,6 +85,9 @@ static void compare_vcpu_events(struct kvm_vcpu_events *left,
 {
 }
 
+#define TEST_SYNC_FIELDS   (KVM_SYNC_X86_REGS|KVM_SYNC_X86_SREGS|KVM_SYNC_X86_EVENTS)
+#define INVALID_SYNC_FIELD 0x80000000
+
 int main(int argc, char *argv[])
 {
        struct kvm_vm *vm;
@@ -98,9 +101,14 @@ int main(int argc, char *argv[])
        setbuf(stdout, NULL);
 
        cap = kvm_check_cap(KVM_CAP_SYNC_REGS);
-       TEST_ASSERT((unsigned long)cap == KVM_SYNC_X86_VALID_FIELDS,
-                   "KVM_CAP_SYNC_REGS (0x%x) != KVM_SYNC_X86_VALID_FIELDS (0x%lx)\n",
-                   cap, KVM_SYNC_X86_VALID_FIELDS);
+       if ((cap & TEST_SYNC_FIELDS) != TEST_SYNC_FIELDS) {
+               fprintf(stderr, "KVM_CAP_SYNC_REGS not supported, skipping test\n");
+               exit(KSFT_SKIP);
+       }
+       if ((cap & INVALID_SYNC_FIELD) != 0) {
+               fprintf(stderr, "The \"invalid\" field is not invalid, skipping test\n");
+               exit(KSFT_SKIP);
+       }
 
        /* Create VM */
        vm = vm_create_default(VCPU_ID, guest_code);
@@ -108,7 +116,14 @@ int main(int argc, char *argv[])
        run = vcpu_state(vm, VCPU_ID);
 
        /* Request reading invalid register set from VCPU. */
-       run->kvm_valid_regs = KVM_SYNC_X86_VALID_FIELDS << 1;
+       run->kvm_valid_regs = INVALID_SYNC_FIELD;
+       rv = _vcpu_run(vm, VCPU_ID);
+       TEST_ASSERT(rv < 0 && errno == EINVAL,
+                   "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
+                   rv);
+       vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0;
+
+       run->kvm_valid_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
        rv = _vcpu_run(vm, VCPU_ID);
        TEST_ASSERT(rv < 0 && errno == EINVAL,
                    "Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
@@ -116,7 +131,14 @@ int main(int argc, char *argv[])
        vcpu_state(vm, VCPU_ID)->kvm_valid_regs = 0;
 
        /* Request setting invalid register set into VCPU. */
-       run->kvm_dirty_regs = KVM_SYNC_X86_VALID_FIELDS << 1;
+       run->kvm_dirty_regs = INVALID_SYNC_FIELD;
+       rv = _vcpu_run(vm, VCPU_ID);
+       TEST_ASSERT(rv < 0 && errno == EINVAL,
+                   "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
+                   rv);
+       vcpu_state(vm, VCPU_ID)->kvm_dirty_regs = 0;
+
+       run->kvm_dirty_regs = INVALID_SYNC_FIELD | TEST_SYNC_FIELDS;
        rv = _vcpu_run(vm, VCPU_ID);
        TEST_ASSERT(rv < 0 && errno == EINVAL,
                    "Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
@@ -125,7 +147,7 @@ int main(int argc, char *argv[])
 
        /* Request and verify all valid register sets. */
        /* TODO: BUILD TIME CHECK: TEST_ASSERT(KVM_SYNC_X86_NUM_FIELDS != 3); */
-       run->kvm_valid_regs = KVM_SYNC_X86_VALID_FIELDS;
+       run->kvm_valid_regs = TEST_SYNC_FIELDS;
        rv = _vcpu_run(vm, VCPU_ID);
        TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
                    "Unexpected exit reason: %u (%s),\n",
@@ -146,7 +168,7 @@ int main(int argc, char *argv[])
        run->s.regs.sregs.apic_base = 1 << 11;
        /* TODO run->s.regs.events.XYZ = ABC; */
 
-       run->kvm_valid_regs = KVM_SYNC_X86_VALID_FIELDS;
+       run->kvm_valid_regs = TEST_SYNC_FIELDS;
        run->kvm_dirty_regs = KVM_SYNC_X86_REGS | KVM_SYNC_X86_SREGS;
        rv = _vcpu_run(vm, VCPU_ID);
        TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
@@ -172,7 +194,7 @@ int main(int argc, char *argv[])
        /* Clear kvm_dirty_regs bits, verify new s.regs values are
         * overwritten with existing guest values.
         */
-       run->kvm_valid_regs = KVM_SYNC_X86_VALID_FIELDS;
+       run->kvm_valid_regs = TEST_SYNC_FIELDS;
        run->kvm_dirty_regs = 0;
        run->s.regs.regs.r11 = 0xDEADBEEF;
        rv = _vcpu_run(vm, VCPU_ID);
@@ -211,7 +233,7 @@ int main(int argc, char *argv[])
         * with kvm_sync_regs values.
         */
        run->kvm_valid_regs = 0;
-       run->kvm_dirty_regs = KVM_SYNC_X86_VALID_FIELDS;
+       run->kvm_dirty_regs = TEST_SYNC_FIELDS;
        run->s.regs.regs.r11 = 0xBBBB;
        rv = _vcpu_run(vm, VCPU_ID);
        TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
index 8f7f62093add0fca51d5923196189cc3110e9597..aaa633263b2c42b38445e3b73815a9f2db977670 100644 (file)
@@ -189,8 +189,8 @@ int main(int argc, char *argv[])
        struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
 
        if (!(entry->ecx & CPUID_VMX)) {
-               printf("nested VMX not enabled, skipping test");
-               return 0;
+               fprintf(stderr, "nested VMX not enabled, skipping test\n");
+               exit(KSFT_SKIP);
        }
 
        vm = vm_create_default_vmx(VCPU_ID, (void *) l1_guest_code);
index daf5effec3f07d7d67e58d15571e15defd749814..3ff81a478dbed059f3d0b92c9291c96efdbc7284 100644 (file)
@@ -6,7 +6,7 @@ CFLAGS += -I../../../../usr/include/
 
 TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh
 TEST_PROGS += fib_tests.sh fib-onlink-tests.sh pmtu.sh
-TEST_GEN_PROGS_EXTENDED := in_netns.sh
+TEST_PROGS_EXTENDED := in_netns.sh
 TEST_GEN_FILES =  socket
 TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy
 TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
index 5b012f4981d4c411329d073e7fbcb832d090c1c0..6f289a49e5ecf01552026bef35534a93d8cd136c 100644 (file)
@@ -66,7 +66,7 @@
         "cmdUnderTest": "$TC action add action bpf object-file _b.o index 667",
         "expExitCode": "0",
         "verifyCmd": "$TC action get action bpf index 667",
-        "matchPattern": "action order [0-9]*: bpf _b.o:\\[action\\] id [0-9]* tag 3b185187f1855c4c default-action pipe.*index 667 ref",
+        "matchPattern": "action order [0-9]*: bpf _b.o:\\[action\\] id [0-9]* tag 3b185187f1855c4c( jited)? default-action pipe.*index 667 ref",
         "matchCount": "1",
         "teardown": [
             "$TC action flush action bpf",
         "cmdUnderTest": "$TC action add action bpf object-file _c.o index 667",
         "expExitCode": "255",
         "verifyCmd": "$TC action get action bpf index 667",
-        "matchPattern": "action order [0-9]*: bpf _b.o:\\[action\\] id [0-9].*index 667 ref",
+        "matchPattern": "action order [0-9]*: bpf _c.o:\\[action\\] id [0-9].*index 667 ref",
         "matchCount": "0",
         "teardown": [
-            "$TC action flush action bpf",
+            [
+                "$TC action flush action bpf",
+                0,
+                1,
+                255
+            ],
             "rm -f _c.o"
         ]
     },
index 10b38178cff207a9ae1e8d59970e3f19fc7be7f6..4ffc0b5e610560c752c99de33d6f5857e7344773 100644 (file)
@@ -211,6 +211,7 @@ static int vgic_debug_show(struct seq_file *s, void *v)
        struct vgic_state_iter *iter = (struct vgic_state_iter *)v;
        struct vgic_irq *irq;
        struct kvm_vcpu *vcpu = NULL;
+       unsigned long flags;
 
        if (iter->dist_id == 0) {
                print_dist_state(s, &kvm->arch.vgic);
@@ -227,9 +228,9 @@ static int vgic_debug_show(struct seq_file *s, void *v)
                irq = &kvm->arch.vgic.spis[iter->intid - VGIC_NR_PRIVATE_IRQS];
        }
 
-       spin_lock(&irq->irq_lock);
+       spin_lock_irqsave(&irq->irq_lock, flags);
        print_irq_state(s, irq, vcpu);
-       spin_unlock(&irq->irq_lock);
+       spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        return 0;
 }
index 68378fe17a0e7e5b0be896863b94913bceb901c9..e07156c303235e13dc00b31d39e38ff1d30d281d 100644 (file)
@@ -423,7 +423,7 @@ static irqreturn_t vgic_maintenance_handler(int irq, void *data)
         * We cannot rely on the vgic maintenance interrupt to be
         * delivered synchronously. This means we can only use it to
         * exit the VM, and we perform the handling of EOIed
-        * interrupts on the exit path (see vgic_process_maintenance).
+        * interrupts on the exit path (see vgic_fold_lr_state).
         */
        return IRQ_HANDLED;
 }
index a8f07243aa9f0533dd2a8fe57c7589c849142e53..4ed79c939fb447188d0a2bc7c740e85e1d82135c 100644 (file)
@@ -52,6 +52,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
        struct vgic_irq *irq = vgic_get_irq(kvm, NULL, intid), *oldirq;
+       unsigned long flags;
        int ret;
 
        /* In this case there is no put, since we keep the reference. */
@@ -71,7 +72,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
        irq->intid = intid;
        irq->target_vcpu = vcpu;
 
-       spin_lock(&dist->lpi_list_lock);
+       spin_lock_irqsave(&dist->lpi_list_lock, flags);
 
        /*
         * There could be a race with another vgic_add_lpi(), so we need to
@@ -99,7 +100,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
        dist->lpi_list_count++;
 
 out_unlock:
-       spin_unlock(&dist->lpi_list_lock);
+       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        /*
         * We "cache" the configuration table entries in our struct vgic_irq's.
@@ -280,8 +281,8 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
        int ret;
        unsigned long flags;
 
-       ret = kvm_read_guest(kvm, propbase + irq->intid - GIC_LPI_OFFSET,
-                            &prop, 1);
+       ret = kvm_read_guest_lock(kvm, propbase + irq->intid - GIC_LPI_OFFSET,
+                                 &prop, 1);
 
        if (ret)
                return ret;
@@ -315,6 +316,7 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
 {
        struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
        struct vgic_irq *irq;
+       unsigned long flags;
        u32 *intids;
        int irq_count, i = 0;
 
@@ -330,7 +332,7 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
        if (!intids)
                return -ENOMEM;
 
-       spin_lock(&dist->lpi_list_lock);
+       spin_lock_irqsave(&dist->lpi_list_lock, flags);
        list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
                if (i == irq_count)
                        break;
@@ -339,7 +341,7 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
                        continue;
                intids[i++] = irq->intid;
        }
-       spin_unlock(&dist->lpi_list_lock);
+       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        *intid_ptr = intids;
        return i;
@@ -348,10 +350,11 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
 static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
 {
        int ret = 0;
+       unsigned long flags;
 
-       spin_lock(&irq->irq_lock);
+       spin_lock_irqsave(&irq->irq_lock, flags);
        irq->target_vcpu = vcpu;
-       spin_unlock(&irq->irq_lock);
+       spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        if (irq->hw) {
                struct its_vlpi_map map;
@@ -441,8 +444,9 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu)
                 * this very same byte in the last iteration. Reuse that.
                 */
                if (byte_offset != last_byte_offset) {
-                       ret = kvm_read_guest(vcpu->kvm, pendbase + byte_offset,
-                                            &pendmask, 1);
+                       ret = kvm_read_guest_lock(vcpu->kvm,
+                                                 pendbase + byte_offset,
+                                                 &pendmask, 1);
                        if (ret) {
                                kfree(intids);
                                return ret;
@@ -786,7 +790,7 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id,
                return false;
 
        /* Each 1st level entry is represented by a 64-bit value. */
-       if (kvm_read_guest(its->dev->kvm,
+       if (kvm_read_guest_lock(its->dev->kvm,
                           BASER_ADDRESS(baser) + index * sizeof(indirect_ptr),
                           &indirect_ptr, sizeof(indirect_ptr)))
                return false;
@@ -1367,8 +1371,8 @@ static void vgic_its_process_commands(struct kvm *kvm, struct vgic_its *its)
        cbaser = CBASER_ADDRESS(its->cbaser);
 
        while (its->cwriter != its->creadr) {
-               int ret = kvm_read_guest(kvm, cbaser + its->creadr,
-                                        cmd_buf, ITS_CMD_SIZE);
+               int ret = kvm_read_guest_lock(kvm, cbaser + its->creadr,
+                                             cmd_buf, ITS_CMD_SIZE);
                /*
                 * If kvm_read_guest() fails, this could be due to the guest
                 * programming a bogus value in CBASER or something else going
@@ -1893,7 +1897,7 @@ static int scan_its_table(struct vgic_its *its, gpa_t base, int size, int esz,
                int next_offset;
                size_t byte_offset;
 
-               ret = kvm_read_guest(kvm, gpa, entry, esz);
+               ret = kvm_read_guest_lock(kvm, gpa, entry, esz);
                if (ret)
                        return ret;
 
@@ -2263,7 +2267,7 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
        int ret;
 
        BUG_ON(esz > sizeof(val));
-       ret = kvm_read_guest(kvm, gpa, &val, esz);
+       ret = kvm_read_guest_lock(kvm, gpa, &val, esz);
        if (ret)
                return ret;
        val = le64_to_cpu(val);
index dbe99d635c80435ffd938999c4246ce6f45307c7..ff9655cfeb2f8678558163790de2aeb6ec5841df 100644 (file)
@@ -289,10 +289,16 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
               irq->vcpu->cpu != -1) /* VCPU thread is running */
                cond_resched_lock(&irq->irq_lock);
 
-       if (irq->hw)
+       if (irq->hw) {
                vgic_hw_irq_change_active(vcpu, irq, active, !requester_vcpu);
-       else
+       } else {
+               u32 model = vcpu->kvm->arch.vgic.vgic_model;
+
                irq->active = active;
+               if (model == KVM_DEV_TYPE_ARM_VGIC_V2 &&
+                   active && vgic_irq_is_sgi(irq->intid))
+                       irq->active_source = requester_vcpu->vcpu_id;
+       }
 
        if (irq->active)
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
index 45aa433f018ffdebfd05cd7d2720ed996b57dc4d..a5f2e44f1c33d42ad2693d63b8142665864e64a6 100644 (file)
@@ -37,13 +37,6 @@ void vgic_v2_init_lrs(void)
                vgic_v2_write_lr(i, 0);
 }
 
-void vgic_v2_set_npie(struct kvm_vcpu *vcpu)
-{
-       struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
-
-       cpuif->vgic_hcr |= GICH_HCR_NPIE;
-}
-
 void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
 {
        struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
@@ -71,13 +64,18 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
        int lr;
        unsigned long flags;
 
-       cpuif->vgic_hcr &= ~(GICH_HCR_UIE | GICH_HCR_NPIE);
+       cpuif->vgic_hcr &= ~GICH_HCR_UIE;
 
        for (lr = 0; lr < vgic_cpu->used_lrs; lr++) {
                u32 val = cpuif->vgic_lr[lr];
-               u32 intid = val & GICH_LR_VIRTUALID;
+               u32 cpuid, intid = val & GICH_LR_VIRTUALID;
                struct vgic_irq *irq;
 
+               /* Extract the source vCPU id from the LR */
+               cpuid = val & GICH_LR_PHYSID_CPUID;
+               cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+               cpuid &= 7;
+
                /* Notify fds when the guest EOI'ed a level-triggered SPI */
                if (lr_signals_eoi_mi(val) && vgic_valid_spi(vcpu->kvm, intid))
                        kvm_notify_acked_irq(vcpu->kvm, 0,
@@ -90,17 +88,16 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
                /* Always preserve the active bit */
                irq->active = !!(val & GICH_LR_ACTIVE_BIT);
 
+               if (irq->active && vgic_irq_is_sgi(intid))
+                       irq->active_source = cpuid;
+
                /* Edge is the only case where we preserve the pending bit */
                if (irq->config == VGIC_CONFIG_EDGE &&
                    (val & GICH_LR_PENDING_BIT)) {
                        irq->pending_latch = true;
 
-                       if (vgic_irq_is_sgi(intid)) {
-                               u32 cpuid = val & GICH_LR_PHYSID_CPUID;
-
-                               cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+                       if (vgic_irq_is_sgi(intid))
                                irq->source |= (1 << cpuid);
-                       }
                }
 
                /*
@@ -152,8 +149,15 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
        u32 val = irq->intid;
        bool allow_pending = true;
 
-       if (irq->active)
+       if (irq->active) {
                val |= GICH_LR_ACTIVE_BIT;
+               if (vgic_irq_is_sgi(irq->intid))
+                       val |= irq->active_source << GICH_LR_PHYSID_CPUID_SHIFT;
+               if (vgic_irq_is_multi_sgi(irq)) {
+                       allow_pending = false;
+                       val |= GICH_LR_EOI;
+               }
+       }
 
        if (irq->hw) {
                val |= GICH_LR_HW;
@@ -190,8 +194,10 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
                        BUG_ON(!src);
                        val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
                        irq->source &= ~(1 << (src - 1));
-                       if (irq->source)
+                       if (irq->source) {
                                irq->pending_latch = true;
+                               val |= GICH_LR_EOI;
+                       }
                }
        }
 
index 8195f52ae6f0906c31432ca0ac4471d4bdd3c74a..bdcf8e7a6161298d373a7605dc5fe6be43fa872e 100644 (file)
@@ -27,13 +27,6 @@ static bool group1_trap;
 static bool common_trap;
 static bool gicv4_enable;
 
-void vgic_v3_set_npie(struct kvm_vcpu *vcpu)
-{
-       struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
-
-       cpuif->vgic_hcr |= ICH_HCR_NPIE;
-}
-
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
        struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
@@ -55,17 +48,23 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
        int lr;
        unsigned long flags;
 
-       cpuif->vgic_hcr &= ~(ICH_HCR_UIE | ICH_HCR_NPIE);
+       cpuif->vgic_hcr &= ~ICH_HCR_UIE;
 
        for (lr = 0; lr < vgic_cpu->used_lrs; lr++) {
                u64 val = cpuif->vgic_lr[lr];
-               u32 intid;
+               u32 intid, cpuid;
                struct vgic_irq *irq;
+               bool is_v2_sgi = false;
 
-               if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
+               cpuid = val & GICH_LR_PHYSID_CPUID;
+               cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+
+               if (model == KVM_DEV_TYPE_ARM_VGIC_V3) {
                        intid = val & ICH_LR_VIRTUAL_ID_MASK;
-               else
+               } else {
                        intid = val & GICH_LR_VIRTUALID;
+                       is_v2_sgi = vgic_irq_is_sgi(intid);
+               }
 
                /* Notify fds when the guest EOI'ed a level-triggered IRQ */
                if (lr_signals_eoi_mi(val) && vgic_valid_spi(vcpu->kvm, intid))
@@ -81,18 +80,16 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
                /* Always preserve the active bit */
                irq->active = !!(val & ICH_LR_ACTIVE_BIT);
 
+               if (irq->active && is_v2_sgi)
+                       irq->active_source = cpuid;
+
                /* Edge is the only case where we preserve the pending bit */
                if (irq->config == VGIC_CONFIG_EDGE &&
                    (val & ICH_LR_PENDING_BIT)) {
                        irq->pending_latch = true;
 
-                       if (vgic_irq_is_sgi(intid) &&
-                           model == KVM_DEV_TYPE_ARM_VGIC_V2) {
-                               u32 cpuid = val & GICH_LR_PHYSID_CPUID;
-
-                               cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
+                       if (is_v2_sgi)
                                irq->source |= (1 << cpuid);
-                       }
                }
 
                /*
@@ -133,10 +130,20 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
 {
        u32 model = vcpu->kvm->arch.vgic.vgic_model;
        u64 val = irq->intid;
-       bool allow_pending = true;
+       bool allow_pending = true, is_v2_sgi;
 
-       if (irq->active)
+       is_v2_sgi = (vgic_irq_is_sgi(irq->intid) &&
+                    model == KVM_DEV_TYPE_ARM_VGIC_V2);
+
+       if (irq->active) {
                val |= ICH_LR_ACTIVE_BIT;
+               if (is_v2_sgi)
+                       val |= irq->active_source << GICH_LR_PHYSID_CPUID_SHIFT;
+               if (vgic_irq_is_multi_sgi(irq)) {
+                       allow_pending = false;
+                       val |= ICH_LR_EOI;
+               }
+       }
 
        if (irq->hw) {
                val |= ICH_LR_HW;
@@ -174,8 +181,10 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
                        BUG_ON(!src);
                        val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
                        irq->source &= ~(1 << (src - 1));
-                       if (irq->source)
+                       if (irq->source) {
                                irq->pending_latch = true;
+                               val |= ICH_LR_EOI;
+                       }
                }
        }
 
@@ -335,7 +344,7 @@ retry:
        bit_nr = irq->intid % BITS_PER_BYTE;
        ptr = pendbase + byte_offset;
 
-       ret = kvm_read_guest(kvm, ptr, &val, 1);
+       ret = kvm_read_guest_lock(kvm, ptr, &val, 1);
        if (ret)
                return ret;
 
@@ -388,7 +397,7 @@ int vgic_v3_save_pending_tables(struct kvm *kvm)
                ptr = pendbase + byte_offset;
 
                if (byte_offset != last_byte_offset) {
-                       ret = kvm_read_guest(kvm, ptr, &val, 1);
+                       ret = kvm_read_guest_lock(kvm, ptr, &val, 1);
                        if (ret)
                                return ret;
                        last_byte_offset = byte_offset;
index 702936cbe173013086a2a60349ed34a041152877..33c8325c8f35662c03c37319605d28e2f2f9d7a4 100644 (file)
@@ -43,9 +43,13 @@ struct vgic_global kvm_vgic_global_state __ro_after_init = {
  * kvm->lock (mutex)
  *   its->cmd_lock (mutex)
  *     its->its_lock (mutex)
- *       vgic_cpu->ap_list_lock
- *         kvm->lpi_list_lock
- *           vgic_irq->irq_lock
+ *       vgic_cpu->ap_list_lock                must be taken with IRQs disabled
+ *         kvm->lpi_list_lock          must be taken with IRQs disabled
+ *           vgic_irq->irq_lock                must be taken with IRQs disabled
+ *
+ * As the ap_list_lock might be taken from the timer interrupt handler,
+ * we have to disable IRQs before taking this lock and everything lower
+ * than it.
  *
  * If you need to take multiple locks, always take the upper lock first,
  * then the lower ones, e.g. first take the its_lock, then the irq_lock.
@@ -72,8 +76,9 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
        struct vgic_irq *irq = NULL;
+       unsigned long flags;
 
-       spin_lock(&dist->lpi_list_lock);
+       spin_lock_irqsave(&dist->lpi_list_lock, flags);
 
        list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
                if (irq->intid != intid)
@@ -89,7 +94,7 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
        irq = NULL;
 
 out_unlock:
-       spin_unlock(&dist->lpi_list_lock);
+       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        return irq;
 }
@@ -134,19 +139,20 @@ static void vgic_irq_release(struct kref *ref)
 void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
+       unsigned long flags;
 
        if (irq->intid < VGIC_MIN_LPI)
                return;
 
-       spin_lock(&dist->lpi_list_lock);
+       spin_lock_irqsave(&dist->lpi_list_lock, flags);
        if (!kref_put(&irq->refcount, vgic_irq_release)) {
-               spin_unlock(&dist->lpi_list_lock);
+               spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
                return;
        };
 
        list_del(&irq->lpi_list);
        dist->lpi_list_count--;
-       spin_unlock(&dist->lpi_list_lock);
+       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        kfree(irq);
 }
@@ -725,14 +731,6 @@ static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
                vgic_v3_set_underflow(vcpu);
 }
 
-static inline void vgic_set_npie(struct kvm_vcpu *vcpu)
-{
-       if (kvm_vgic_global_state.type == VGIC_V2)
-               vgic_v2_set_npie(vcpu);
-       else
-               vgic_v3_set_npie(vcpu);
-}
-
 /* Requires the ap_list_lock to be held. */
 static int compute_ap_list_depth(struct kvm_vcpu *vcpu,
                                 bool *multi_sgi)
@@ -746,17 +744,15 @@ static int compute_ap_list_depth(struct kvm_vcpu *vcpu,
        DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
 
        list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
+               int w;
+
                spin_lock(&irq->irq_lock);
                /* GICv2 SGIs can count for more than one... */
-               if (vgic_irq_is_sgi(irq->intid) && irq->source) {
-                       int w = hweight8(irq->source);
-
-                       count += w;
-                       *multi_sgi |= (w > 1);
-               } else {
-                       count++;
-               }
+               w = vgic_irq_get_lr_count(irq);
                spin_unlock(&irq->irq_lock);
+
+               count += w;
+               *multi_sgi |= (w > 1);
        }
        return count;
 }
@@ -767,7 +763,6 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
        struct vgic_irq *irq;
        int count;
-       bool npie = false;
        bool multi_sgi;
        u8 prio = 0xff;
 
@@ -797,10 +792,8 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
                if (likely(vgic_target_oracle(irq) == vcpu)) {
                        vgic_populate_lr(vcpu, irq, count++);
 
-                       if (irq->source) {
-                               npie = true;
+                       if (irq->source)
                                prio = irq->priority;
-                       }
                }
 
                spin_unlock(&irq->irq_lock);
@@ -813,9 +806,6 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
                }
        }
 
-       if (npie)
-               vgic_set_npie(vcpu);
-
        vcpu->arch.vgic_cpu.used_lrs = count;
 
        /* Nuke remaining LRs */
index 830e815748a05bae8d31de8db1b2fd6166392c08..32c25d42c93f401390f5d00fca80e637c8670151 100644 (file)
@@ -110,6 +110,20 @@ static inline bool vgic_irq_is_mapped_level(struct vgic_irq *irq)
        return irq->config == VGIC_CONFIG_LEVEL && irq->hw;
 }
 
+static inline int vgic_irq_get_lr_count(struct vgic_irq *irq)
+{
+       /* Account for the active state as an interrupt */
+       if (vgic_irq_is_sgi(irq->intid) && irq->source)
+               return hweight8(irq->source) + irq->active;
+
+       return irq_is_pending(irq) || irq->active;
+}
+
+static inline bool vgic_irq_is_multi_sgi(struct vgic_irq *irq)
+{
+       return vgic_irq_get_lr_count(irq) > 1;
+}
+
 /*
  * This struct provides an intermediate representation of the fields contained
  * in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC