Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
authorDavid S. Miller <davem@davemloft.net>
Wed, 28 Nov 2018 19:02:45 +0000 (11:02 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 28 Nov 2018 19:02:45 +0000 (11:02 -0800)
Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net:

1) Disable BH while holding list spinlock in nf_conncount, from
   Taehee Yoo.

2) List corruption in nf_conncount, also from Taehee.

3) Fix race that results in leaving around an empty list node in
   nf_conncount, from Taehee Yoo.

4) Proper chain handling for inactive chains from the commit path,
   from Florian Westphal. This includes a selftest for this.

5) Do duplicate rule handles when replacing rules, also from Florian.

6) Remove net_exit path in xt_RATEEST that results in splat, from Taehee.

7) Possible use-after-free in nft_compat when releasing extensions.
   From Florian.

8) Memory leak in xt_hashlimit, from Taehee.

9) Call ip_vs_dst_notifier after ipv6_dev_notf, from Xin Long.

10) Fix cttimeout with udplite and gre, from Florian.

11) Preserve oif for IPv6 link-local generated traffic from mangle
    table, from Alin Nastac.

12) Missing error handling in masquerade notifiers, from Taehee Yoo.

13) Use mutex to protect registration/unregistration of masquerade
    extensions in order to prevent a race, from Taehee.

14) Incorrect condition check in tree_nodes_free(), also from Taehee.

15) Fix chain counter leak in rule replacement path, from Taehee.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
431 files changed:
CREDITS
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/pm/cpufreq.rst
Documentation/admin-guide/security-bugs.rst
Documentation/cpu-freq/cpufreq-stats.txt
Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt [deleted file]
Documentation/devicetree/bindings/net/can/holt_hi311x.txt
Documentation/devicetree/bindings/net/can/rcar_can.txt
Documentation/devicetree/bindings/net/dsa/dsa.txt
Documentation/media/uapi/v4l/dev-meta.rst
Documentation/media/uapi/v4l/vidioc-g-fmt.rst
Documentation/networking/rxrpc.txt
MAINTAINERS
Makefile
arch/arm/include/asm/cputype.h
arch/arm/include/asm/proc-fns.h
arch/arm/kernel/bugs.c
arch/arm/kernel/head-common.S
arch/arm/kernel/setup.c
arch/arm/kernel/smp.c
arch/arm/mach-omap2/display.c
arch/arm/mm/proc-v7-bugs.c
arch/arm/vfp/vfpmodule.c
arch/arm64/include/asm/sysreg.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/setup.c
arch/arm64/net/bpf_jit_comp.c
arch/mips/configs/cavium_octeon_defconfig
arch/mips/kernel/setup.c
arch/mips/kernel/traps.c
arch/mips/loongson64/loongson-3/numa.c
arch/mips/sgi-ip27/ip27-memory.c
arch/parisc/include/asm/spinlock.h
arch/parisc/kernel/syscall.S
arch/powerpc/include/asm/io.h
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/include/asm/ptrace.h
arch/powerpc/kernel/setup_64.c
arch/powerpc/kvm/trace.h
arch/powerpc/kvm/trace_booke.h
arch/powerpc/kvm/trace_hv.h
arch/powerpc/kvm/trace_pr.h
arch/powerpc/mm/numa.c
arch/powerpc/mm/slb.c
arch/powerpc/net/bpf_jit_comp64.c
arch/powerpc/platforms/powernv/npu-dma.c
arch/riscv/Makefile
arch/riscv/boot/.gitignore [new file with mode: 0644]
arch/riscv/boot/Makefile [new file with mode: 0644]
arch/riscv/boot/install.sh [new file with mode: 0644]
arch/riscv/configs/defconfig
arch/riscv/include/asm/module.h
arch/riscv/include/asm/ptrace.h
arch/riscv/include/asm/uaccess.h
arch/riscv/include/asm/unistd.h
arch/riscv/include/uapi/asm/syscalls.h [deleted file]
arch/riscv/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/riscv/kernel/cpu.c
arch/riscv/kernel/head.S
arch/riscv/kernel/module.c
arch/riscv/kernel/vmlinux.lds.S
arch/riscv/lib/Makefile
arch/sparc/net/bpf_jit_comp_64.c
arch/x86/events/intel/uncore.h
arch/x86/events/intel/uncore_snb.c
arch/xtensa/include/asm/processor.h
arch/xtensa/kernel/head.S
block/bio.c
block/blk-core.c
block/blk-lib.c
block/bounce.c
crypto/crypto_user_base.c
crypto/crypto_user_stat.c
crypto/simd.c
drivers/acpi/Kconfig
drivers/acpi/acpi_platform.c
drivers/acpi/nfit/core.c
drivers/ata/libata-core.c
drivers/atm/firestream.c
drivers/block/floppy.c
drivers/cpufreq/imx6q-cpufreq.c
drivers/cpufreq/ti-cpufreq.c
drivers/cpuidle/cpuidle-arm.c
drivers/crypto/hisilicon/sec/sec_algs.c
drivers/dma-buf/udmabuf.c
drivers/firmware/efi/arm-init.c
drivers/firmware/efi/arm-runtime.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/arm-stub.c
drivers/firmware/efi/libstub/fdt.c
drivers/firmware/efi/memmap.c
drivers/firmware/efi/runtime-wrappers.c
drivers/gnss/serial.c
drivers/gnss/sirf.c
drivers/gpio/gpio-mockup.c
drivers/gpio/gpio-pxa.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdgpu/vega10_ih.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
drivers/gpu/drm/ast/ast_drv.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_fourcc.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_gpu_error.h
drivers/gpu/drm/i915/intel_device_info.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp_mst.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_hotplug.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_runtime_pm.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/meson/meson_venc.c
drivers/gpu/drm/omapdrm/dss/dsi.c
drivers/gpu/drm/omapdrm/dss/dss.c
drivers/gpu/drm/omapdrm/dss/hdmi4.c
drivers/gpu/drm/omapdrm/dss/hdmi5.c
drivers/gpu/drm/omapdrm/dss/venc.c
drivers/gpu/drm/omapdrm/omap_crtc.c
drivers/gpu/drm/vc4/vc4_kms.c
drivers/gpu/drm/vc4/vc4_plane.c
drivers/hv/hv_kvp.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/intel-iommu.c
drivers/iommu/intel-svm.c
drivers/iommu/ipmmu-vmsa.c
drivers/media/cec/cec-adap.c
drivers/media/i2c/tc358743.c
drivers/media/pci/intel/ipu3/ipu3-cio2.c
drivers/media/platform/omap3isp/isp.c
drivers/media/platform/vicodec/vicodec-core.c
drivers/media/platform/vim2m.c
drivers/media/v4l2-core/v4l2-ctrls.c
drivers/media/v4l2-core/v4l2-event.c
drivers/media/v4l2-core/v4l2-mem2mem.c
drivers/misc/atmel-ssc.c
drivers/misc/sgi-gru/grukdump.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mtd/nand/raw/atmel/nand-controller.c
drivers/mtd/nand/raw/qcom_nandc.c
drivers/mtd/spi-nor/cadence-quadspi.c
drivers/mtd/spi-nor/spi-nor.c
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/can/rcar/rcar_can.c
drivers/net/can/rx-offload.c
drivers/net/can/spi/hi311x.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
drivers/net/can/usb/ucan.c
drivers/net/ethernet/amazon/ena/ena_netdev.c
drivers/net/ethernet/amazon/ena/ena_netdev.h
drivers/net/ethernet/amd/sunlance.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/cavium/thunder/nic_main.c
drivers/net/ethernet/cavium/thunder/nicvf_main.c
drivers/net/ethernet/cavium/thunder/nicvf_queues.c
drivers/net/ethernet/chelsio/Kconfig
drivers/net/ethernet/chelsio/cxgb4/Makefile
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/cortina/gemini.c
drivers/net/ethernet/faraday/ftmac100.c
drivers/net/ethernet/hisilicon/hip04_eth.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/ibm/ibmvnic.h
drivers/net/ethernet/lantiq_xrx200.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/mellanox/mlx4/alloc.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/mr.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/port.c
drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
drivers/net/ethernet/microchip/lan743x_main.c
drivers/net/ethernet/microchip/lan743x_main.h
drivers/net/ethernet/qlogic/qed/qed_dcbx.c
drivers/net/ethernet/qlogic/qed/qed_debug.c
drivers/net/ethernet/qlogic/qed/qed_dev.c
drivers/net/ethernet/qlogic/qed/qed_int.c
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qed/qed_rdma.c
drivers/net/ethernet/qlogic/qed/qed_rdma.h
drivers/net/ethernet/via/via-velocity.c
drivers/net/phy/mdio-gpio.c
drivers/net/phy/mscc.c
drivers/net/phy/phy_device.c
drivers/net/rionet.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/ipheth.c
drivers/net/virtio_net.c
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c
drivers/net/wireless/intel/iwlwifi/fw/acpi.h
drivers/net/wireless/intel/iwlwifi/fw/runtime.h
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/mediatek/mt76/Kconfig
drivers/net/wireless/mediatek/mt76/mac80211.c
drivers/net/wireless/mediatek/mt76/mt76x02.h
drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c
drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c
drivers/net/wireless/ti/wlcore/sdio.c
drivers/nvme/host/fc.c
drivers/nvmem/core.c
drivers/opp/ti-opp-supply.c
drivers/pci/pci-acpi.c
drivers/pinctrl/meson/pinctrl-meson-gxbb.c
drivers/pinctrl/meson/pinctrl-meson-gxl.c
drivers/pinctrl/meson/pinctrl-meson.c
drivers/pinctrl/meson/pinctrl-meson8.c
drivers/pinctrl/meson/pinctrl-meson8b.c
drivers/rtc/hctosys.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-pcf2127.c
drivers/s390/net/ism_drv.c
drivers/scsi/Kconfig
drivers/scsi/NCR5380.c
drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
drivers/scsi/lpfc/lpfc_debugfs.c
drivers/scsi/myrb.c
drivers/scsi/myrs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/scsi_lib.c
drivers/scsi/ufs/ufs-hisi.c
drivers/scsi/ufs/ufs_quirks.h
drivers/scsi/ufs/ufshcd.c
drivers/slimbus/qcom-ngd-ctrl.c
drivers/slimbus/slimbus.h
drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
drivers/staging/media/sunxi/cedrus/cedrus.c
drivers/target/target_core_transport.c
drivers/uio/uio.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/dwc2/pci.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/host/xhci-histb.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mtk.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci-tegra.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/appledisplay.c
fs/afs/rxrpc.c
fs/exec.c
fs/fuse/dev.c
fs/fuse/file.c
fs/gfs2/bmap.c
fs/gfs2/rgrp.c
fs/inode.c
fs/iomap.c
fs/namespace.c
fs/nfs/callback_proc.c
fs/nfs/delegation.c
fs/nfs/nfs4state.c
fs/nfsd/nfs4proc.c
fs/notify/fanotify/fanotify.c
fs/notify/fsnotify.c
fs/ocfs2/aops.c
fs/ocfs2/cluster/masklog.h
fs/read_write.c
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_ialloc_btree.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_bmap_util.h
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_file.c
fs/xfs/xfs_reflink.c
fs/xfs/xfs_trace.h
include/linux/can/dev.h
include/linux/can/rx-offload.h
include/linux/efi.h
include/linux/filter.h
include/linux/net_dim.h
include/linux/skbuff.h
include/linux/tcp.h
include/linux/usb/quirks.h
include/media/v4l2-mem2mem.h
include/net/af_rxrpc.h
include/net/sctp/sctp.h
include/trace/events/kyber.h
include/trace/events/rxrpc.h
include/uapi/linux/v4l2-controls.h
kernel/bpf/core.c
kernel/bpf/local_storage.c
kernel/bpf/queue_stack_maps.c
kernel/bpf/verifier.c
kernel/debug/kdb/kdb_bt.c
kernel/debug/kdb/kdb_io.c
kernel/debug/kdb/kdb_keyboard.c
kernel/debug/kdb/kdb_main.c
kernel/debug/kdb/kdb_private.h
kernel/debug/kdb/kdb_support.c
kernel/sched/fair.c
kernel/sched/psi.c
kernel/trace/bpf_trace.c
lib/test_firmware.c
lib/ubsan.c
mm/gup.c
mm/hugetlb.c
mm/memblock.c
mm/page_alloc.c
mm/shmem.c
mm/swapfile.c
mm/vmstat.c
mm/z3fold.c
net/batman-adv/bat_v_elp.c
net/batman-adv/fragmentation.c
net/bridge/br_private.h
net/bridge/br_vlan.c
net/can/raw.c
net/ceph/messenger.c
net/core/dev.c
net/core/filter.c
net/core/skbuff.c
net/ipv4/ip_output.c
net/ipv4/ip_tunnel_core.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv6/addrconf.c
net/ipv6/ip6_output.c
net/ipv6/route.c
net/l2tp/l2tp_core.c
net/packet/af_packet.c
net/rxrpc/af_rxrpc.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/sch_fq.c
net/sctp/output.c
net/sctp/socket.c
net/sctp/stream.c
net/smc/af_smc.c
net/smc/smc_cdc.c
net/smc/smc_cdc.h
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_ism.c
net/smc/smc_ism.h
net/smc/smc_wr.c
net/socket.c
net/sunrpc/auth_generic.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/xdr.c
net/tipc/discover.c
net/tipc/net.c
net/tipc/net.h
net/tipc/node.c
net/tipc/socket.c
scripts/faddr2line
scripts/spdxcheck.py
security/integrity/digsig_asymmetric.c
security/selinux/hooks.c
security/selinux/ss/mls.c
sound/core/oss/pcm_oss.c
sound/core/oss/pcm_plugin.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_realtek.c
tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
tools/bpf/bpftool/Documentation/bpftool-map.rst
tools/bpf/bpftool/Documentation/bpftool-net.rst
tools/bpf/bpftool/Documentation/bpftool-perf.rst
tools/bpf/bpftool/Documentation/bpftool-prog.rst
tools/bpf/bpftool/Documentation/bpftool.rst
tools/bpf/bpftool/common.c
tools/bpf/bpftool/main.h
tools/bpf/bpftool/prog.c
tools/include/uapi/linux/pkt_cls.h [new file with mode: 0644]
tools/include/uapi/linux/tc_act/tc_bpf.h [new file with mode: 0644]
tools/power/cpupower/Makefile
tools/power/cpupower/bench/Makefile
tools/power/cpupower/debug/x86_64/Makefile
tools/power/cpupower/lib/cpufreq.c
tools/power/cpupower/lib/cpuidle.c
tools/power/cpupower/lib/cpupower.c
tools/power/cpupower/lib/cpupower_intern.h
tools/testing/nvdimm/test/nfit.c
tools/testing/selftests/bpf/test_netcnt.c
tools/testing/selftests/bpf/test_verifier.c
tools/testing/selftests/powerpc/mm/wild_bctr.c
tools/testing/selftests/tc-testing/tdc.py

diff --git a/CREDITS b/CREDITS
index 5befd2d714d0037548bed049a979dc4fcee1d300..84cbec4c62115adc38b976504b04799bb6fb0469 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2138,6 +2138,10 @@ E: paul@laufernet.com
 D: Soundblaster driver fixes, ISAPnP quirk
 S: California, USA
 
+N: Jarkko Lavinen
+E: jarkko.lavinen@nokia.com
+D: OMAP MMC support
+
 N: Jonathan Layes
 D: ARPD support
 
index 81d1d5a7472804e50a663480ef92dc67abc71ab5..19f4423e70d913ea2bf0801e4e14b57dc74e320f 100644 (file)
                                        prevent spurious wakeup);
                                n = USB_QUIRK_DELAY_CTRL_MSG (Device needs a
                                        pause after every control message);
+                               o = USB_QUIRK_HUB_SLOW_RESET (Hub needs extra
+                                       delay after resetting its port);
                        Example: quirks=0781:5580:bk,0a5c:5834:gij
 
        usbhid.mousepoll=
index 47153e64dfb530465ca01d28272e058293eb08b5..7eca9026a9ed2c3ed2a35b7e2184660e8caa9fdf 100644 (file)
@@ -150,7 +150,7 @@ data structures necessary to handle the given policy and, possibly, to add
 a governor ``sysfs`` interface to it.  Next, the governor is started by
 invoking its ``->start()`` callback.
 
-That callback it expected to register per-CPU utilization update callbacks for
+That callback is expected to register per-CPU utilization update callbacks for
 all of the online CPUs belonging to the given policy with the CPU scheduler.
 The utilization update callbacks will be invoked by the CPU scheduler on
 important events, like task enqueue and dequeue, on every iteration of the
index 164bf71149fdf2e6ad099b45196cbd6d1d8347cc..30187d49dc2c7d38869c4073e60093d315c3fc4e 100644 (file)
@@ -32,16 +32,17 @@ Disclosure and embargoed information
 The security list is not a disclosure channel.  For that, see Coordination
 below.
 
-Once a robust fix has been developed, our preference is to release the
-fix in a timely fashion, treating it no differently than any of the other
-thousands of changes and fixes the Linux kernel project releases every
-month.
-
-However, at the request of the reporter, we will postpone releasing the
-fix for up to 5 business days after the date of the report or after the
-embargo has lifted; whichever comes first.  The only exception to that
-rule is if the bug is publicly known, in which case the preference is to
-release the fix as soon as it's available.
+Once a robust fix has been developed, the release process starts.  Fixes
+for publicly known bugs are released immediately.
+
+Although our preference is to release fixes for publicly undisclosed bugs
+as soon as they become available, this may be postponed at the request of
+the reporter or an affected party for up to 7 calendar days from the start
+of the release process, with an exceptional extension to 14 calendar days
+if it is agreed that the criticality of the bug requires more time.  The
+only valid reason for deferring the publication of a fix is to accommodate
+the logistics of QA and large scale rollouts which require release
+coordination.
 
 Whilst embargoed information may be shared with trusted individuals in
 order to develop a fix, such information will not be published alongside
index a873855c811d63f3a47cd2ec830404abb89d48c8..14378cecb1723f7d9b4b4f3b0b1ccd0ca3126c26 100644 (file)
@@ -86,9 +86,11 @@ transitions.
 This will give a fine grained information about all the CPU frequency
 transitions. The cat output here is a two dimensional matrix, where an entry
 <i,j> (row i, column j) represents the count of number of transitions from 
-Freq_i to Freq_j. Freq_i is in descending order with increasing rows and 
-Freq_j is in descending order with increasing columns. The output here also 
-contains the actual freq values for each row and column for better readability.
+Freq_i to Freq_j. Freq_i rows and Freq_j columns follow the sorting order in
+which the driver has provided the frequency table initially to the cpufreq core
+and so can be sorted (ascending or descending) or unsorted.  The output here
+also contains the actual freq values for each row and column for better
+readability.
 
 If the transition table is bigger than PAGE_SIZE, reading this will
 return an -EFBIG error.
diff --git a/Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt b/Documentation/devicetree/bindings/cpufreq/arm_big_little_dt.txt
deleted file mode 100644 (file)
index 2aa06ac..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-Generic ARM big LITTLE cpufreq driver's DT glue
------------------------------------------------
-
-This is DT specific glue layer for generic cpufreq driver for big LITTLE
-systems.
-
-Both required and optional properties listed below must be defined
-under node /cpus/cpu@x. Where x is the first cpu inside a cluster.
-
-FIXME: Cpus should boot in the order specified in DT and all cpus for a cluster
-must be present contiguously. Generic DT driver will check only node 'x' for
-cpu:x.
-
-Required properties:
-- operating-points: Refer to Documentation/devicetree/bindings/opp/opp.txt
-  for details
-
-Optional properties:
-- clock-latency: Specify the possible maximum transition latency for clock,
-  in unit of nanoseconds.
-
-Examples:
-
-cpus {
-       #address-cells = <1>;
-       #size-cells = <0>;
-
-       cpu@0 {
-               compatible = "arm,cortex-a15";
-               reg = <0>;
-               next-level-cache = <&L2>;
-               operating-points = <
-                       /* kHz    uV */
-                       792000  1100000
-                       396000  950000
-                       198000  850000
-               >;
-               clock-latency = <61036>; /* two CLK32 periods */
-       };
-
-       cpu@1 {
-               compatible = "arm,cortex-a15";
-               reg = <1>;
-               next-level-cache = <&L2>;
-       };
-
-       cpu@100 {
-               compatible = "arm,cortex-a7";
-               reg = <100>;
-               next-level-cache = <&L2>;
-               operating-points = <
-                       /* kHz    uV */
-                       792000  950000
-                       396000  750000
-                       198000  450000
-               >;
-               clock-latency = <61036>; /* two CLK32 periods */
-       };
-
-       cpu@101 {
-               compatible = "arm,cortex-a7";
-               reg = <101>;
-               next-level-cache = <&L2>;
-       };
-};
index 903a78da65be288cf750af872584b60e9f42c06f..3a9926f99937039022d283817beac8e9bcbbc926 100644 (file)
@@ -17,7 +17,7 @@ Example:
                reg = <1>;
                clocks = <&clk32m>;
                interrupt-parent = <&gpio4>;
-               interrupts = <13 IRQ_TYPE_EDGE_RISING>;
+               interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
                vdd-supply = <&reg5v0>;
                xceiver-supply = <&reg5v0>;
        };
index cc4372842bf37670284d9b676699b5eb00882de9..9936b9ee67c36672afeb050a5641aa44cebbb728 100644 (file)
@@ -5,6 +5,7 @@ Required properties:
 - compatible: "renesas,can-r8a7743" if CAN controller is a part of R8A7743 SoC.
              "renesas,can-r8a7744" if CAN controller is a part of R8A7744 SoC.
              "renesas,can-r8a7745" if CAN controller is a part of R8A7745 SoC.
+             "renesas,can-r8a774a1" if CAN controller is a part of R8A774A1 SoC.
              "renesas,can-r8a7778" if CAN controller is a part of R8A7778 SoC.
              "renesas,can-r8a7779" if CAN controller is a part of R8A7779 SoC.
              "renesas,can-r8a7790" if CAN controller is a part of R8A7790 SoC.
@@ -14,26 +15,32 @@ Required properties:
              "renesas,can-r8a7794" if CAN controller is a part of R8A7794 SoC.
              "renesas,can-r8a7795" if CAN controller is a part of R8A7795 SoC.
              "renesas,can-r8a7796" if CAN controller is a part of R8A7796 SoC.
+             "renesas,can-r8a77965" if CAN controller is a part of R8A77965 SoC.
              "renesas,rcar-gen1-can" for a generic R-Car Gen1 compatible device.
              "renesas,rcar-gen2-can" for a generic R-Car Gen2 or RZ/G1
              compatible device.
-             "renesas,rcar-gen3-can" for a generic R-Car Gen3 compatible device.
+             "renesas,rcar-gen3-can" for a generic R-Car Gen3 or RZ/G2
+             compatible device.
              When compatible with the generic version, nodes must list the
              SoC-specific version corresponding to the platform first
              followed by the generic version.
 
 - reg: physical base address and size of the R-Car CAN register map.
 - interrupts: interrupt specifier for the sole interrupt.
-- clocks: phandles and clock specifiers for 3 CAN clock inputs.
-- clock-names: 3 clock input name strings: "clkp1", "clkp2", "can_clk".
+- clocks: phandles and clock specifiers for 2 CAN clock inputs for RZ/G2
+         devices.
+         phandles and clock specifiers for 3 CAN clock inputs for every other
+         SoC.
+- clock-names: 2 clock input name strings for RZ/G2: "clkp1", "can_clk".
+              3 clock input name strings for every other SoC: "clkp1", "clkp2",
+              "can_clk".
 - pinctrl-0: pin control group to be used for this controller.
 - pinctrl-names: must be "default".
 
-Required properties for "renesas,can-r8a7795" and "renesas,can-r8a7796"
-compatible:
-In R8A7795 and R8A7796 SoCs, "clkp2" can be CANFD clock. This is a div6 clock
-and can be used by both CAN and CAN FD controller at the same time. It needs to
-be scaled to maximum frequency if any of these controllers use it. This is done
+Required properties for R8A7795, R8A7796 and R8A77965:
+For the denoted SoCs, "clkp2" can be CANFD clock. This is a div6 clock and can
+be used by both CAN and CAN FD controller at the same time. It needs to be
+scaled to maximum frequency if any of these controllers use it. This is done
 using the below properties:
 
 - assigned-clocks: phandle of clkp2(CANFD) clock.
@@ -42,8 +49,9 @@ using the below properties:
 Optional properties:
 - renesas,can-clock-select: R-Car CAN Clock Source Select. Valid values are:
                            <0x0> (default) : Peripheral clock (clkp1)
-                           <0x1> : Peripheral clock (clkp2)
-                           <0x3> : Externally input clock
+                           <0x1> : Peripheral clock (clkp2) (not supported by
+                                   RZ/G2 devices)
+                           <0x3> : External input clock
 
 Example
 -------
index 3ceeb8de11963572cc1bd8ce324433e0dbf6bd03..35694c0c376b91c8b51982d1dce992682b983d92 100644 (file)
@@ -7,7 +7,7 @@ limitations.
 Current Binding
 ---------------
 
-Switches are true Linux devices and can be probes by any means. Once
+Switches are true Linux devices and can be probed by any means. Once
 probed, they register to the DSA framework, passing a node
 pointer. This node is expected to fulfil the following binding, and
 may contain additional properties as required by the device it is
index f7ac8d0d3af14a1a6d951df74847972220711133..b65dc078abeb8ca4a1a9a045eddc2d1b8844c333 100644 (file)
@@ -40,7 +40,7 @@ To use the :ref:`format` ioctls applications set the ``type`` field of the
 the desired operation. Both drivers and applications must set the remainder of
 the :c:type:`v4l2_format` structure to 0.
 
-.. _v4l2-meta-format:
+.. c:type:: v4l2_meta_format
 
 .. tabularcolumns:: |p{1.4cm}|p{2.2cm}|p{13.9cm}|
 
index 3ead350e099f97a6146ff98bf0126a8388149883..9ea494a8facab2cca0b51745cda1af6f0f53fd4c 100644 (file)
@@ -132,6 +132,11 @@ The format as returned by :ref:`VIDIOC_TRY_FMT <VIDIOC_G_FMT>` must be identical
       - ``sdr``
       - Definition of a data format, see :ref:`pixfmt`, used by SDR
        capture and output devices.
+    * -
+      - struct :c:type:`v4l2_meta_format`
+      - ``meta``
+      - Definition of a metadata format, see :ref:`meta-formats`, used by
+       metadata capture devices.
     * -
       - __u8
       - ``raw_data``\ [200]
index 605e00cdd6beb1d024519ab8417464fc12064724..89f1302d593a5c0404ed8a434ba580e8440a9139 100644 (file)
@@ -1056,18 +1056,23 @@ The kernel interface functions are as follows:
 
        u32 rxrpc_kernel_check_life(struct socket *sock,
                                    struct rxrpc_call *call);
+       void rxrpc_kernel_probe_life(struct socket *sock,
+                                    struct rxrpc_call *call);
 
-     This returns a number that is updated when ACKs are received from the peer
-     (notably including PING RESPONSE ACKs which we can elicit by sending PING
-     ACKs to see if the call still exists on the server).  The caller should
-     compare the numbers of two calls to see if the call is still alive after
-     waiting for a suitable interval.
+     The first function returns a number that is updated when ACKs are received
+     from the peer (notably including PING RESPONSE ACKs which we can elicit by
+     sending PING ACKs to see if the call still exists on the server).  The
+     caller should compare the numbers of two calls to see if the call is still
+     alive after waiting for a suitable interval.
 
      This allows the caller to work out if the server is still contactable and
      if the call is still alive on the server whilst waiting for the server to
      process a client operation.
 
-     This function may transmit a PING ACK.
+     The second function causes a ping ACK to be transmitted to try to provoke
+     the peer into responding, which would then cause the value returned by the
+     first function to change.  Note that this must be called in TASK_RUNNING
+     state.
 
  (*) Get reply timestamp.
 
index 0abecc528daca1cdaa564b36974c89b70229481f..bfaa411199021456f2f3d5f972672e60d4f154c5 100644 (file)
@@ -180,6 +180,7 @@ F:  drivers/net/hamradio/6pack.c
 
 8169 10/100/1000 GIGABIT ETHERNET DRIVER
 M:     Realtek linux nic maintainers <nic_swsd@realtek.com>
+M:     Heiner Kallweit <hkallweit1@gmail.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/realtek/r8169.c
@@ -717,7 +718,7 @@ F:  include/linux/mfd/altera-a10sr.h
 F:     include/dt-bindings/reset/altr,rst-mgr-a10sr.h
 
 ALTERA TRIPLE SPEED ETHERNET DRIVER
-M:     Vince Bridgers <vbridger@opensource.altera.com>
+M:     Thor Thayer <thor.thayer@linux.intel.com>
 L:     netdev@vger.kernel.org
 L:     nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
 S:     Maintained
@@ -2800,7 +2801,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
 Q:     https://patchwork.ozlabs.org/project/netdev/list/?delegate=77147
 S:     Supported
-F:     arch/x86/net/bpf_jit*
+F:     arch/*/net/*
 F:     Documentation/networking/filter.txt
 F:     Documentation/bpf/
 F:     include/linux/bpf*
@@ -2820,6 +2821,67 @@ F:       tools/bpf/
 F:     tools/lib/bpf/
 F:     tools/testing/selftests/bpf/
 
+BPF JIT for ARM
+M:     Shubham Bansal <illusionist.neo@gmail.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     arch/arm/net/
+
+BPF JIT for ARM64
+M:     Daniel Borkmann <daniel@iogearbox.net>
+M:     Alexei Starovoitov <ast@kernel.org>
+M:     Zi Shen Lim <zlim.lnx@gmail.com>
+L:     netdev@vger.kernel.org
+S:     Supported
+F:     arch/arm64/net/
+
+BPF JIT for MIPS (32-BIT AND 64-BIT)
+M:     Paul Burton <paul.burton@mips.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     arch/mips/net/
+
+BPF JIT for NFP NICs
+M:     Jakub Kicinski <jakub.kicinski@netronome.com>
+L:     netdev@vger.kernel.org
+S:     Supported
+F:     drivers/net/ethernet/netronome/nfp/bpf/
+
+BPF JIT for POWERPC (32-BIT AND 64-BIT)
+M:     Naveen N. Rao <naveen.n.rao@linux.ibm.com>
+M:     Sandipan Das <sandipan@linux.ibm.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     arch/powerpc/net/
+
+BPF JIT for S390
+M:     Martin Schwidefsky <schwidefsky@de.ibm.com>
+M:     Heiko Carstens <heiko.carstens@de.ibm.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     arch/s390/net/
+X:     arch/s390/net/pnet.c
+
+BPF JIT for SPARC (32-BIT AND 64-BIT)
+M:     David S. Miller <davem@davemloft.net>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     arch/sparc/net/
+
+BPF JIT for X86 32-BIT
+M:     Wang YanQing <udknight@gmail.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     arch/x86/net/bpf_jit_comp32.c
+
+BPF JIT for X86 64-BIT
+M:     Alexei Starovoitov <ast@kernel.org>
+M:     Daniel Borkmann <daniel@iogearbox.net>
+L:     netdev@vger.kernel.org
+S:     Supported
+F:     arch/x86/net/
+X:     arch/x86/net/bpf_jit_comp32.c
+
 BROADCOM B44 10/100 ETHERNET DRIVER
 M:     Michael Chan <michael.chan@broadcom.com>
 L:     netdev@vger.kernel.org
@@ -3276,6 +3338,12 @@ F:       include/uapi/linux/caif/
 F:     include/net/caif/
 F:     net/caif/
 
+CAKE QDISC
+M:     Toke Høiland-Jørgensen <toke@toke.dk>
+L:     cake@lists.bufferbloat.net (moderated for non-subscribers)
+S:     Maintained
+F:     net/sched/sch_cake.c
+
 CALGARY x86-64 IOMMU
 M:     Muli Ben-Yehuda <mulix@mulix.org>
 M:     Jon Mason <jdmason@kudzu.us>
@@ -5528,6 +5596,7 @@ F:        net/bridge/
 ETHERNET PHY LIBRARY
 M:     Andrew Lunn <andrew@lunn.ch>
 M:     Florian Fainelli <f.fainelli@gmail.com>
+M:     Heiner Kallweit <hkallweit1@gmail.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     Documentation/ABI/testing/sysfs-bus-mdio
@@ -6299,6 +6368,7 @@ F:        tools/testing/selftests/gpio/
 
 GPIO SUBSYSTEM
 M:     Linus Walleij <linus.walleij@linaro.org>
+M:     Bartosz Golaszewski <bgolaszewski@baylibre.com>
 L:     linux-gpio@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio.git
 S:     Maintained
@@ -7436,6 +7506,20 @@ S:       Maintained
 F:     Documentation/fb/intelfb.txt
 F:     drivers/video/fbdev/intelfb/
 
+INTEL GPIO DRIVERS
+M:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+L:     linux-gpio@vger.kernel.org
+S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git
+F:     drivers/gpio/gpio-ich.c
+F:     drivers/gpio/gpio-intel-mid.c
+F:     drivers/gpio/gpio-lynxpoint.c
+F:     drivers/gpio/gpio-merrifield.c
+F:     drivers/gpio/gpio-ml-ioh.c
+F:     drivers/gpio/gpio-pch.c
+F:     drivers/gpio/gpio-sch.c
+F:     drivers/gpio/gpio-sodaville.c
+
 INTEL GVT-g DRIVERS (Intel GPU Virtualization)
 M:     Zhenyu Wang <zhenyuw@linux.intel.com>
 M:     Zhi Wang <zhi.a.wang@intel.com>
@@ -7446,12 +7530,6 @@ T:       git https://github.com/intel/gvt-linux.git
 S:     Supported
 F:     drivers/gpu/drm/i915/gvt/
 
-INTEL PMIC GPIO DRIVER
-R:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-S:     Maintained
-F:     drivers/gpio/gpio-*cove.c
-F:     drivers/gpio/gpio-msic.c
-
 INTEL HID EVENT DRIVER
 M:     Alex Hung <alex.hung@canonical.com>
 L:     platform-driver-x86@vger.kernel.org
@@ -7539,12 +7617,6 @@ W:       https://01.org/linux-acpi
 S:     Supported
 F:     drivers/platform/x86/intel_menlow.c
 
-INTEL MERRIFIELD GPIO DRIVER
-M:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
-L:     linux-gpio@vger.kernel.org
-S:     Maintained
-F:     drivers/gpio/gpio-merrifield.c
-
 INTEL MIC DRIVERS (mic)
 M:     Sudeep Dutt <sudeep.dutt@intel.com>
 M:     Ashutosh Dixit <ashutosh.dixit@intel.com>
@@ -7577,6 +7649,13 @@ F:       drivers/platform/x86/intel_punit_ipc.c
 F:     arch/x86/include/asm/intel_pmc_ipc.h
 F:     arch/x86/include/asm/intel_punit_ipc.h
 
+INTEL PMIC GPIO DRIVERS
+M:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+S:     Maintained
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git
+F:     drivers/gpio/gpio-*cove.c
+F:     drivers/gpio/gpio-msic.c
+
 INTEL MULTIFUNCTION PMIC DEVICE DRIVERS
 R:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
 S:     Maintained
@@ -10808,9 +10887,9 @@ F:      drivers/media/platform/omap3isp/
 F:     drivers/staging/media/omap4iss/
 
 OMAP MMC SUPPORT
-M:     Jarkko Lavinen <jarkko.lavinen@nokia.com>
+M:     Aaro Koskinen <aaro.koskinen@iki.fi>
 L:     linux-omap@vger.kernel.org
-S:     Maintained
+S:     Odd Fixes
 F:     drivers/mmc/host/omap.c
 
 OMAP POWER MANAGEMENT SUPPORT
@@ -11745,6 +11824,7 @@ F:      Documentation/devicetree/bindings/pinctrl/fsl,*
 PIN CONTROLLER - INTEL
 M:     Mika Westerberg <mika.westerberg@linux.intel.com>
 M:     Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/pinctrl/intel.git
 S:     Maintained
 F:     drivers/pinctrl/intel/
 
@@ -14078,6 +14158,7 @@ F:      Documentation/devicetree/bindings/iio/proximity/vl53l0x.txt
 
 STABLE BRANCH
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+M:     Sasha Levin <sashal@kernel.org>
 L:     stable@vger.kernel.org
 S:     Supported
 F:     Documentation/process/stable-kernel-rules.rst
index 2f36db89789534f69abae6f23bb522f4300bc517..ddbf627cad8f5fd8a2d0d06a913294d88a0ff878 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 4
 PATCHLEVEL = 20
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME = "People's Front"
 
 # *DOCUMENTATION*
index 0d289240b6ca110ab961a280ddd20fc1c567f2a4..775cac3c02bb0a31facb970e16feef83f86c6632 100644 (file)
 #include <linux/kernel.h>
 
 extern unsigned int processor_id;
+struct proc_info_list *lookup_processor(u32 midr);
 
 #ifdef CONFIG_CPU_CP15
 #define read_cpuid(reg)                                                        \
index e25f4392e1b2868446de858701d408aaaee26eab..e1b6f280ab088fb0b8ac59b6ceb3543606c97e01 100644 (file)
@@ -23,7 +23,7 @@ struct mm_struct;
 /*
  * Don't change this structure - ASM code relies on it.
  */
-extern struct processor {
+struct processor {
        /* MISC
         * get data abort address/flags
         */
@@ -79,9 +79,13 @@ extern struct processor {
        unsigned int suspend_size;
        void (*do_suspend)(void *);
        void (*do_resume)(void *);
-} processor;
+};
 
 #ifndef MULTI_CPU
+static inline void init_proc_vtable(const struct processor *p)
+{
+}
+
 extern void cpu_proc_init(void);
 extern void cpu_proc_fin(void);
 extern int cpu_do_idle(void);
@@ -98,17 +102,50 @@ extern void cpu_reset(unsigned long addr, bool hvc) __attribute__((noreturn));
 extern void cpu_do_suspend(void *);
 extern void cpu_do_resume(void *);
 #else
-#define cpu_proc_init                  processor._proc_init
-#define cpu_proc_fin                   processor._proc_fin
-#define cpu_reset                      processor.reset
-#define cpu_do_idle                    processor._do_idle
-#define cpu_dcache_clean_area          processor.dcache_clean_area
-#define cpu_set_pte_ext                        processor.set_pte_ext
-#define cpu_do_switch_mm               processor.switch_mm
 
-/* These three are private to arch/arm/kernel/suspend.c */
-#define cpu_do_suspend                 processor.do_suspend
-#define cpu_do_resume                  processor.do_resume
+extern struct processor processor;
+#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+#include <linux/smp.h>
+/*
+ * This can't be a per-cpu variable because we need to access it before
+ * per-cpu has been initialised.  We have a couple of functions that are
+ * called in a pre-emptible context, and so can't use smp_processor_id()
+ * there, hence PROC_TABLE().  We insist in init_proc_vtable() that the
+ * function pointers for these are identical across all CPUs.
+ */
+extern struct processor *cpu_vtable[];
+#define PROC_VTABLE(f)                 cpu_vtable[smp_processor_id()]->f
+#define PROC_TABLE(f)                  cpu_vtable[0]->f
+static inline void init_proc_vtable(const struct processor *p)
+{
+       unsigned int cpu = smp_processor_id();
+       *cpu_vtable[cpu] = *p;
+       WARN_ON_ONCE(cpu_vtable[cpu]->dcache_clean_area !=
+                    cpu_vtable[0]->dcache_clean_area);
+       WARN_ON_ONCE(cpu_vtable[cpu]->set_pte_ext !=
+                    cpu_vtable[0]->set_pte_ext);
+}
+#else
+#define PROC_VTABLE(f)                 processor.f
+#define PROC_TABLE(f)                  processor.f
+static inline void init_proc_vtable(const struct processor *p)
+{
+       processor = *p;
+}
+#endif
+
+#define cpu_proc_init                  PROC_VTABLE(_proc_init)
+#define cpu_check_bugs                 PROC_VTABLE(check_bugs)
+#define cpu_proc_fin                   PROC_VTABLE(_proc_fin)
+#define cpu_reset                      PROC_VTABLE(reset)
+#define cpu_do_idle                    PROC_VTABLE(_do_idle)
+#define cpu_dcache_clean_area          PROC_TABLE(dcache_clean_area)
+#define cpu_set_pte_ext                        PROC_TABLE(set_pte_ext)
+#define cpu_do_switch_mm               PROC_VTABLE(switch_mm)
+
+/* These two are private to arch/arm/kernel/suspend.c */
+#define cpu_do_suspend                 PROC_VTABLE(do_suspend)
+#define cpu_do_resume                  PROC_VTABLE(do_resume)
 #endif
 
 extern void cpu_resume(void);
index 7be5113101915cd81a5558f45238041138fb5a58..d41d3598e5e541115c08f9b81b26fd187a7fe7af 100644 (file)
@@ -6,8 +6,8 @@
 void check_other_bugs(void)
 {
 #ifdef MULTI_CPU
-       if (processor.check_bugs)
-               processor.check_bugs();
+       if (cpu_check_bugs)
+               cpu_check_bugs();
 #endif
 }
 
index 6e0375e7db055bc82cf0674b37b74646e2d64ff0..997b02302c3145f5ac380ae18823eba50d916ac7 100644 (file)
@@ -145,6 +145,9 @@ __mmap_switched_data:
 #endif
        .size   __mmap_switched_data, . - __mmap_switched_data
 
+       __FINIT
+       .text
+
 /*
  * This provides a C-API version of __lookup_processor_type
  */
@@ -156,9 +159,6 @@ ENTRY(lookup_processor_type)
        ldmfd   sp!, {r4 - r6, r9, pc}
 ENDPROC(lookup_processor_type)
 
-       __FINIT
-       .text
-
 /*
  * Read processor ID register (CP#15, CR0), and look up in the linker-built
  * supported processor list.  Note that we can't use the absolute addresses
index ac7e08886863cfa74855e5b91c4f436e85da1e0a..375b13f7e780663eddb3f04e632751064a6b5bfd 100644 (file)
@@ -114,6 +114,11 @@ EXPORT_SYMBOL(elf_hwcap2);
 
 #ifdef MULTI_CPU
 struct processor processor __ro_after_init;
+#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+struct processor *cpu_vtable[NR_CPUS] = {
+       [0] = &processor,
+};
+#endif
 #endif
 #ifdef MULTI_TLB
 struct cpu_tlb_fns cpu_tlb __ro_after_init;
@@ -666,28 +671,33 @@ static void __init smp_build_mpidr_hash(void)
 }
 #endif
 
-static void __init setup_processor(void)
+/*
+ * locate processor in the list of supported processor types.  The linker
+ * builds this table for us from the entries in arch/arm/mm/proc-*.S
+ */
+struct proc_info_list *lookup_processor(u32 midr)
 {
-       struct proc_info_list *list;
+       struct proc_info_list *list = lookup_processor_type(midr);
 
-       /*
-        * locate processor in the list of supported processor
-        * types.  The linker builds this table for us from the
-        * entries in arch/arm/mm/proc-*.S
-        */
-       list = lookup_processor_type(read_cpuid_id());
        if (!list) {
-               pr_err("CPU configuration botched (ID %08x), unable to continue.\n",
-                      read_cpuid_id());
-               while (1);
+               pr_err("CPU%u: configuration botched (ID %08x), CPU halted\n",
+                      smp_processor_id(), midr);
+               while (1)
+               /* can't use cpu_relax() here as it may require MMU setup */;
        }
 
+       return list;
+}
+
+static void __init setup_processor(void)
+{
+       unsigned int midr = read_cpuid_id();
+       struct proc_info_list *list = lookup_processor(midr);
+
        cpu_name = list->cpu_name;
        __cpu_architecture = __get_cpu_architecture();
 
-#ifdef MULTI_CPU
-       processor = *list->proc;
-#endif
+       init_proc_vtable(list->proc);
 #ifdef MULTI_TLB
        cpu_tlb = *list->tlb;
 #endif
@@ -699,7 +709,7 @@ static void __init setup_processor(void)
 #endif
 
        pr_info("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
-               cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
+               list->cpu_name, midr, midr & 15,
                proc_arch[cpu_architecture()], get_cr());
 
        snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
index 0978282d5fc27a7c4a5e6b0e274da8bfc4c14c8d..12a6172263c0b057a94f2041accf581088374fb0 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/procinfo.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
@@ -102,6 +103,30 @@ static unsigned long get_arch_pgd(pgd_t *pgd)
 #endif
 }
 
+#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR)
+static int secondary_biglittle_prepare(unsigned int cpu)
+{
+       if (!cpu_vtable[cpu])
+               cpu_vtable[cpu] = kzalloc(sizeof(*cpu_vtable[cpu]), GFP_KERNEL);
+
+       return cpu_vtable[cpu] ? 0 : -ENOMEM;
+}
+
+static void secondary_biglittle_init(void)
+{
+       init_proc_vtable(lookup_processor(read_cpuid_id())->proc);
+}
+#else
+static int secondary_biglittle_prepare(unsigned int cpu)
+{
+       return 0;
+}
+
+static void secondary_biglittle_init(void)
+{
+}
+#endif
+
 int __cpu_up(unsigned int cpu, struct task_struct *idle)
 {
        int ret;
@@ -109,6 +134,10 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
        if (!smp_ops.smp_boot_secondary)
                return -ENOSYS;
 
+       ret = secondary_biglittle_prepare(cpu);
+       if (ret)
+               return ret;
+
        /*
         * We need to tell the secondary core where to find
         * its stack and the page tables.
@@ -359,6 +388,8 @@ asmlinkage void secondary_start_kernel(void)
        struct mm_struct *mm = &init_mm;
        unsigned int cpu;
 
+       secondary_biglittle_init();
+
        /*
         * The identity mapping is uncached (strongly ordered), so
         * switch away from it before attempting any exclusive accesses.
index 9500b6e2738019a4fb53e50c8150a2972ca8c391..f86b72d1d59e51f4af15319df87ee61141b4fd02 100644 (file)
@@ -209,11 +209,61 @@ static int __init omapdss_init_fbdev(void)
 
        return 0;
 }
-#else
-static inline int omapdss_init_fbdev(void)
+
+static const char * const omapdss_compat_names[] __initconst = {
+       "ti,omap2-dss",
+       "ti,omap3-dss",
+       "ti,omap4-dss",
+       "ti,omap5-dss",
+       "ti,dra7-dss",
+};
+
+static struct device_node * __init omapdss_find_dss_of_node(void)
 {
-       return 0;
+       struct device_node *node;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(omapdss_compat_names); ++i) {
+               node = of_find_compatible_node(NULL, NULL,
+                       omapdss_compat_names[i]);
+               if (node)
+                       return node;
+       }
+
+       return NULL;
 }
+
+static int __init omapdss_init_of(void)
+{
+       int r;
+       struct device_node *node;
+       struct platform_device *pdev;
+
+       /* only create dss helper devices if dss is enabled in the .dts */
+
+       node = omapdss_find_dss_of_node();
+       if (!node)
+               return 0;
+
+       if (!of_device_is_available(node))
+               return 0;
+
+       pdev = of_find_device_by_node(node);
+
+       if (!pdev) {
+               pr_err("Unable to find DSS platform device\n");
+               return -ENODEV;
+       }
+
+       r = of_platform_populate(node, NULL, NULL, &pdev->dev);
+       if (r) {
+               pr_err("Unable to populate DSS submodule devices\n");
+               return r;
+       }
+
+       return omapdss_init_fbdev();
+}
+omap_device_initcall(omapdss_init_of);
 #endif /* CONFIG_FB_OMAP2 */
 
 static void dispc_disable_outputs(void)
@@ -361,58 +411,3 @@ int omap_dss_reset(struct omap_hwmod *oh)
 
        return r;
 }
-
-static const char * const omapdss_compat_names[] __initconst = {
-       "ti,omap2-dss",
-       "ti,omap3-dss",
-       "ti,omap4-dss",
-       "ti,omap5-dss",
-       "ti,dra7-dss",
-};
-
-static struct device_node * __init omapdss_find_dss_of_node(void)
-{
-       struct device_node *node;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(omapdss_compat_names); ++i) {
-               node = of_find_compatible_node(NULL, NULL,
-                       omapdss_compat_names[i]);
-               if (node)
-                       return node;
-       }
-
-       return NULL;
-}
-
-static int __init omapdss_init_of(void)
-{
-       int r;
-       struct device_node *node;
-       struct platform_device *pdev;
-
-       /* only create dss helper devices if dss is enabled in the .dts */
-
-       node = omapdss_find_dss_of_node();
-       if (!node)
-               return 0;
-
-       if (!of_device_is_available(node))
-               return 0;
-
-       pdev = of_find_device_by_node(node);
-
-       if (!pdev) {
-               pr_err("Unable to find DSS platform device\n");
-               return -ENODEV;
-       }
-
-       r = of_platform_populate(node, NULL, NULL, &pdev->dev);
-       if (r) {
-               pr_err("Unable to populate DSS submodule devices\n");
-               return r;
-       }
-
-       return omapdss_init_fbdev();
-}
-omap_device_initcall(omapdss_init_of);
index 5544b82a2e7a553d015e23d77a9017682dd91f11..9a07916af8dd27dd021781c06451340ce6d03032 100644 (file)
@@ -52,8 +52,6 @@ static void cpu_v7_spectre_init(void)
        case ARM_CPU_PART_CORTEX_A17:
        case ARM_CPU_PART_CORTEX_A73:
        case ARM_CPU_PART_CORTEX_A75:
-               if (processor.switch_mm != cpu_v7_bpiall_switch_mm)
-                       goto bl_error;
                per_cpu(harden_branch_predictor_fn, cpu) =
                        harden_branch_predictor_bpiall;
                spectre_v2_method = "BPIALL";
@@ -61,8 +59,6 @@ static void cpu_v7_spectre_init(void)
 
        case ARM_CPU_PART_CORTEX_A15:
        case ARM_CPU_PART_BRAHMA_B15:
-               if (processor.switch_mm != cpu_v7_iciallu_switch_mm)
-                       goto bl_error;
                per_cpu(harden_branch_predictor_fn, cpu) =
                        harden_branch_predictor_iciallu;
                spectre_v2_method = "ICIALLU";
@@ -88,11 +84,9 @@ static void cpu_v7_spectre_init(void)
                                          ARM_SMCCC_ARCH_WORKAROUND_1, &res);
                        if ((int)res.a0 != 0)
                                break;
-                       if (processor.switch_mm != cpu_v7_hvc_switch_mm && cpu)
-                               goto bl_error;
                        per_cpu(harden_branch_predictor_fn, cpu) =
                                call_hvc_arch_workaround_1;
-                       processor.switch_mm = cpu_v7_hvc_switch_mm;
+                       cpu_do_switch_mm = cpu_v7_hvc_switch_mm;
                        spectre_v2_method = "hypervisor";
                        break;
 
@@ -101,11 +95,9 @@ static void cpu_v7_spectre_init(void)
                                          ARM_SMCCC_ARCH_WORKAROUND_1, &res);
                        if ((int)res.a0 != 0)
                                break;
-                       if (processor.switch_mm != cpu_v7_smc_switch_mm && cpu)
-                               goto bl_error;
                        per_cpu(harden_branch_predictor_fn, cpu) =
                                call_smc_arch_workaround_1;
-                       processor.switch_mm = cpu_v7_smc_switch_mm;
+                       cpu_do_switch_mm = cpu_v7_smc_switch_mm;
                        spectre_v2_method = "firmware";
                        break;
 
@@ -119,11 +111,6 @@ static void cpu_v7_spectre_init(void)
        if (spectre_v2_method)
                pr_info("CPU%u: Spectre v2: using %s workaround\n",
                        smp_processor_id(), spectre_v2_method);
-       return;
-
-bl_error:
-       pr_err("CPU%u: Spectre v2: incorrect context switching function, system vulnerable\n",
-               cpu);
 }
 #else
 static void cpu_v7_spectre_init(void)
index aff6e6eadc700f08241668e66c1235ea825217ce..ee7b07938dd59311f47fe5b385bcc27bfa4878f8 100644 (file)
@@ -573,7 +573,7 @@ int vfp_preserve_user_clear_hwstate(struct user_vfp *ufp,
         */
        ufp_exc->fpexc = hwstate->fpexc;
        ufp_exc->fpinst = hwstate->fpinst;
-       ufp_exc->fpinst2 = ufp_exc->fpinst2;
+       ufp_exc->fpinst2 = hwstate->fpinst2;
 
        /* Ensure that VFP is disabled. */
        vfp_flush_hwstate(thread);
index 0c909c4a932ff3da741fbda7c16cf6a3780d6107..842fb9572661063bd0db34b27e14d4829093208d 100644 (file)
                         SCTLR_ELx_SA     | SCTLR_ELx_I    | SCTLR_ELx_WXN | \
                         SCTLR_ELx_DSSBS | ENDIAN_CLEAR_EL2 | SCTLR_EL2_RES0)
 
-#if (SCTLR_EL2_SET ^ SCTLR_EL2_CLEAR) != 0xffffffffffffffff
+#if (SCTLR_EL2_SET ^ SCTLR_EL2_CLEAR) != 0xffffffffffffffffUL
 #error "Inconsistent SCTLR_EL2 set/clear bits"
 #endif
 
                         SCTLR_EL1_UMA | SCTLR_ELx_WXN     | ENDIAN_CLEAR_EL1 |\
                         SCTLR_ELx_DSSBS | SCTLR_EL1_NTWI  | SCTLR_EL1_RES0)
 
-#if (SCTLR_EL1_SET ^ SCTLR_EL1_CLEAR) != 0xffffffffffffffff
+#if (SCTLR_EL1_SET ^ SCTLR_EL1_CLEAR) != 0xffffffffffffffffUL
 #error "Inconsistent SCTLR_EL1 set/clear bits"
 #endif
 
index af50064dea51ad23c7c47cbe4786839fbf8603fa..aec5ecb85737edbe274b4f1c8a9082ac4a6947e1 100644 (file)
@@ -1333,7 +1333,6 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
                .cpu_enable = cpu_enable_hw_dbm,
        },
 #endif
-#ifdef CONFIG_ARM64_SSBD
        {
                .desc = "CRC32 instructions",
                .capability = ARM64_HAS_CRC32,
@@ -1343,6 +1342,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
                .field_pos = ID_AA64ISAR0_CRC32_SHIFT,
                .min_field_value = 1,
        },
+#ifdef CONFIG_ARM64_SSBD
        {
                .desc = "Speculative Store Bypassing Safe (SSBS)",
                .capability = ARM64_SSBS,
index 953e316521fcaa34fcbe26a9ca8ca7de6b9f51e9..f4fc1e0544b73c5c3785ee35a027ec6cb60623dd 100644 (file)
@@ -313,6 +313,7 @@ void __init setup_arch(char **cmdline_p)
        arm64_memblock_init();
 
        paging_init();
+       efi_apply_persistent_mem_reservations();
 
        acpi_table_upgrade();
 
index a6fdaea07c6339cf2754d582765747ee5d8b2ff5..89198017e8e681268504235331471b38b7e945b9 100644 (file)
@@ -351,7 +351,8 @@ static void build_epilogue(struct jit_ctx *ctx)
  * >0 - successfully JITed a 16-byte eBPF instruction.
  * <0 - failed to JIT.
  */
-static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
+static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
+                     bool extra_pass)
 {
        const u8 code = insn->code;
        const u8 dst = bpf2a64[insn->dst_reg];
@@ -625,12 +626,19 @@ emit_cond_jmp:
        case BPF_JMP | BPF_CALL:
        {
                const u8 r0 = bpf2a64[BPF_REG_0];
-               const u64 func = (u64)__bpf_call_base + imm;
+               bool func_addr_fixed;
+               u64 func_addr;
+               int ret;
 
-               if (ctx->prog->is_func)
-                       emit_addr_mov_i64(tmp, func, ctx);
+               ret = bpf_jit_get_func_addr(ctx->prog, insn, extra_pass,
+                                           &func_addr, &func_addr_fixed);
+               if (ret < 0)
+                       return ret;
+               if (func_addr_fixed)
+                       /* We can use optimized emission here. */
+                       emit_a64_mov_i64(tmp, func_addr, ctx);
                else
-                       emit_a64_mov_i64(tmp, func, ctx);
+                       emit_addr_mov_i64(tmp, func_addr, ctx);
                emit(A64_BLR(tmp), ctx);
                emit(A64_MOV(1, r0, A64_R(0)), ctx);
                break;
@@ -753,7 +761,7 @@ emit_cond_jmp:
        return 0;
 }
 
-static int build_body(struct jit_ctx *ctx)
+static int build_body(struct jit_ctx *ctx, bool extra_pass)
 {
        const struct bpf_prog *prog = ctx->prog;
        int i;
@@ -762,7 +770,7 @@ static int build_body(struct jit_ctx *ctx)
                const struct bpf_insn *insn = &prog->insnsi[i];
                int ret;
 
-               ret = build_insn(insn, ctx);
+               ret = build_insn(insn, ctx, extra_pass);
                if (ret > 0) {
                        i++;
                        if (ctx->image == NULL)
@@ -858,7 +866,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        /* 1. Initial fake pass to compute ctx->idx. */
 
        /* Fake pass to fill in ctx->offset. */
-       if (build_body(&ctx)) {
+       if (build_body(&ctx, extra_pass)) {
                prog = orig_prog;
                goto out_off;
        }
@@ -888,7 +896,7 @@ skip_init_ctx:
 
        build_prologue(&ctx, was_classic);
 
-       if (build_body(&ctx)) {
+       if (build_body(&ctx, extra_pass)) {
                bpf_jit_binary_free(header);
                prog = orig_prog;
                goto out_off;
index 490b12af103c1285043ecfec912b1839c5586f06..c52d0efacd1466f0320a025d3519ffb8ba212a09 100644 (file)
@@ -140,6 +140,7 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_STAGING=y
 CONFIG_OCTEON_ETHERNET=y
+CONFIG_OCTEON_USB=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_RAS=y
 CONFIG_EXT4_FS=y
index ea09ed6a80a9f2dc0aa625e2fcec0b34e2c6acea..8c6c48ed786a1527c22ba5b46bcdad70029e5865 100644 (file)
@@ -794,6 +794,7 @@ static void __init arch_mem_init(char **cmdline_p)
 
        /* call board setup routine */
        plat_mem_setup();
+       memblock_set_bottom_up(true);
 
        /*
         * Make sure all kernel memory is in the maps.  The "UP" and
index 0f852e1b589193d43f9125cfbfa303d6b47c6fed..15e103c6d799ebd90ad3f55a954c1d40329d5bac 100644 (file)
@@ -2260,10 +2260,8 @@ void __init trap_init(void)
                unsigned long size = 0x200 + VECTORSPACING*64;
                phys_addr_t ebase_pa;
 
-               memblock_set_bottom_up(true);
                ebase = (unsigned long)
                        memblock_alloc_from(size, 1 << fls(size), 0);
-               memblock_set_bottom_up(false);
 
                /*
                 * Try to ensure ebase resides in KSeg0 if possible.
@@ -2307,6 +2305,7 @@ void __init trap_init(void)
        if (board_ebase_setup)
                board_ebase_setup();
        per_cpu_trap_init(true);
+       memblock_set_bottom_up(false);
 
        /*
         * Copy the generic exception handlers to their final destination.
index 622761878cd11bd54e53affa43e5504c0aadc9c0..60bf0a1cb75719d731b60f8b2fe2954074dea77b 100644 (file)
@@ -231,6 +231,8 @@ static __init void prom_meminit(void)
                        cpumask_clear(&__node_data[(node)]->cpumask);
                }
        }
+       max_low_pfn = PHYS_PFN(memblock_end_of_DRAM());
+
        for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) {
                node = cpu / loongson_sysconf.cores_per_node;
                if (node >= num_online_nodes())
@@ -248,19 +250,9 @@ static __init void prom_meminit(void)
 
 void __init paging_init(void)
 {
-       unsigned node;
        unsigned long zones_size[MAX_NR_ZONES] = {0, };
 
        pagetable_init();
-
-       for_each_online_node(node) {
-               unsigned long  start_pfn, end_pfn;
-
-               get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
-
-               if (end_pfn > max_low_pfn)
-                       max_low_pfn = end_pfn;
-       }
 #ifdef CONFIG_ZONE_DMA32
        zones_size[ZONE_DMA32] = MAX_DMA32_PFN;
 #endif
index d8b8444d679527e3843ea1de091be70926355f34..813d13f92957ed00715ac5914d62dc09bcba1861 100644 (file)
@@ -435,6 +435,7 @@ void __init prom_meminit(void)
 
        mlreset();
        szmem();
+       max_low_pfn = PHYS_PFN(memblock_end_of_DRAM());
 
        for (node = 0; node < MAX_COMPACT_NODES; node++) {
                if (node_online(node)) {
@@ -455,18 +456,8 @@ extern void setup_zero_pages(void);
 void __init paging_init(void)
 {
        unsigned long zones_size[MAX_NR_ZONES] = {0, };
-       unsigned node;
 
        pagetable_init();
-
-       for_each_online_node(node) {
-               unsigned long start_pfn, end_pfn;
-
-               get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
-
-               if (end_pfn > max_low_pfn)
-                       max_low_pfn = end_pfn;
-       }
        zones_size[ZONE_NORMAL] = max_low_pfn;
        free_area_init_nodes(zones_size);
 }
index 16aec9ba2580a6dd3b3b9bfe03d29099815d2412..8a63515f03bfe3931930d094a479060815832fe6 100644 (file)
@@ -37,8 +37,8 @@ static inline void arch_spin_unlock(arch_spinlock_t *x)
        volatile unsigned int *a;
 
        a = __ldcw_align(x);
-       /* Release with ordered store. */
-       __asm__ __volatile__("stw,ma %0,0(%1)" : : "r"(1), "r"(a) : "memory");
+       mb();
+       *a = 1;
 }
 
 static inline int arch_spin_trylock(arch_spinlock_t *x)
index 9505c317818df77cb1e67ea39fa3b43110d32d16..a9bc90dc4ae75e4e0489a297ef64c645a9cc7557 100644 (file)
@@ -640,7 +640,8 @@ cas_action:
        sub,<>  %r28, %r25, %r0
 2:     stw     %r24, 0(%r26)
        /* Free lock */
-       stw,ma  %r20, 0(%sr2,%r20)
+       sync
+       stw     %r20, 0(%sr2,%r20)
 #if ENABLE_LWS_DEBUG
        /* Clear thread register indicator */
        stw     %r0, 4(%sr2,%r20)
@@ -654,7 +655,8 @@ cas_action:
 3:             
        /* Error occurred on load or store */
        /* Free lock */
-       stw,ma  %r20, 0(%sr2,%r20)
+       sync
+       stw     %r20, 0(%sr2,%r20)
 #if ENABLE_LWS_DEBUG
        stw     %r0, 4(%sr2,%r20)
 #endif
@@ -855,7 +857,8 @@ cas2_action:
 
 cas2_end:
        /* Free lock */
-       stw,ma  %r20, 0(%sr2,%r20)
+       sync
+       stw     %r20, 0(%sr2,%r20)
        /* Enable interrupts */
        ssm     PSW_SM_I, %r0
        /* Return to userspace, set no error */
@@ -865,7 +868,8 @@ cas2_end:
 22:
        /* Error occurred on load or store */
        /* Free lock */
-       stw,ma  %r20, 0(%sr2,%r20)
+       sync
+       stw     %r20, 0(%sr2,%r20)
        ssm     PSW_SM_I, %r0
        ldo     1(%r0),%r28
        b       lws_exit
index 3ef40b703c4ab86e7daf3982ae4781de8988b32f..e746becd9d6ff29c65ab0109fb82dd945a046f6d 100644 (file)
@@ -268,19 +268,13 @@ extern void _memcpy_toio(volatile void __iomem *dest, const void *src,
  * their hooks, a bitfield is reserved for use by the platform near the
  * top of MMIO addresses (not PIO, those have to cope the hard way).
  *
- * This bit field is 12 bits and is at the top of the IO virtual
- * addresses PCI_IO_INDIRECT_TOKEN_MASK.
+ * The highest address in the kernel virtual space are:
  *
- * The kernel virtual space is thus:
+ *  d0003fffffffffff   # with Hash MMU
+ *  c00fffffffffffff   # with Radix MMU
  *
- *  0xD000000000000000         : vmalloc
- *  0xD000080000000000         : PCI PHB IO space
- *  0xD000080080000000         : ioremap
- *  0xD0000fffffffffff         : end of ioremap region
- *
- * Since the top 4 bits are reserved as the region ID, we use thus
- * the next 12 bits and keep 4 bits available for the future if the
- * virtual address space is ever to be extended.
+ * The top 4 bits are reserved as the region ID on hash, leaving us 8 bits
+ * that can be used for the field.
  *
  * The direct IO mapping operations will then mask off those bits
  * before doing the actual access, though that only happen when
@@ -292,8 +286,8 @@ extern void _memcpy_toio(volatile void __iomem *dest, const void *src,
  */
 
 #ifdef CONFIG_PPC_INDIRECT_MMIO
-#define PCI_IO_IND_TOKEN_MASK  0x0fff000000000000ul
-#define PCI_IO_IND_TOKEN_SHIFT 48
+#define PCI_IO_IND_TOKEN_SHIFT 52
+#define PCI_IO_IND_TOKEN_MASK  (0xfful << PCI_IO_IND_TOKEN_SHIFT)
 #define PCI_FIX_ADDR(addr)                                             \
        ((PCI_IO_ADDR)(((unsigned long)(addr)) & ~PCI_IO_IND_TOKEN_MASK))
 #define PCI_GET_ADDR_TOKEN(addr)                                       \
index 6093bc8f74e518bf225c014c25521c8a515ba013..a6e9e314c7077044c0bb58590c95dddce4be8ed1 100644 (file)
                                        __PPC_RS(t) | __PPC_RA0(a) | __PPC_RB(b))
 #define PPC_SLBFEE_DOT(t, b)   stringify_in_c(.long PPC_INST_SLBFEE | \
                                        __PPC_RT(t) | __PPC_RB(b))
+#define __PPC_SLBFEE_DOT(t, b) stringify_in_c(.long PPC_INST_SLBFEE |  \
+                                              ___PPC_RT(t) | ___PPC_RB(b))
 #define PPC_ICBT(c,a,b)                stringify_in_c(.long PPC_INST_ICBT | \
                                       __PPC_CT(c) | __PPC_RA0(a) | __PPC_RB(b))
 /* PASemi instructions */
index f73886a1a7f51714da637c0f9c81a8dfd1107b7f..0b8a735b6d85f08512143b539c5ee5329598c48c 100644 (file)
@@ -54,6 +54,7 @@ struct pt_regs
 
 #ifdef CONFIG_PPC64
        unsigned long ppr;
+       unsigned long __pad;    /* Maintain 16 byte interrupt stack alignment */
 #endif
 };
 #endif
index 2a51e4cc8246d35d18d8ddd54b258af02dda47c4..236c1151a3a77057013313ed5da588673f5f3419 100644 (file)
@@ -636,6 +636,8 @@ static void *__init alloc_stack(unsigned long limit, int cpu)
 {
        unsigned long pa;
 
+       BUILD_BUG_ON(STACK_INT_FRAME_SIZE % 16);
+
        pa = memblock_alloc_base_nid(THREAD_SIZE, THREAD_SIZE, limit,
                                        early_cpu_to_node(cpu), MEMBLOCK_NONE);
        if (!pa) {
index 491b0f715d6bc2c345850645f2dbcd4700f6f182..ea1d7c80831900c4403443b8d836cd462998bf22 100644 (file)
@@ -6,8 +6,6 @@
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM kvm
-#define TRACE_INCLUDE_PATH .
-#define TRACE_INCLUDE_FILE trace
 
 /*
  * Tracepoint for guest mode entry.
@@ -120,4 +118,10 @@ TRACE_EVENT(kvm_check_requests,
 #endif /* _TRACE_KVM_H */
 
 /* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace
+
 #include <trace/define_trace.h>
index ac640e81fdc5f43709858ad8b3dd5ec2eee58a8f..3837842986aa46ee4ac80f4759d1051d9221c87c 100644 (file)
@@ -6,8 +6,6 @@
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM kvm_booke
-#define TRACE_INCLUDE_PATH .
-#define TRACE_INCLUDE_FILE trace_booke
 
 #define kvm_trace_symbol_exit \
        {0, "CRITICAL"}, \
@@ -218,4 +216,11 @@ TRACE_EVENT(kvm_booke_queue_irqprio,
 #endif
 
 /* This part must be outside protection */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_booke
+
 #include <trace/define_trace.h>
index bcfe8a987f6a977e65f2e9c7a02962a7099c2a66..8a1e3b0047f190e53a64dfe57c9c88f9ac11d617 100644 (file)
@@ -9,8 +9,6 @@
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM kvm_hv
-#define TRACE_INCLUDE_PATH .
-#define TRACE_INCLUDE_FILE trace_hv
 
 #define kvm_trace_symbol_hcall \
        {H_REMOVE,                      "H_REMOVE"}, \
@@ -497,4 +495,11 @@ TRACE_EVENT(kvmppc_run_vcpu_exit,
 #endif /* _TRACE_KVM_HV_H */
 
 /* This part must be outside protection */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_hv
+
 #include <trace/define_trace.h>
index 2f9a8829552b946ee8a308a2e069ab6a5c9bb1ba..46a46d328fbf2237dd203d3c33d54dbe0db129b1 100644 (file)
@@ -8,8 +8,6 @@
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM kvm_pr
-#define TRACE_INCLUDE_PATH .
-#define TRACE_INCLUDE_FILE trace_pr
 
 TRACE_EVENT(kvm_book3s_reenter,
        TP_PROTO(int r, struct kvm_vcpu *vcpu),
@@ -257,4 +255,11 @@ TRACE_EVENT(kvm_exit,
 #endif /* _TRACE_KVM_H */
 
 /* This part must be outside protection */
+
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_pr
+
 #include <trace/define_trace.h>
index 3a048e98a13231b6ce8ec239d91e98fe1ed2d3a9..ce28ae5ca08033ff36ee157e9b83be3a61d44f52 100644 (file)
@@ -1178,7 +1178,7 @@ static long vphn_get_associativity(unsigned long cpu,
 
        switch (rc) {
        case H_FUNCTION:
-               printk(KERN_INFO
+               printk_once(KERN_INFO
                        "VPHN is not supported. Disabling polling...\n");
                stop_topology_update();
                break;
index c3fdf2969d9faec5cacac62dfd9416011f9b17eb..bc3914d54e26ef8c400c65c92b8c359c171f8207 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/mmu.h>
 #include <asm/mmu_context.h>
 #include <asm/paca.h>
+#include <asm/ppc-opcode.h>
 #include <asm/cputable.h>
 #include <asm/cacheflush.h>
 #include <asm/smp.h>
@@ -58,27 +59,19 @@ static inline unsigned long mk_vsid_data(unsigned long ea, int ssize,
        return __mk_vsid_data(get_kernel_vsid(ea, ssize), ssize, flags);
 }
 
-static void assert_slb_exists(unsigned long ea)
+static void assert_slb_presence(bool present, unsigned long ea)
 {
 #ifdef CONFIG_DEBUG_VM
        unsigned long tmp;
 
        WARN_ON_ONCE(mfmsr() & MSR_EE);
 
-       asm volatile("slbfee. %0, %1" : "=r"(tmp) : "r"(ea) : "cr0");
-       WARN_ON(tmp == 0);
-#endif
-}
-
-static void assert_slb_notexists(unsigned long ea)
-{
-#ifdef CONFIG_DEBUG_VM
-       unsigned long tmp;
+       if (!cpu_has_feature(CPU_FTR_ARCH_206))
+               return;
 
-       WARN_ON_ONCE(mfmsr() & MSR_EE);
+       asm volatile(__PPC_SLBFEE_DOT(%0, %1) : "=r"(tmp) : "r"(ea) : "cr0");
 
-       asm volatile("slbfee. %0, %1" : "=r"(tmp) : "r"(ea) : "cr0");
-       WARN_ON(tmp != 0);
+       WARN_ON(present == (tmp == 0));
 #endif
 }
 
@@ -114,7 +107,7 @@ static inline void create_shadowed_slbe(unsigned long ea, int ssize,
         */
        slb_shadow_update(ea, ssize, flags, index);
 
-       assert_slb_notexists(ea);
+       assert_slb_presence(false, ea);
        asm volatile("slbmte  %0,%1" :
                     : "r" (mk_vsid_data(ea, ssize, flags)),
                       "r" (mk_esid_data(ea, ssize, index))
@@ -137,7 +130,7 @@ void __slb_restore_bolted_realmode(void)
                       "r" (be64_to_cpu(p->save_area[index].esid)));
        }
 
-       assert_slb_exists(local_paca->kstack);
+       assert_slb_presence(true, local_paca->kstack);
 }
 
 /*
@@ -185,7 +178,7 @@ void slb_flush_and_restore_bolted(void)
                     :: "r" (be64_to_cpu(p->save_area[KSTACK_INDEX].vsid)),
                        "r" (be64_to_cpu(p->save_area[KSTACK_INDEX].esid))
                     : "memory");
-       assert_slb_exists(get_paca()->kstack);
+       assert_slb_presence(true, get_paca()->kstack);
 
        get_paca()->slb_cache_ptr = 0;
 
@@ -443,9 +436,9 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
                                ea = (unsigned long)
                                        get_paca()->slb_cache[i] << SID_SHIFT;
                                /*
-                                * Could assert_slb_exists here, but hypervisor
-                                * or machine check could have come in and
-                                * removed the entry at this point.
+                                * Could assert_slb_presence(true) here, but
+                                * hypervisor or machine check could have come
+                                * in and removed the entry at this point.
                                 */
 
                                slbie_data = ea;
@@ -676,7 +669,7 @@ static long slb_insert_entry(unsigned long ea, unsigned long context,
         * User preloads should add isync afterwards in case the kernel
         * accesses user memory before it returns to userspace with rfid.
         */
-       assert_slb_notexists(ea);
+       assert_slb_presence(false, ea);
        asm volatile("slbmte %0, %1" : : "r" (vsid_data), "r" (esid_data));
 
        barrier();
@@ -715,7 +708,7 @@ static long slb_allocate_kernel(unsigned long ea, unsigned long id)
                        return -EFAULT;
 
                if (ea < H_VMALLOC_END)
-                       flags = get_paca()->vmalloc_sllp;
+                       flags = local_paca->vmalloc_sllp;
                else
                        flags = SLB_VSID_KERNEL | mmu_psize_defs[mmu_io_psize].sllp;
        } else {
index 50b129785aeeead06f8d131a64d30a6ccda2576e..17482f5de3e262f53d67b4199490660362b394a0 100644 (file)
@@ -166,7 +166,33 @@ static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
        PPC_BLR();
 }
 
-static void bpf_jit_emit_func_call(u32 *image, struct codegen_context *ctx, u64 func)
+static void bpf_jit_emit_func_call_hlp(u32 *image, struct codegen_context *ctx,
+                                      u64 func)
+{
+#ifdef PPC64_ELF_ABI_v1
+       /* func points to the function descriptor */
+       PPC_LI64(b2p[TMP_REG_2], func);
+       /* Load actual entry point from function descriptor */
+       PPC_BPF_LL(b2p[TMP_REG_1], b2p[TMP_REG_2], 0);
+       /* ... and move it to LR */
+       PPC_MTLR(b2p[TMP_REG_1]);
+       /*
+        * Load TOC from function descriptor at offset 8.
+        * We can clobber r2 since we get called through a
+        * function pointer (so caller will save/restore r2)
+        * and since we don't use a TOC ourself.
+        */
+       PPC_BPF_LL(2, b2p[TMP_REG_2], 8);
+#else
+       /* We can clobber r12 */
+       PPC_FUNC_ADDR(12, func);
+       PPC_MTLR(12);
+#endif
+       PPC_BLRL();
+}
+
+static void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx,
+                                      u64 func)
 {
        unsigned int i, ctx_idx = ctx->idx;
 
@@ -273,7 +299,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
 {
        const struct bpf_insn *insn = fp->insnsi;
        int flen = fp->len;
-       int i;
+       int i, ret;
 
        /* Start of epilogue code - will only be valid 2nd pass onwards */
        u32 exit_addr = addrs[flen];
@@ -284,8 +310,9 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
                u32 src_reg = b2p[insn[i].src_reg];
                s16 off = insn[i].off;
                s32 imm = insn[i].imm;
+               bool func_addr_fixed;
+               u64 func_addr;
                u64 imm64;
-               u8 *func;
                u32 true_cond;
                u32 tmp_idx;
 
@@ -711,23 +738,15 @@ emit_clear:
                case BPF_JMP | BPF_CALL:
                        ctx->seen |= SEEN_FUNC;
 
-                       /* bpf function call */
-                       if (insn[i].src_reg == BPF_PSEUDO_CALL)
-                               if (!extra_pass)
-                                       func = NULL;
-                               else if (fp->aux->func && off < fp->aux->func_cnt)
-                                       /* use the subprog id from the off
-                                        * field to lookup the callee address
-                                        */
-                                       func = (u8 *) fp->aux->func[off]->bpf_func;
-                               else
-                                       return -EINVAL;
-                       /* kernel helper call */
-                       else
-                               func = (u8 *) __bpf_call_base + imm;
-
-                       bpf_jit_emit_func_call(image, ctx, (u64)func);
+                       ret = bpf_jit_get_func_addr(fp, &insn[i], extra_pass,
+                                                   &func_addr, &func_addr_fixed);
+                       if (ret < 0)
+                               return ret;
 
+                       if (func_addr_fixed)
+                               bpf_jit_emit_func_call_hlp(image, ctx, func_addr);
+                       else
+                               bpf_jit_emit_func_call_rel(image, ctx, func_addr);
                        /* move return value from r3 to BPF_REG_0 */
                        PPC_MR(b2p[BPF_REG_0], 3);
                        break;
index 6f60e09319223015f5ebd36e3aa1fd9f66078520..75b9352529818899e99a978a4d85beeae535db90 100644 (file)
@@ -102,63 +102,6 @@ struct pci_dev *pnv_pci_get_npu_dev(struct pci_dev *gpdev, int index)
 }
 EXPORT_SYMBOL(pnv_pci_get_npu_dev);
 
-#define NPU_DMA_OP_UNSUPPORTED()                                       \
-       dev_err_once(dev, "%s operation unsupported for NVLink devices\n", \
-               __func__)
-
-static void *dma_npu_alloc(struct device *dev, size_t size,
-                          dma_addr_t *dma_handle, gfp_t flag,
-                          unsigned long attrs)
-{
-       NPU_DMA_OP_UNSUPPORTED();
-       return NULL;
-}
-
-static void dma_npu_free(struct device *dev, size_t size,
-                        void *vaddr, dma_addr_t dma_handle,
-                        unsigned long attrs)
-{
-       NPU_DMA_OP_UNSUPPORTED();
-}
-
-static dma_addr_t dma_npu_map_page(struct device *dev, struct page *page,
-                                  unsigned long offset, size_t size,
-                                  enum dma_data_direction direction,
-                                  unsigned long attrs)
-{
-       NPU_DMA_OP_UNSUPPORTED();
-       return 0;
-}
-
-static int dma_npu_map_sg(struct device *dev, struct scatterlist *sglist,
-                         int nelems, enum dma_data_direction direction,
-                         unsigned long attrs)
-{
-       NPU_DMA_OP_UNSUPPORTED();
-       return 0;
-}
-
-static int dma_npu_dma_supported(struct device *dev, u64 mask)
-{
-       NPU_DMA_OP_UNSUPPORTED();
-       return 0;
-}
-
-static u64 dma_npu_get_required_mask(struct device *dev)
-{
-       NPU_DMA_OP_UNSUPPORTED();
-       return 0;
-}
-
-static const struct dma_map_ops dma_npu_ops = {
-       .map_page               = dma_npu_map_page,
-       .map_sg                 = dma_npu_map_sg,
-       .alloc                  = dma_npu_alloc,
-       .free                   = dma_npu_free,
-       .dma_supported          = dma_npu_dma_supported,
-       .get_required_mask      = dma_npu_get_required_mask,
-};
-
 /*
  * Returns the PE assoicated with the PCI device of the given
  * NPU. Returns the linked pci device if pci_dev != NULL.
@@ -270,10 +213,11 @@ static void pnv_npu_dma_set_32(struct pnv_ioda_pe *npe)
        rc = pnv_npu_set_window(npe, 0, gpe->table_group.tables[0]);
 
        /*
-        * We don't initialise npu_pe->tce32_table as we always use
-        * dma_npu_ops which are nops.
+        * NVLink devices use the same TCE table configuration as
+        * their parent device so drivers shouldn't be doing DMA
+        * operations directly on these devices.
         */
-       set_dma_ops(&npe->pdev->dev, &dma_npu_ops);
+       set_dma_ops(&npe->pdev->dev, NULL);
 }
 
 /*
index d10146197533affd63c3e7392ccd73a4d7ba2e27..4b594f2e4f7ebd9eb791f6c2709f4023d3aa76c6 100644 (file)
@@ -71,10 +71,27 @@ KBUILD_CFLAGS += $(call cc-option,-mstrict-align)
 # arch specific predefines for sparse
 CHECKFLAGS += -D__riscv -D__riscv_xlen=$(BITS)
 
+# Default target when executing plain make
+boot           := arch/riscv/boot
+KBUILD_IMAGE   := $(boot)/Image.gz
+
 head-y := arch/riscv/kernel/head.o
 
 core-y += arch/riscv/kernel/ arch/riscv/mm/
 
 libs-y += arch/riscv/lib/
 
-all: vmlinux
+PHONY += vdso_install
+vdso_install:
+       $(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@
+
+all: Image.gz
+
+Image: vmlinux
+       $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+Image.%: Image
+       $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+zinstall install:
+       $(Q)$(MAKE) $(build)=$(boot) $@
diff --git a/arch/riscv/boot/.gitignore b/arch/riscv/boot/.gitignore
new file mode 100644 (file)
index 0000000..8dab0bb
--- /dev/null
@@ -0,0 +1,2 @@
+Image
+Image.gz
diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile
new file mode 100644 (file)
index 0000000..0990a9f
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# arch/riscv/boot/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2018, Anup Patel.
+# Author: Anup Patel <anup@brainfault.org>
+#
+# Based on the ia64 and arm64 boot/Makefile.
+#
+
+OBJCOPYFLAGS_Image :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
+
+targets := Image
+
+$(obj)/Image: vmlinux FORCE
+       $(call if_changed,objcopy)
+
+$(obj)/Image.gz: $(obj)/Image FORCE
+       $(call if_changed,gzip)
+
+install:
+       $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+       $(obj)/Image System.map "$(INSTALL_PATH)"
+
+zinstall:
+       $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+       $(obj)/Image.gz System.map "$(INSTALL_PATH)"
diff --git a/arch/riscv/boot/install.sh b/arch/riscv/boot/install.sh
new file mode 100644 (file)
index 0000000..18c3915
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# arch/riscv/boot/install.sh
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+# Adapted from code in arch/i386/boot/install.sh by Russell King
+#
+# "make install" script for the RISC-V Linux port
+#
+# Arguments:
+#   $1 - kernel version
+#   $2 - kernel image file
+#   $3 - kernel map file
+#   $4 - default install path (blank if root directory)
+#
+
+verify () {
+       if [ ! -f "$1" ]; then
+               echo ""                                                   1>&2
+               echo " *** Missing file: $1"                              1>&2
+               echo ' *** You need to run "make" before "make install".' 1>&2
+               echo ""                                                   1>&2
+               exit 1
+       fi
+}
+
+# Make sure the files actually exist
+verify "$2"
+verify "$3"
+
+# User may have a custom install script
+if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
+if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
+
+if [ "$(basename $2)" = "Image.gz" ]; then
+# Compressed install
+  echo "Installing compressed kernel"
+  base=vmlinuz
+else
+# Normal install
+  echo "Installing normal kernel"
+  base=vmlinux
+fi
+
+if [ -f $4/$base-$1 ]; then
+  mv $4/$base-$1 $4/$base-$1.old
+fi
+cat $2 > $4/$base-$1
+
+# Install system map file
+if [ -f $4/System.map-$1 ]; then
+  mv $4/System.map-$1 $4/System.map-$1.old
+fi
+cp $3 $4/System.map-$1
index 07fa9ea75fea1f1c72caaa6f246c28df86b6a532..ef4f15df9adf03c091bf621f900413680a2829f2 100644 (file)
@@ -76,4 +76,5 @@ CONFIG_NFS_V4_1=y
 CONFIG_NFS_V4_2=y
 CONFIG_ROOT_NFS=y
 CONFIG_CRYPTO_USER_API_HASH=y
+CONFIG_PRINTK_TIME=y
 # CONFIG_RCU_TRACE is not set
index 349df33808c4231d155d2e6018e19cc4cb19cb4d..cd2af4b013e3826e3b43f44565a9b6c1c6ae7b70 100644 (file)
@@ -8,6 +8,7 @@
 
 #define MODULE_ARCH_VERMAGIC    "riscv"
 
+struct module;
 u64 module_emit_got_entry(struct module *mod, u64 val);
 u64 module_emit_plt_entry(struct module *mod, u64 val);
 
index 2c5df945d43c9abfdfd197a61d8c92ce20e48133..bbe1862e8f80cd404164f03a485a89f253f9fa45 100644 (file)
@@ -56,8 +56,8 @@ struct pt_regs {
        unsigned long sstatus;
        unsigned long sbadaddr;
        unsigned long scause;
-        /* a0 value before the syscall */
-        unsigned long orig_a0;
+       /* a0 value before the syscall */
+       unsigned long orig_a0;
 };
 
 #ifdef CONFIG_64BIT
index 473cfc84e412f3827703caaadffa34a8983c978d..8c3e3e3c8be1204b67076985a9b54e80217707b1 100644 (file)
@@ -400,13 +400,13 @@ extern unsigned long __must_check __asm_copy_from_user(void *to,
 static inline unsigned long
 raw_copy_from_user(void *to, const void __user *from, unsigned long n)
 {
-       return __asm_copy_to_user(to, from, n);
+       return __asm_copy_from_user(to, from, n);
 }
 
 static inline unsigned long
 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
 {
-       return __asm_copy_from_user(to, from, n);
+       return __asm_copy_to_user(to, from, n);
 }
 
 extern long strncpy_from_user(char *dest, const char __user *src, long count);
index eff7aa9aa1637851aadd871807644560bef5c412..fef96f117b4def3fe9a99ec9ca8b26d2278e087c 100644 (file)
 
 /*
  * There is explicitly no include guard here because this file is expected to
- * be included multiple times.  See uapi/asm/syscalls.h for more info.
+ * be included multiple times.
  */
 
-#define __ARCH_WANT_NEW_STAT
 #define __ARCH_WANT_SYS_CLONE
+
 #include <uapi/asm/unistd.h>
-#include <uapi/asm/syscalls.h>
diff --git a/arch/riscv/include/uapi/asm/syscalls.h b/arch/riscv/include/uapi/asm/syscalls.h
deleted file mode 100644 (file)
index 206dc4b..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2017-2018 SiFive
- */
-
-/*
- * There is explicitly no include guard here because this file is expected to
- * be included multiple times in order to define the syscall macros via
- * __SYSCALL.
- */
-
-/*
- * Allows the instruction cache to be flushed from userspace.  Despite RISC-V
- * having a direct 'fence.i' instruction available to userspace (which we
- * can't trap!), that's not actually viable when running on Linux because the
- * kernel might schedule a process on another hart.  There is no way for
- * userspace to handle this without invoking the kernel (as it doesn't know the
- * thread->hart mappings), so we've defined a RISC-V specific system call to
- * flush the instruction cache.
- *
- * __NR_riscv_flush_icache is defined to flush the instruction cache over an
- * address range, with the flush applying to either all threads or just the
- * caller.  We don't currently do anything with the address range, that's just
- * in there for forwards compatibility.
- */
-#ifndef __NR_riscv_flush_icache
-#define __NR_riscv_flush_icache (__NR_arch_specific_syscall + 15)
-#endif
-__SYSCALL(__NR_riscv_flush_icache, sys_riscv_flush_icache)
diff --git a/arch/riscv/include/uapi/asm/unistd.h b/arch/riscv/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..1f3bd3e
--- /dev/null
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (C) 2018 David Abdurachmanov <david.abdurachmanov@gmail.com>
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef __LP64__
+#define __ARCH_WANT_NEW_STAT
+#endif /* __LP64__ */
+
+#include <asm-generic/unistd.h>
+
+/*
+ * Allows the instruction cache to be flushed from userspace.  Despite RISC-V
+ * having a direct 'fence.i' instruction available to userspace (which we
+ * can't trap!), that's not actually viable when running on Linux because the
+ * kernel might schedule a process on another hart.  There is no way for
+ * userspace to handle this without invoking the kernel (as it doesn't know the
+ * thread->hart mappings), so we've defined a RISC-V specific system call to
+ * flush the instruction cache.
+ *
+ * __NR_riscv_flush_icache is defined to flush the instruction cache over an
+ * address range, with the flush applying to either all threads or just the
+ * caller.  We don't currently do anything with the address range, that's just
+ * in there for forwards compatibility.
+ */
+#ifndef __NR_riscv_flush_icache
+#define __NR_riscv_flush_icache (__NR_arch_specific_syscall + 15)
+#endif
+__SYSCALL(__NR_riscv_flush_icache, sys_riscv_flush_icache)
index 3a5a2ee31547b2ca1f3ec0f0cf613ff3448e85e3..b4a7d4427fbb9430e02cdc1855729a9eba90c815 100644 (file)
@@ -64,7 +64,7 @@ int riscv_of_processor_hartid(struct device_node *node)
 
 static void print_isa(struct seq_file *f, const char *orig_isa)
 {
-       static const char *ext = "mafdc";
+       static const char *ext = "mafdcsu";
        const char *isa = orig_isa;
        const char *e;
 
@@ -88,11 +88,14 @@ static void print_isa(struct seq_file *f, const char *orig_isa)
        /*
         * Check the rest of the ISA string for valid extensions, printing those
         * we find.  RISC-V ISA strings define an order, so we only print the
-        * extension bits when they're in order.
+        * extension bits when they're in order. Hide the supervisor (S)
+        * extension from userspace as it's not accessible from there.
         */
        for (e = ext; *e != '\0'; ++e) {
                if (isa[0] == e[0]) {
-                       seq_write(f, isa, 1);
+                       if (isa[0] != 's')
+                               seq_write(f, isa, 1);
+
                        isa++;
                }
        }
index 711190d473d41f47dd52f9fc4720df720ebf57be..fe884cd69abd8f0d7b3fe3a9e20b781937a32502 100644 (file)
@@ -44,6 +44,16 @@ ENTRY(_start)
        amoadd.w a3, a2, (a3)
        bnez a3, .Lsecondary_start
 
+       /* Clear BSS for flat non-ELF images */
+       la a3, __bss_start
+       la a4, __bss_stop
+       ble a4, a3, clear_bss_done
+clear_bss:
+       REG_S zero, (a3)
+       add a3, a3, RISCV_SZPTR
+       blt a3, a4, clear_bss
+clear_bss_done:
+
        /* Save hart ID and DTB physical address */
        mv s0, a0
        mv s1, a1
index 3303ed2cd4193f82c51730a992d6c875b361ff80..7dd308129b40f1862ab04dc1e12c790bf7c111fe 100644 (file)
@@ -21,7 +21,7 @@ static int apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v)
 {
        if (v != (u32)v) {
                pr_err("%s: value %016llx out of range for 32-bit field\n",
-                      me->name, v);
+                      me->name, (long long)v);
                return -EINVAL;
        }
        *location = v;
@@ -102,7 +102,7 @@ static int apply_r_riscv_pcrel_hi20_rela(struct module *me, u32 *location,
        if (offset != (s32)offset) {
                pr_err(
                  "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
-                 me->name, v, location);
+                 me->name, (long long)v, location);
                return -EINVAL;
        }
 
@@ -144,7 +144,7 @@ static int apply_r_riscv_hi20_rela(struct module *me, u32 *location,
        if (IS_ENABLED(CMODEL_MEDLOW)) {
                pr_err(
                  "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
-                 me->name, v, location);
+                 me->name, (long long)v, location);
                return -EINVAL;
        }
 
@@ -188,7 +188,7 @@ static int apply_r_riscv_got_hi20_rela(struct module *me, u32 *location,
        } else {
                pr_err(
                  "%s: can not generate the GOT entry for symbol = %016llx from PC = %p\n",
-                 me->name, v, location);
+                 me->name, (long long)v, location);
                return -EINVAL;
        }
 
@@ -212,7 +212,7 @@ static int apply_r_riscv_call_plt_rela(struct module *me, u32 *location,
                } else {
                        pr_err(
                          "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
-                         me->name, v, location);
+                         me->name, (long long)v, location);
                        return -EINVAL;
                }
        }
@@ -234,7 +234,7 @@ static int apply_r_riscv_call_rela(struct module *me, u32 *location,
        if (offset != fill_v) {
                pr_err(
                  "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
-                 me->name, v, location);
+                 me->name, (long long)v, location);
                return -EINVAL;
        }
 
index ece84991609ca56d2d3549d1a2dde2139a943028..65df1dfdc30385be7a9a149034a0ba66a5bbbd8e 100644 (file)
@@ -74,7 +74,7 @@ SECTIONS
                *(.sbss*)
        }
 
-       BSS_SECTION(0, 0, 0)
+       BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0)
 
        EXCEPTION_TABLE(0x10)
        NOTES
index 5739bd05d289e5034b5d9faee2baebb1be1251ed..4e2e600f7d5384074fff062628cbb04f9113f7ab 100644 (file)
@@ -3,6 +3,6 @@ lib-y   += memcpy.o
 lib-y  += memset.o
 lib-y  += uaccess.o
 
-lib-(CONFIG_64BIT) += tishift.o
+lib-$(CONFIG_64BIT) += tishift.o
 
 lib-$(CONFIG_32BIT) += udivdi3.o
index 222785af550b46736676808b6e00d8d8cef9a286..5fda4f7bf15d176fbb913435ea0a25c510c8df5a 100644 (file)
@@ -791,7 +791,7 @@ static int emit_compare_and_branch(const u8 code, const u8 dst, u8 src,
 }
 
 /* Just skip the save instruction and the ctx register move.  */
-#define BPF_TAILCALL_PROLOGUE_SKIP     16
+#define BPF_TAILCALL_PROLOGUE_SKIP     32
 #define BPF_TAILCALL_CNT_SP_OFF                (STACK_BIAS + 128)
 
 static void build_prologue(struct jit_ctx *ctx)
@@ -824,9 +824,15 @@ static void build_prologue(struct jit_ctx *ctx)
                const u8 vfp = bpf2sparc[BPF_REG_FP];
 
                emit(ADD | IMMED | RS1(FP) | S13(STACK_BIAS) | RD(vfp), ctx);
+       } else {
+               emit_nop(ctx);
        }
 
        emit_reg_move(I0, O0, ctx);
+       emit_reg_move(I1, O1, ctx);
+       emit_reg_move(I2, O2, ctx);
+       emit_reg_move(I3, O3, ctx);
+       emit_reg_move(I4, O4, ctx);
        /* If you add anything here, adjust BPF_TAILCALL_PROLOGUE_SKIP above. */
 }
 
@@ -1270,6 +1276,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                const u8 tmp2 = bpf2sparc[TMP_REG_2];
                u32 opcode = 0, rs2;
 
+               if (insn->dst_reg == BPF_REG_FP)
+                       ctx->saw_frame_pointer = true;
+
                ctx->tmp_2_used = true;
                emit_loadimm(imm, tmp2, ctx);
 
@@ -1308,6 +1317,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                const u8 tmp = bpf2sparc[TMP_REG_1];
                u32 opcode = 0, rs2;
 
+               if (insn->dst_reg == BPF_REG_FP)
+                       ctx->saw_frame_pointer = true;
+
                switch (BPF_SIZE(code)) {
                case BPF_W:
                        opcode = ST32;
@@ -1340,6 +1352,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                const u8 tmp2 = bpf2sparc[TMP_REG_2];
                const u8 tmp3 = bpf2sparc[TMP_REG_3];
 
+               if (insn->dst_reg == BPF_REG_FP)
+                       ctx->saw_frame_pointer = true;
+
                ctx->tmp_1_used = true;
                ctx->tmp_2_used = true;
                ctx->tmp_3_used = true;
@@ -1360,6 +1375,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                const u8 tmp2 = bpf2sparc[TMP_REG_2];
                const u8 tmp3 = bpf2sparc[TMP_REG_3];
 
+               if (insn->dst_reg == BPF_REG_FP)
+                       ctx->saw_frame_pointer = true;
+
                ctx->tmp_1_used = true;
                ctx->tmp_2_used = true;
                ctx->tmp_3_used = true;
@@ -1425,12 +1443,12 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        struct bpf_prog *tmp, *orig_prog = prog;
        struct sparc64_jit_data *jit_data;
        struct bpf_binary_header *header;
+       u32 prev_image_size, image_size;
        bool tmp_blinded = false;
        bool extra_pass = false;
        struct jit_ctx ctx;
-       u32 image_size;
        u8 *image_ptr;
-       int pass;
+       int pass, i;
 
        if (!prog->jit_requested)
                return orig_prog;
@@ -1461,61 +1479,82 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
                header = jit_data->header;
                extra_pass = true;
                image_size = sizeof(u32) * ctx.idx;
+               prev_image_size = image_size;
+               pass = 1;
                goto skip_init_ctx;
        }
 
        memset(&ctx, 0, sizeof(ctx));
        ctx.prog = prog;
 
-       ctx.offset = kcalloc(prog->len, sizeof(unsigned int), GFP_KERNEL);
+       ctx.offset = kmalloc_array(prog->len, sizeof(unsigned int), GFP_KERNEL);
        if (ctx.offset == NULL) {
                prog = orig_prog;
                goto out_off;
        }
 
-       /* Fake pass to detect features used, and get an accurate assessment
-        * of what the final image size will be.
+       /* Longest sequence emitted is for bswap32, 12 instructions.  Pre-cook
+        * the offset array so that we converge faster.
         */
-       if (build_body(&ctx)) {
-               prog = orig_prog;
-               goto out_off;
-       }
-       build_prologue(&ctx);
-       build_epilogue(&ctx);
-
-       /* Now we know the actual image size. */
-       image_size = sizeof(u32) * ctx.idx;
-       header = bpf_jit_binary_alloc(image_size, &image_ptr,
-                                     sizeof(u32), jit_fill_hole);
-       if (header == NULL) {
-               prog = orig_prog;
-               goto out_off;
-       }
+       for (i = 0; i < prog->len; i++)
+               ctx.offset[i] = i * (12 * 4);
 
-       ctx.image = (u32 *)image_ptr;
-skip_init_ctx:
-       for (pass = 1; pass < 3; pass++) {
+       prev_image_size = ~0U;
+       for (pass = 1; pass < 40; pass++) {
                ctx.idx = 0;
 
                build_prologue(&ctx);
-
                if (build_body(&ctx)) {
-                       bpf_jit_binary_free(header);
                        prog = orig_prog;
                        goto out_off;
                }
-
                build_epilogue(&ctx);
 
                if (bpf_jit_enable > 1)
-                       pr_info("Pass %d: shrink = %d, seen = [%c%c%c%c%c%c]\n", pass,
-                               image_size - (ctx.idx * 4),
+                       pr_info("Pass %d: size = %u, seen = [%c%c%c%c%c%c]\n", pass,
+                               ctx.idx * 4,
                                ctx.tmp_1_used ? '1' : ' ',
                                ctx.tmp_2_used ? '2' : ' ',
                                ctx.tmp_3_used ? '3' : ' ',
                                ctx.saw_frame_pointer ? 'F' : ' ',
                                ctx.saw_call ? 'C' : ' ',
                                ctx.saw_tail_call ? 'T' : ' ');
+
+               if (ctx.idx * 4 == prev_image_size)
+                       break;
+               prev_image_size = ctx.idx * 4;
+               cond_resched();
+       }
+
+       /* Now we know the actual image size. */
+       image_size = sizeof(u32) * ctx.idx;
+       header = bpf_jit_binary_alloc(image_size, &image_ptr,
+                                     sizeof(u32), jit_fill_hole);
+       if (header == NULL) {
+               prog = orig_prog;
+               goto out_off;
+       }
+
+       ctx.image = (u32 *)image_ptr;
+skip_init_ctx:
+       ctx.idx = 0;
+
+       build_prologue(&ctx);
+
+       if (build_body(&ctx)) {
+               bpf_jit_binary_free(header);
+               prog = orig_prog;
+               goto out_off;
+       }
+
+       build_epilogue(&ctx);
+
+       if (ctx.idx * 4 != prev_image_size) {
+               pr_err("bpf_jit: Failed to converge, prev_size=%u size=%d\n",
+                      prev_image_size, ctx.idx * 4);
+               bpf_jit_binary_free(header);
+               prog = orig_prog;
+               goto out_off;
        }
 
        if (bpf_jit_enable > 1)
index e17ab885b1e928d17a671eb96f12cf21905bdb93..cb46d602a6b8bd17eb458f84778019b56b15a93c 100644 (file)
@@ -129,8 +129,15 @@ struct intel_uncore_box {
        struct intel_uncore_extra_reg shared_regs[0];
 };
 
-#define UNCORE_BOX_FLAG_INITIATED      0
-#define UNCORE_BOX_FLAG_CTL_OFFS8      1 /* event config registers are 8-byte apart */
+/* CFL uncore 8th cbox MSRs */
+#define CFL_UNC_CBO_7_PERFEVTSEL0              0xf70
+#define CFL_UNC_CBO_7_PER_CTR0                 0xf76
+
+#define UNCORE_BOX_FLAG_INITIATED              0
+/* event config registers are 8-byte apart */
+#define UNCORE_BOX_FLAG_CTL_OFFS8              1
+/* CFL 8th CBOX has different MSR space */
+#define UNCORE_BOX_FLAG_CFL8_CBOX_MSR_OFFS     2
 
 struct uncore_event_desc {
        struct kobj_attribute attr;
@@ -297,17 +304,27 @@ unsigned int uncore_freerunning_counter(struct intel_uncore_box *box,
 static inline
 unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx)
 {
-       return box->pmu->type->event_ctl +
-               (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) +
-               uncore_msr_box_offset(box);
+       if (test_bit(UNCORE_BOX_FLAG_CFL8_CBOX_MSR_OFFS, &box->flags)) {
+               return CFL_UNC_CBO_7_PERFEVTSEL0 +
+                      (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx);
+       } else {
+               return box->pmu->type->event_ctl +
+                      (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) +
+                      uncore_msr_box_offset(box);
+       }
 }
 
 static inline
 unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx)
 {
-       return box->pmu->type->perf_ctr +
-               (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) +
-               uncore_msr_box_offset(box);
+       if (test_bit(UNCORE_BOX_FLAG_CFL8_CBOX_MSR_OFFS, &box->flags)) {
+               return CFL_UNC_CBO_7_PER_CTR0 +
+                      (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx);
+       } else {
+               return box->pmu->type->perf_ctr +
+                      (box->pmu->type->pair_ctr_ctl ? 2 * idx : idx) +
+                      uncore_msr_box_offset(box);
+       }
 }
 
 static inline
index 8527c3e1038b78d868743274c35368ab318649ca..2593b0d7aeee6089413d980618ce07c35d84c101 100644 (file)
 #define PCI_DEVICE_ID_INTEL_SKL_HQ_IMC 0x1910
 #define PCI_DEVICE_ID_INTEL_SKL_SD_IMC 0x190f
 #define PCI_DEVICE_ID_INTEL_SKL_SQ_IMC 0x191f
+#define PCI_DEVICE_ID_INTEL_KBL_Y_IMC  0x590c
+#define PCI_DEVICE_ID_INTEL_KBL_U_IMC  0x5904
+#define PCI_DEVICE_ID_INTEL_KBL_UQ_IMC 0x5914
+#define PCI_DEVICE_ID_INTEL_KBL_SD_IMC 0x590f
+#define PCI_DEVICE_ID_INTEL_KBL_SQ_IMC 0x591f
+#define PCI_DEVICE_ID_INTEL_CFL_2U_IMC 0x3ecc
+#define PCI_DEVICE_ID_INTEL_CFL_4U_IMC 0x3ed0
+#define PCI_DEVICE_ID_INTEL_CFL_4H_IMC 0x3e10
+#define PCI_DEVICE_ID_INTEL_CFL_6H_IMC 0x3ec4
+#define PCI_DEVICE_ID_INTEL_CFL_2S_D_IMC       0x3e0f
+#define PCI_DEVICE_ID_INTEL_CFL_4S_D_IMC       0x3e1f
+#define PCI_DEVICE_ID_INTEL_CFL_6S_D_IMC       0x3ec2
+#define PCI_DEVICE_ID_INTEL_CFL_8S_D_IMC       0x3e30
+#define PCI_DEVICE_ID_INTEL_CFL_4S_W_IMC       0x3e18
+#define PCI_DEVICE_ID_INTEL_CFL_6S_W_IMC       0x3ec6
+#define PCI_DEVICE_ID_INTEL_CFL_8S_W_IMC       0x3e31
+#define PCI_DEVICE_ID_INTEL_CFL_4S_S_IMC       0x3e33
+#define PCI_DEVICE_ID_INTEL_CFL_6S_S_IMC       0x3eca
+#define PCI_DEVICE_ID_INTEL_CFL_8S_S_IMC       0x3e32
 
 /* SNB event control */
 #define SNB_UNC_CTL_EV_SEL_MASK                        0x000000ff
@@ -202,6 +221,10 @@ static void skl_uncore_msr_init_box(struct intel_uncore_box *box)
                wrmsrl(SKL_UNC_PERF_GLOBAL_CTL,
                        SNB_UNC_GLOBAL_CTL_EN | SKL_UNC_GLOBAL_CTL_CORE_ALL);
        }
+
+       /* The 8th CBOX has different MSR space */
+       if (box->pmu->pmu_idx == 7)
+               __set_bit(UNCORE_BOX_FLAG_CFL8_CBOX_MSR_OFFS, &box->flags);
 }
 
 static void skl_uncore_msr_enable_box(struct intel_uncore_box *box)
@@ -228,7 +251,7 @@ static struct intel_uncore_ops skl_uncore_msr_ops = {
 static struct intel_uncore_type skl_uncore_cbox = {
        .name           = "cbox",
        .num_counters   = 4,
-       .num_boxes      = 5,
+       .num_boxes      = 8,
        .perf_ctr_bits  = 44,
        .fixed_ctr_bits = 48,
        .perf_ctr       = SNB_UNC_CBO_0_PER_CTR0,
@@ -569,7 +592,82 @@ static const struct pci_device_id skl_uncore_pci_ids[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_SQ_IMC),
                .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
        },
-
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_Y_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_U_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_UQ_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_SD_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_SQ_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_2U_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_4U_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_4H_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_6H_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_2S_D_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_4S_D_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_6S_D_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_8S_D_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_4S_W_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_6S_W_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_8S_W_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_4S_S_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_6S_S_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CFL_8S_S_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
        { /* end: all zeroes */ },
 };
 
@@ -618,6 +716,25 @@ static const struct imc_uncore_pci_dev desktop_imc_pci_ids[] = {
        IMC_DEV(SKL_HQ_IMC, &skl_uncore_pci_driver),  /* 6th Gen Core H Quad Core */
        IMC_DEV(SKL_SD_IMC, &skl_uncore_pci_driver),  /* 6th Gen Core S Dual Core */
        IMC_DEV(SKL_SQ_IMC, &skl_uncore_pci_driver),  /* 6th Gen Core S Quad Core */
+       IMC_DEV(KBL_Y_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core Y */
+       IMC_DEV(KBL_U_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core U */
+       IMC_DEV(KBL_UQ_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core U Quad Core */
+       IMC_DEV(KBL_SD_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core S Dual Core */
+       IMC_DEV(KBL_SQ_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core S Quad Core */
+       IMC_DEV(CFL_2U_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core U 2 Cores */
+       IMC_DEV(CFL_4U_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core U 4 Cores */
+       IMC_DEV(CFL_4H_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core H 4 Cores */
+       IMC_DEV(CFL_6H_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core H 6 Cores */
+       IMC_DEV(CFL_2S_D_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core S 2 Cores Desktop */
+       IMC_DEV(CFL_4S_D_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core S 4 Cores Desktop */
+       IMC_DEV(CFL_6S_D_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core S 6 Cores Desktop */
+       IMC_DEV(CFL_8S_D_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core S 8 Cores Desktop */
+       IMC_DEV(CFL_4S_W_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core S 4 Cores Work Station */
+       IMC_DEV(CFL_6S_W_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core S 6 Cores Work Station */
+       IMC_DEV(CFL_8S_W_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core S 8 Cores Work Station */
+       IMC_DEV(CFL_4S_S_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core S 4 Cores Server */
+       IMC_DEV(CFL_6S_S_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core S 6 Cores Server */
+       IMC_DEV(CFL_8S_S_IMC, &skl_uncore_pci_driver),  /* 8th Gen Core S 8 Cores Server */
        {  /* end marker */ }
 };
 
index be9bfd9aa865beb554b2b6e7ce92010cf276b927..34a23016dd1442f5c95d445f13276d97c772072d 100644 (file)
 # error Linux requires the Xtensa Windowed Registers Option.
 #endif
 
-#define ARCH_SLAB_MINALIGN     XCHAL_DATA_WIDTH
+/* Xtensa ABI requires stack alignment to be at least 16 */
+
+#define STACK_ALIGN (XCHAL_DATA_WIDTH > 16 ? XCHAL_DATA_WIDTH : 16)
+
+#define ARCH_SLAB_MINALIGN STACK_ALIGN
 
 /*
  * User space process size: 1 GB.
index 2f76118ecf6230ff01fe0e43221269da7b208f46..9053a5622d2c3435faefe4950f953b7923e8332f 100644 (file)
@@ -88,9 +88,12 @@ _SetupMMU:
        initialize_mmu
 #if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
        rsr     a2, excsave1
-       movi    a3, 0x08000000
+       movi    a3, XCHAL_KSEG_PADDR
+       bltu    a2, a3, 1f
+       sub     a2, a2, a3
+       movi    a3, XCHAL_KSEG_SIZE
        bgeu    a2, a3, 1f
-       movi    a3, 0xd0000000
+       movi    a3, XCHAL_KSEG_CACHED_VADDR
        add     a2, a2, a3
        wsr     a2, excsave1
 1:
index a50d59236b1976439e691bc0f22da002eedfd0a9..4f4d9884443b63a8f002ddd754ea467f9a0e4c16 100644 (file)
@@ -605,6 +605,7 @@ void __bio_clone_fast(struct bio *bio, struct bio *bio_src)
        if (bio_flagged(bio_src, BIO_THROTTLED))
                bio_set_flag(bio, BIO_THROTTLED);
        bio->bi_opf = bio_src->bi_opf;
+       bio->bi_ioprio = bio_src->bi_ioprio;
        bio->bi_write_hint = bio_src->bi_write_hint;
        bio->bi_iter = bio_src->bi_iter;
        bio->bi_io_vec = bio_src->bi_io_vec;
index ce12515f9b9b9930da4515ed8f70a4cf5f5b946f..deb56932f8c46e9cb0fe0950000b8da1922addfc 100644 (file)
@@ -798,9 +798,8 @@ void blk_cleanup_queue(struct request_queue *q)
         * dispatch may still be in-progress since we dispatch requests
         * from more than one contexts.
         *
-        * No need to quiesce queue if it isn't initialized yet since
-        * blk_freeze_queue() should be enough for cases of passthrough
-        * request.
+        * We rely on driver to deal with the race in case that queue
+        * initialization isn't done.
         */
        if (q->mq_ops && blk_queue_init_done(q))
                blk_mq_quiesce_queue(q);
index e8b3bb9bf37595acea4ec434b3664f8ad6a8c2b8..5f2c429d437847447bc329a00c11a91f58a28edf 100644 (file)
@@ -55,9 +55,11 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
                return -EINVAL;
 
        while (nr_sects) {
-               unsigned int req_sects = min_t(unsigned int, nr_sects,
+               sector_t req_sects = min_t(sector_t, nr_sects,
                                bio_allowed_max_sectors(q));
 
+               WARN_ON_ONCE((req_sects << 9) > UINT_MAX);
+
                bio = blk_next_bio(bio, 0, gfp_mask);
                bio->bi_iter.bi_sector = sector;
                bio_set_dev(bio, bdev);
index 36869afc258ccf6ea609e0e74db6cea56e6d2c34..559c55bda040e2da3d2ec1bc66dacb6e7f02b829 100644 (file)
@@ -248,6 +248,7 @@ static struct bio *bounce_clone_bio(struct bio *bio_src, gfp_t gfp_mask,
                return NULL;
        bio->bi_disk            = bio_src->bi_disk;
        bio->bi_opf             = bio_src->bi_opf;
+       bio->bi_ioprio          = bio_src->bi_ioprio;
        bio->bi_write_hint      = bio_src->bi_write_hint;
        bio->bi_iter.bi_sector  = bio_src->bi_iter.bi_sector;
        bio->bi_iter.bi_size    = bio_src->bi_iter.bi_size;
index e41f6cc33fff49f2b35ad52504742ba79c70c3b8..784748dbb19f0c58482ad18c761c7de121d41928 100644 (file)
@@ -84,7 +84,7 @@ static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_cipher rcipher;
 
-       strlcpy(rcipher.type, "cipher", sizeof(rcipher.type));
+       strncpy(rcipher.type, "cipher", sizeof(rcipher.type));
 
        rcipher.blocksize = alg->cra_blocksize;
        rcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
@@ -103,7 +103,7 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_comp rcomp;
 
-       strlcpy(rcomp.type, "compression", sizeof(rcomp.type));
+       strncpy(rcomp.type, "compression", sizeof(rcomp.type));
        if (nla_put(skb, CRYPTOCFGA_REPORT_COMPRESS,
                    sizeof(struct crypto_report_comp), &rcomp))
                goto nla_put_failure;
@@ -117,7 +117,7 @@ static int crypto_report_acomp(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_acomp racomp;
 
-       strlcpy(racomp.type, "acomp", sizeof(racomp.type));
+       strncpy(racomp.type, "acomp", sizeof(racomp.type));
 
        if (nla_put(skb, CRYPTOCFGA_REPORT_ACOMP,
                    sizeof(struct crypto_report_acomp), &racomp))
@@ -132,7 +132,7 @@ static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_akcipher rakcipher;
 
-       strlcpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
+       strncpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
 
        if (nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER,
                    sizeof(struct crypto_report_akcipher), &rakcipher))
@@ -147,7 +147,7 @@ static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_kpp rkpp;
 
-       strlcpy(rkpp.type, "kpp", sizeof(rkpp.type));
+       strncpy(rkpp.type, "kpp", sizeof(rkpp.type));
 
        if (nla_put(skb, CRYPTOCFGA_REPORT_KPP,
                    sizeof(struct crypto_report_kpp), &rkpp))
@@ -161,10 +161,10 @@ nla_put_failure:
 static int crypto_report_one(struct crypto_alg *alg,
                             struct crypto_user_alg *ualg, struct sk_buff *skb)
 {
-       strlcpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
-       strlcpy(ualg->cru_driver_name, alg->cra_driver_name,
+       strncpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
+       strncpy(ualg->cru_driver_name, alg->cra_driver_name,
                sizeof(ualg->cru_driver_name));
-       strlcpy(ualg->cru_module_name, module_name(alg->cra_module),
+       strncpy(ualg->cru_module_name, module_name(alg->cra_module),
                sizeof(ualg->cru_module_name));
 
        ualg->cru_type = 0;
@@ -177,7 +177,7 @@ static int crypto_report_one(struct crypto_alg *alg,
        if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
                struct crypto_report_larval rl;
 
-               strlcpy(rl.type, "larval", sizeof(rl.type));
+               strncpy(rl.type, "larval", sizeof(rl.type));
                if (nla_put(skb, CRYPTOCFGA_REPORT_LARVAL,
                            sizeof(struct crypto_report_larval), &rl))
                        goto nla_put_failure;
index 021ad06bbb628b5bc199ccded03c44429bae061c..1dfaa0ccd555b5bd3246822365114fa69c7e5ae1 100644 (file)
@@ -37,6 +37,8 @@ static int crypto_report_aead(struct sk_buff *skb, struct crypto_alg *alg)
        u64 v64;
        u32 v32;
 
+       memset(&raead, 0, sizeof(raead));
+
        strncpy(raead.type, "aead", sizeof(raead.type));
 
        v32 = atomic_read(&alg->encrypt_cnt);
@@ -65,6 +67,8 @@ static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg)
        u64 v64;
        u32 v32;
 
+       memset(&rcipher, 0, sizeof(rcipher));
+
        strlcpy(rcipher.type, "cipher", sizeof(rcipher.type));
 
        v32 = atomic_read(&alg->encrypt_cnt);
@@ -93,6 +97,8 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg)
        u64 v64;
        u32 v32;
 
+       memset(&rcomp, 0, sizeof(rcomp));
+
        strlcpy(rcomp.type, "compression", sizeof(rcomp.type));
        v32 = atomic_read(&alg->compress_cnt);
        rcomp.stat_compress_cnt = v32;
@@ -120,6 +126,8 @@ static int crypto_report_acomp(struct sk_buff *skb, struct crypto_alg *alg)
        u64 v64;
        u32 v32;
 
+       memset(&racomp, 0, sizeof(racomp));
+
        strlcpy(racomp.type, "acomp", sizeof(racomp.type));
        v32 = atomic_read(&alg->compress_cnt);
        racomp.stat_compress_cnt = v32;
@@ -147,6 +155,8 @@ static int crypto_report_akcipher(struct sk_buff *skb, struct crypto_alg *alg)
        u64 v64;
        u32 v32;
 
+       memset(&rakcipher, 0, sizeof(rakcipher));
+
        strncpy(rakcipher.type, "akcipher", sizeof(rakcipher.type));
        v32 = atomic_read(&alg->encrypt_cnt);
        rakcipher.stat_encrypt_cnt = v32;
@@ -177,6 +187,8 @@ static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg)
        struct crypto_stat rkpp;
        u32 v;
 
+       memset(&rkpp, 0, sizeof(rkpp));
+
        strlcpy(rkpp.type, "kpp", sizeof(rkpp.type));
 
        v = atomic_read(&alg->setsecret_cnt);
@@ -203,6 +215,8 @@ static int crypto_report_ahash(struct sk_buff *skb, struct crypto_alg *alg)
        u64 v64;
        u32 v32;
 
+       memset(&rhash, 0, sizeof(rhash));
+
        strncpy(rhash.type, "ahash", sizeof(rhash.type));
 
        v32 = atomic_read(&alg->hash_cnt);
@@ -227,6 +241,8 @@ static int crypto_report_shash(struct sk_buff *skb, struct crypto_alg *alg)
        u64 v64;
        u32 v32;
 
+       memset(&rhash, 0, sizeof(rhash));
+
        strncpy(rhash.type, "shash", sizeof(rhash.type));
 
        v32 = atomic_read(&alg->hash_cnt);
@@ -251,6 +267,8 @@ static int crypto_report_rng(struct sk_buff *skb, struct crypto_alg *alg)
        u64 v64;
        u32 v32;
 
+       memset(&rrng, 0, sizeof(rrng));
+
        strncpy(rrng.type, "rng", sizeof(rrng.type));
 
        v32 = atomic_read(&alg->generate_cnt);
@@ -275,6 +293,8 @@ static int crypto_reportstat_one(struct crypto_alg *alg,
                                 struct crypto_user_alg *ualg,
                                 struct sk_buff *skb)
 {
+       memset(ualg, 0, sizeof(*ualg));
+
        strlcpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name));
        strlcpy(ualg->cru_driver_name, alg->cra_driver_name,
                sizeof(ualg->cru_driver_name));
@@ -291,6 +311,7 @@ static int crypto_reportstat_one(struct crypto_alg *alg,
        if (alg->cra_flags & CRYPTO_ALG_LARVAL) {
                struct crypto_stat rl;
 
+               memset(&rl, 0, sizeof(rl));
                strlcpy(rl.type, "larval", sizeof(rl.type));
                if (nla_put(skb, CRYPTOCFGA_STAT_LARVAL,
                            sizeof(struct crypto_stat), &rl))
index ea7240be3001ba245c12d3214c11a7c7e6a8a1fd..78e8d037ae2b342d94ff837d6c9de82b6a4a1090 100644 (file)
@@ -124,8 +124,9 @@ static int simd_skcipher_init(struct crypto_skcipher *tfm)
 
        ctx->cryptd_tfm = cryptd_tfm;
 
-       reqsize = sizeof(struct skcipher_request);
-       reqsize += crypto_skcipher_reqsize(&cryptd_tfm->base);
+       reqsize = crypto_skcipher_reqsize(cryptd_skcipher_child(cryptd_tfm));
+       reqsize = max(reqsize, crypto_skcipher_reqsize(&cryptd_tfm->base));
+       reqsize += sizeof(struct skcipher_request);
 
        crypto_skcipher_set_reqsize(tfm, reqsize);
 
index 8f3a444c6ea9233a2c0cd116e387a71c65d2360f..7cea769c37df55b50c55a7e8751a05057b5348cd 100644 (file)
@@ -512,7 +512,7 @@ config CRC_PMIC_OPREGION
 
 config XPOWER_PMIC_OPREGION
        bool "ACPI operation region support for XPower AXP288 PMIC"
-       depends on MFD_AXP20X_I2C && IOSF_MBI
+       depends on MFD_AXP20X_I2C && IOSF_MBI=y
        help
          This config adds ACPI operation region support for XPower AXP288 PMIC.
 
index eaa60c94205a82f685190a5c0790d6ca91df69cb..1f32caa87686e2369b0f4841447d5ab5093b993d 100644 (file)
@@ -30,6 +30,7 @@ static const struct acpi_device_id forbidden_id_list[] = {
        {"PNP0200",  0},        /* AT DMA Controller */
        {"ACPI0009", 0},        /* IOxAPIC */
        {"ACPI000A", 0},        /* IOAPIC */
+       {"SMB0001",  0},        /* ACPI SMBUS virtual device */
        {"", 0},
 };
 
index f8c638f3c946d904fd0d9ea0aa3301bca2bafd14..14d9f5bea0151c39e706ebfb4ecddb1962fdcc33 100644 (file)
@@ -2928,9 +2928,9 @@ static int acpi_nfit_query_poison(struct acpi_nfit_desc *acpi_desc)
                return rc;
 
        if (ars_status_process_records(acpi_desc))
-               return -ENOMEM;
+               dev_err(acpi_desc->dev, "Failed to process ARS records\n");
 
-       return 0;
+       return rc;
 }
 
 static int ars_register(struct acpi_nfit_desc *acpi_desc,
@@ -3341,8 +3341,6 @@ static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
                struct nvdimm *nvdimm, unsigned int cmd)
 {
        struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
-       struct nfit_spa *nfit_spa;
-       int rc = 0;
 
        if (nvdimm)
                return 0;
@@ -3355,17 +3353,10 @@ static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
         * just needs guarantees that any ARS it initiates are not
         * interrupted by any intervening start requests from userspace.
         */
-       mutex_lock(&acpi_desc->init_mutex);
-       list_for_each_entry(nfit_spa, &acpi_desc->spas, list)
-               if (acpi_desc->scrub_spa
-                               || test_bit(ARS_REQ_SHORT, &nfit_spa->ars_state)
-                               || test_bit(ARS_REQ_LONG, &nfit_spa->ars_state)) {
-                       rc = -EBUSY;
-                       break;
-               }
-       mutex_unlock(&acpi_desc->init_mutex);
+       if (work_busy(&acpi_desc->dwork.work))
+               return -EBUSY;
 
-       return rc;
+       return 0;
 }
 
 int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc,
index 6e594644cb1d360dabbdf3a4b68851a45c5bfb0f..a7f5202a48152a42e6b2b7ab5835289d8cb6fcca 100644 (file)
@@ -4553,7 +4553,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        /* These specific Samsung models/firmware-revs do not handle LPM well */
        { "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_HORKAGE_NOLPM, },
        { "SAMSUNG SSD PM830 mSATA *",  "CXM13D1Q", ATA_HORKAGE_NOLPM, },
-       { "SAMSUNG MZ7TD256HAFV-000L9", "DXT02L5Q", ATA_HORKAGE_NOLPM, },
+       { "SAMSUNG MZ7TD256HAFV-000L9", NULL,       ATA_HORKAGE_NOLPM, },
 
        /* devices that don't properly handle queued TRIM commands */
        { "Micron_M500IT_*",            "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
index 4e46dc9e41ad01142ffdcfe1c38921df9db0ebda..11e1663bdc4dee0e2cfd7cd9ba61783d00277bbf 100644 (file)
@@ -1410,7 +1410,7 @@ static int init_q(struct fs_dev *dev, struct queue *txq, int queue,
 
        func_enter ();
 
-       fs_dprintk (FS_DEBUG_INIT, "Inititing queue at %x: %d entries:\n", 
+       fs_dprintk (FS_DEBUG_INIT, "Initializing queue at %x: %d entries:\n",
                    queue, nentries);
 
        p = aligned_kmalloc (sz, GFP_KERNEL, 0x10);
@@ -1443,7 +1443,7 @@ static int init_fp(struct fs_dev *dev, struct freepool *fp, int queue,
 {
        func_enter ();
 
-       fs_dprintk (FS_DEBUG_INIT, "Inititing free pool at %x:\n", queue);
+       fs_dprintk (FS_DEBUG_INIT, "Initializing free pool at %x:\n", queue);
 
        write_fs (dev, FP_CNF(queue), (bufsize * RBFP_RBS) | RBFP_RBSVAL | RBFP_CME);
        write_fs (dev, FP_SA(queue),  0);
index a8cfa011c28483ef389ee161b5ca86af71eac13e..fb23578e9a416703648154b7371f05bbe3f5ceb8 100644 (file)
@@ -4148,10 +4148,11 @@ static int __floppy_read_block_0(struct block_device *bdev, int drive)
        bio.bi_end_io = floppy_rb0_cb;
        bio_set_op_attrs(&bio, REQ_OP_READ, 0);
 
+       init_completion(&cbdata.complete);
+
        submit_bio(&bio);
        process_fd_request();
 
-       init_completion(&cbdata.complete);
        wait_for_completion(&cbdata.complete);
 
        __free_page(page);
index 8cfee0ab804b43e2dc90e9f55b241a7aa17de363..d8c3595e90236e5f9d87ca9b5f55a7cbdb76ccdc 100644 (file)
@@ -160,8 +160,13 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
        /* Ensure the arm clock divider is what we expect */
        ret = clk_set_rate(clks[ARM].clk, new_freq * 1000);
        if (ret) {
+               int ret1;
+
                dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
-               regulator_set_voltage_tol(arm_reg, volt_old, 0);
+               ret1 = regulator_set_voltage_tol(arm_reg, volt_old, 0);
+               if (ret1)
+                       dev_warn(cpu_dev,
+                                "failed to restore vddarm voltage: %d\n", ret1);
                return ret;
        }
 
index 3f0e2a14895a03dc0c4bc1d01c032d0f50a4b4ae..22b53bf268179ad8c2e873dd9637af61adf2f54d 100644 (file)
@@ -201,19 +201,28 @@ static const struct of_device_id ti_cpufreq_of_match[] = {
        {},
 };
 
+static const struct of_device_id *ti_cpufreq_match_node(void)
+{
+       struct device_node *np;
+       const struct of_device_id *match;
+
+       np = of_find_node_by_path("/");
+       match = of_match_node(ti_cpufreq_of_match, np);
+       of_node_put(np);
+
+       return match;
+}
+
 static int ti_cpufreq_probe(struct platform_device *pdev)
 {
        u32 version[VERSION_COUNT];
-       struct device_node *np;
        const struct of_device_id *match;
        struct opp_table *ti_opp_table;
        struct ti_cpufreq_data *opp_data;
        const char * const reg_names[] = {"vdd", "vbb"};
        int ret;
 
-       np = of_find_node_by_path("/");
-       match = of_match_node(ti_cpufreq_of_match, np);
-       of_node_put(np);
+       match = dev_get_platdata(&pdev->dev);
        if (!match)
                return -ENODEV;
 
@@ -290,7 +299,14 @@ fail_put_node:
 
 static int ti_cpufreq_init(void)
 {
-       platform_device_register_simple("ti-cpufreq", -1, NULL, 0);
+       const struct of_device_id *match;
+
+       /* Check to ensure we are on a compatible platform */
+       match = ti_cpufreq_match_node();
+       if (match)
+               platform_device_register_data(NULL, "ti-cpufreq", -1, match,
+                                             sizeof(*match));
+
        return 0;
 }
 module_init(ti_cpufreq_init);
index 073557f433eb1be630a7f64b8cfc9930771eff2a..3a407a3ef22b4c5a53046452c75c3784e0b77d9d 100644 (file)
@@ -82,7 +82,6 @@ static int __init arm_idle_init_cpu(int cpu)
 {
        int ret;
        struct cpuidle_driver *drv;
-       struct cpuidle_device *dev;
 
        drv = kmemdup(&arm_idle_driver, sizeof(*drv), GFP_KERNEL);
        if (!drv)
@@ -103,13 +102,6 @@ static int __init arm_idle_init_cpu(int cpu)
                goto out_kfree_drv;
        }
 
-       ret = cpuidle_register_driver(drv);
-       if (ret) {
-               if (ret != -EBUSY)
-                       pr_err("Failed to register cpuidle driver\n");
-               goto out_kfree_drv;
-       }
-
        /*
         * Call arch CPU operations in order to initialize
         * idle states suspend back-end specific data
@@ -117,37 +109,21 @@ static int __init arm_idle_init_cpu(int cpu)
        ret = arm_cpuidle_init(cpu);
 
        /*
-        * Skip the cpuidle device initialization if the reported
+        * Allow the initialization to continue for other CPUs, if the reported
         * failure is a HW misconfiguration/breakage (-ENXIO).
         */
-       if (ret == -ENXIO)
-               return 0;
-
        if (ret) {
                pr_err("CPU %d failed to init idle CPU ops\n", cpu);
-               goto out_unregister_drv;
-       }
-
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (!dev) {
-               ret = -ENOMEM;
-               goto out_unregister_drv;
+               ret = ret == -ENXIO ? 0 : ret;
+               goto out_kfree_drv;
        }
-       dev->cpu = cpu;
 
-       ret = cpuidle_register_device(dev);
-       if (ret) {
-               pr_err("Failed to register cpuidle device for CPU %d\n",
-                      cpu);
-               goto out_kfree_dev;
-       }
+       ret = cpuidle_register(drv, NULL);
+       if (ret)
+               goto out_kfree_drv;
 
        return 0;
 
-out_kfree_dev:
-       kfree(dev);
-out_unregister_drv:
-       cpuidle_unregister_driver(drv);
 out_kfree_drv:
        kfree(drv);
        return ret;
@@ -178,9 +154,7 @@ out_fail:
        while (--cpu >= 0) {
                dev = per_cpu(cpuidle_devices, cpu);
                drv = cpuidle_get_cpu_driver(dev);
-               cpuidle_unregister_device(dev);
-               cpuidle_unregister_driver(drv);
-               kfree(dev);
+               cpuidle_unregister(drv);
                kfree(drv);
        }
 
index f7d6d690116ee8f32bada36c6b25520976c219c5..cdc4f9a171d986625352319d76ccf243e417410a 100644 (file)
@@ -732,6 +732,7 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
        int *splits_in_nents;
        int *splits_out_nents = NULL;
        struct sec_request_el *el, *temp;
+       bool split = skreq->src != skreq->dst;
 
        mutex_init(&sec_req->lock);
        sec_req->req_base = &skreq->base;
@@ -750,7 +751,7 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
        if (ret)
                goto err_free_split_sizes;
 
-       if (skreq->src != skreq->dst) {
+       if (split) {
                sec_req->len_out = sg_nents(skreq->dst);
                ret = sec_map_and_split_sg(skreq->dst, split_sizes, steps,
                                           &splits_out, &splits_out_nents,
@@ -785,8 +786,9 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
                                               split_sizes[i],
                                               skreq->src != skreq->dst,
                                               splits_in[i], splits_in_nents[i],
-                                              splits_out[i],
-                                              splits_out_nents[i], info);
+                                              split ? splits_out[i] : NULL,
+                                              split ? splits_out_nents[i] : 0,
+                                              info);
                if (IS_ERR(el)) {
                        ret = PTR_ERR(el);
                        goto err_free_elements;
@@ -806,13 +808,6 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
         * more refined but this is unlikely to happen so no need.
         */
 
-       /* Cleanup - all elements in pointer arrays have been coppied */
-       kfree(splits_in_nents);
-       kfree(splits_in);
-       kfree(splits_out_nents);
-       kfree(splits_out);
-       kfree(split_sizes);
-
        /* Grab a big lock for a long time to avoid concurrency issues */
        mutex_lock(&queue->queuelock);
 
@@ -827,13 +822,13 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
             (!queue->havesoftqueue ||
              kfifo_avail(&queue->softqueue) > steps)) ||
            !list_empty(&ctx->backlog)) {
+               ret = -EBUSY;
                if ((skreq->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
                        list_add_tail(&sec_req->backlog_head, &ctx->backlog);
                        mutex_unlock(&queue->queuelock);
-                       return -EBUSY;
+                       goto out;
                }
 
-               ret = -EBUSY;
                mutex_unlock(&queue->queuelock);
                goto err_free_elements;
        }
@@ -842,7 +837,15 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,
        if (ret)
                goto err_free_elements;
 
-       return -EINPROGRESS;
+       ret = -EINPROGRESS;
+out:
+       /* Cleanup - all elements in pointer arrays have been copied */
+       kfree(splits_in_nents);
+       kfree(splits_in);
+       kfree(splits_out_nents);
+       kfree(splits_out);
+       kfree(split_sizes);
+       return ret;
 
 err_free_elements:
        list_for_each_entry_safe(el, temp, &sec_req->elements, head) {
@@ -854,7 +857,7 @@ err_free_elements:
                                 crypto_skcipher_ivsize(atfm),
                                 DMA_BIDIRECTIONAL);
 err_unmap_out_sg:
-       if (skreq->src != skreq->dst)
+       if (split)
                sec_unmap_sg_on_err(skreq->dst, steps, splits_out,
                                    splits_out_nents, sec_req->len_out,
                                    info->dev);
index 5b44ef226904f9be2530b992c3d06ed338dca53c..fc359ca4503d127fda5f9f631f95d98c4a1d671a 100644 (file)
@@ -184,6 +184,7 @@ static long udmabuf_create(const struct udmabuf_create_list *head,
        exp_info.ops  = &udmabuf_ops;
        exp_info.size = ubuf->pagecount << PAGE_SHIFT;
        exp_info.priv = ubuf;
+       exp_info.flags = O_RDWR;
 
        buf = dma_buf_export(&exp_info);
        if (IS_ERR(buf)) {
index 388a929baf95d1e1107ab4b0ab20516dea3cfdf7..1a6a77df8a5e8aea45f3cbc2bac9c5d0883b0edb 100644 (file)
@@ -265,6 +265,10 @@ void __init efi_init(void)
                                    (params.mmap & ~PAGE_MASK)));
 
        init_screen_info();
+
+       /* ARM does not permit early mappings to persist across paging_init() */
+       if (IS_ENABLED(CONFIG_ARM))
+               efi_memmap_unmap();
 }
 
 static int __init register_gop_device(void)
index 922cfb813109a3c14a88a0bb054a09534e813ec9..a00934d263c519a9d476a57a5bb2388c6041b810 100644 (file)
@@ -110,7 +110,7 @@ static int __init arm_enable_runtime_services(void)
 {
        u64 mapsize;
 
-       if (!efi_enabled(EFI_BOOT) || !efi_enabled(EFI_MEMMAP)) {
+       if (!efi_enabled(EFI_BOOT)) {
                pr_info("EFI services will not be available.\n");
                return 0;
        }
index 249eb70691b0f5e7567cf4fc3bbb8dda9df571cf..fad7c62cfc0e422f3b8459653a561f4dee770a6e 100644 (file)
@@ -592,7 +592,11 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
 
                early_memunmap(tbl, sizeof(*tbl));
        }
+       return 0;
+}
 
+int __init efi_apply_persistent_mem_reservations(void)
+{
        if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) {
                unsigned long prsv = efi.mem_reserve;
 
@@ -963,36 +967,43 @@ bool efi_is_table_address(unsigned long phys_addr)
 }
 
 static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock);
+static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init;
 
 int efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
 {
-       struct linux_efi_memreserve *rsv, *parent;
+       struct linux_efi_memreserve *rsv;
 
-       if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
+       if (!efi_memreserve_root)
                return -ENODEV;
 
-       rsv = kmalloc(sizeof(*rsv), GFP_KERNEL);
+       rsv = kmalloc(sizeof(*rsv), GFP_ATOMIC);
        if (!rsv)
                return -ENOMEM;
 
-       parent = memremap(efi.mem_reserve, sizeof(*rsv), MEMREMAP_WB);
-       if (!parent) {
-               kfree(rsv);
-               return -ENOMEM;
-       }
-
        rsv->base = addr;
        rsv->size = size;
 
        spin_lock(&efi_mem_reserve_persistent_lock);
-       rsv->next = parent->next;
-       parent->next = __pa(rsv);
+       rsv->next = efi_memreserve_root->next;
+       efi_memreserve_root->next = __pa(rsv);
        spin_unlock(&efi_mem_reserve_persistent_lock);
 
-       memunmap(parent);
+       return 0;
+}
 
+static int __init efi_memreserve_root_init(void)
+{
+       if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
+               return -ENODEV;
+
+       efi_memreserve_root = memremap(efi.mem_reserve,
+                                      sizeof(*efi_memreserve_root),
+                                      MEMREMAP_WB);
+       if (!efi_memreserve_root)
+               return -ENOMEM;
        return 0;
 }
+early_initcall(efi_memreserve_root_init);
 
 #ifdef CONFIG_KEXEC
 static int update_efi_random_seed(struct notifier_block *nb,
index 30ac0c975f8a1cc6bd544ba90991a4330ea05cd9..3d36142cf81208d408cab75e28edf957fa865c9e 100644 (file)
@@ -75,6 +75,9 @@ void install_memreserve_table(efi_system_table_t *sys_table_arg)
        efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID;
        efi_status_t status;
 
+       if (IS_ENABLED(CONFIG_ARM))
+               return;
+
        status = efi_call_early(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),
                                (void **)&rsv);
        if (status != EFI_SUCCESS) {
index 8830fa601e45d9a1b1094419cd1ec66f41a25e49..0c0d2312f4a8ad27f6e852bc82d5f2b6c0124e64 100644 (file)
@@ -158,6 +158,10 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,
                        return efi_status;
                }
        }
+
+       /* shrink the FDT back to its minimum size */
+       fdt_pack(fdt);
+
        return EFI_SUCCESS;
 
 fdt_set_fail:
index fa2904fb841fe459a6562b9fea237c5213fa97be..38b686c67b177da4875b9174c0f50ca165c6b2d4 100644 (file)
@@ -118,6 +118,9 @@ int __init efi_memmap_init_early(struct efi_memory_map_data *data)
 
 void __init efi_memmap_unmap(void)
 {
+       if (!efi_enabled(EFI_MEMMAP))
+               return;
+
        if (!efi.memmap.late) {
                unsigned long size;
 
index a19d845bdb06748907972b652415594e18a095f9..8903b9ccfc2b8da6cdc5341fef8619744d904c88 100644 (file)
@@ -67,7 +67,7 @@ struct efi_runtime_work efi_rts_work;
        }                                                               \
                                                                        \
        init_completion(&efi_rts_work.efi_rts_comp);                    \
-       INIT_WORK_ONSTACK(&efi_rts_work.work, efi_call_rts);            \
+       INIT_WORK(&efi_rts_work.work, efi_call_rts);                    \
        efi_rts_work.arg1 = _arg1;                                      \
        efi_rts_work.arg2 = _arg2;                                      \
        efi_rts_work.arg3 = _arg3;                                      \
index b01ba4438501a959de7796dc2eff67a6126d88e3..31e891f00175c635a9ee92c7e0f090eb135fc29b 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/of.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
+#include <linux/sched.h>
 #include <linux/serdev.h>
 #include <linux/slab.h>
 
@@ -63,7 +64,7 @@ static int gnss_serial_write_raw(struct gnss_device *gdev,
        int ret;
 
        /* write is only buffered synchronously */
-       ret = serdev_device_write(serdev, buf, count, 0);
+       ret = serdev_device_write(serdev, buf, count, MAX_SCHEDULE_TIMEOUT);
        if (ret < 0)
                return ret;
 
index 79cb98950013bbb60f4ff4126cd562453441045a..71d014edd16760d6c37dad72836ed9e13cbfffba 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
+#include <linux/sched.h>
 #include <linux/serdev.h>
 #include <linux/slab.h>
 #include <linux/wait.h>
@@ -83,7 +84,7 @@ static int sirf_write_raw(struct gnss_device *gdev, const unsigned char *buf,
        int ret;
 
        /* write is only buffered synchronously */
-       ret = serdev_device_write(serdev, buf, count, 0);
+       ret = serdev_device_write(serdev, buf, count, MAX_SCHEDULE_TIMEOUT);
        if (ret < 0)
                return ret;
 
index 8269cffc2967f772ba2da14e566fd136bb68da56..6a50f9f59c901b6d38069a67b5b9f7881e8a43b6 100644 (file)
@@ -35,8 +35,8 @@
 #define gpio_mockup_err(...)   pr_err(GPIO_MOCKUP_NAME ": " __VA_ARGS__)
 
 enum {
-       GPIO_MOCKUP_DIR_OUT = 0,
-       GPIO_MOCKUP_DIR_IN = 1,
+       GPIO_MOCKUP_DIR_IN = 0,
+       GPIO_MOCKUP_DIR_OUT = 1,
 };
 
 /*
@@ -131,7 +131,7 @@ static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset)
 {
        struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 
-       return chip->lines[offset].dir;
+       return !chip->lines[offset].dir;
 }
 
 static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset)
index bfe4c5c9f41cef3a9c3a483e5283e015d840bc91..e9600b556f397babf8c472ceb2b012f2de97b42a 100644 (file)
@@ -268,8 +268,8 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 
        if (pxa_gpio_has_pinctrl()) {
                ret = pinctrl_gpio_direction_input(chip->base + offset);
-               if (!ret)
-                       return 0;
+               if (ret)
+                       return ret;
        }
 
        spin_lock_irqsave(&gpio_lock, flags);
index 230e41562462b27fdf5d11874b3de8c34c107707..a2cbb474901c224bebae335cd0789273a78955ae 100644 (file)
@@ -1295,7 +1295,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
        gdev->descs = kcalloc(chip->ngpio, sizeof(gdev->descs[0]), GFP_KERNEL);
        if (!gdev->descs) {
                status = -ENOMEM;
-               goto err_free_gdev;
+               goto err_free_ida;
        }
 
        if (chip->ngpio == 0) {
@@ -1427,8 +1427,9 @@ err_free_label:
        kfree_const(gdev->label);
 err_free_descs:
        kfree(gdev->descs);
-err_free_gdev:
+err_free_ida:
        ida_simple_remove(&gpio_ida, gdev->id);
+err_free_gdev:
        /* failures here can mean systems won't boot... */
        pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__,
               gdev->base, gdev->base + gdev->ngpio - 1,
index c31a8849e9f87705ed3abac2ac23bfcbc7303d85..1580ec60b89f753ce2e12018b2a07eb936802d2e 100644 (file)
@@ -501,8 +501,11 @@ void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
 
-       amdgpu_dpm_switch_power_profile(adev,
-                                       PP_SMC_POWER_PROFILE_COMPUTE, !idle);
+       if (adev->powerplay.pp_funcs &&
+           adev->powerplay.pp_funcs->switch_power_profile)
+               amdgpu_dpm_switch_power_profile(adev,
+                                               PP_SMC_POWER_PROFILE_COMPUTE,
+                                               !idle);
 }
 
 bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid)
index 6748cd7fc129b0e7b83966da865f674c676c04e1..686a26de50f91e816471548bf3c1a0fc3f86db86 100644 (file)
@@ -626,6 +626,13 @@ int amdgpu_display_modeset_create_props(struct amdgpu_device *adev)
                                         "dither",
                                         amdgpu_dither_enum_list, sz);
 
+       if (amdgpu_device_has_dc_support(adev)) {
+               adev->mode_info.max_bpc_property =
+                       drm_property_create_range(adev->ddev, 0, "max bpc", 8, 16);
+               if (!adev->mode_info.max_bpc_property)
+                       return -ENOMEM;
+       }
+
        return 0;
 }
 
index b9e9e8b02fb756a0d7291c605353d59cd228826e..d1b4d9b6aae0d1743f77dc2373d0c9159d03f937 100644 (file)
@@ -339,6 +339,8 @@ struct amdgpu_mode_info {
        struct drm_property *audio_property;
        /* FMT dithering */
        struct drm_property *dither_property;
+       /* maximum number of bits per channel for monitor color */
+       struct drm_property *max_bpc_property;
        /* hardcoded DFP edid from BIOS */
        struct edid *bios_hardcoded_edid;
        int bios_hardcoded_edid_size;
index 352b304090602e342ef6f584acab90edf126f51a..dad0e2342df9db7641f77f1473a87f6d78d99050 100644 (file)
@@ -1632,13 +1632,6 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
                        continue;
                }
 
-               /* First check if the entry is already handled */
-               if (cursor.pfn < frag_start) {
-                       cursor.entry->huge = true;
-                       amdgpu_vm_pt_next(adev, &cursor);
-                       continue;
-               }
-
                /* If it isn't already handled it can't be a huge page */
                if (cursor.entry->huge) {
                        /* Add the entry to the relocated list to update it. */
@@ -1701,8 +1694,17 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
                        }
                } while (frag_start < entry_end);
 
-               if (frag >= shift)
+               if (amdgpu_vm_pt_descendant(adev, &cursor)) {
+                       /* Mark all child entries as huge */
+                       while (cursor.pfn < frag_start) {
+                               cursor.entry->huge = true;
+                               amdgpu_vm_pt_next(adev, &cursor);
+                       }
+
+               } else if (frag >= shift) {
+                       /* or just move on to the next on the same level. */
                        amdgpu_vm_pt_next(adev, &cursor);
+               }
        }
 
        return 0;
index ceb7847b504f70fe73435e5b81b4ee4da5588421..bfa317ad20a956017273a7c1fe7ca2decd6491e1 100644 (file)
@@ -72,7 +72,7 @@ static void gfxhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)
 
        /* Program the system aperture low logical page number. */
        WREG32_SOC15(GC, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR,
-                    min(adev->gmc.vram_start, adev->gmc.agp_start) >> 18);
+                    min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
 
        if (adev->asic_type == CHIP_RAVEN && adev->rev_id >= 0x8)
                /*
@@ -82,11 +82,11 @@ static void gfxhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)
                 * to get rid of the VM fault and hardware hang.
                 */
                WREG32_SOC15(GC, 0, mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
-                            max((adev->gmc.vram_end >> 18) + 0x1,
+                            max((adev->gmc.fb_end >> 18) + 0x1,
                                 adev->gmc.agp_end >> 18));
        else
                WREG32_SOC15(GC, 0, mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
-                            max(adev->gmc.vram_end, adev->gmc.agp_end) >> 18);
+                            max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);
 
        /* Set default page address. */
        value = adev->vram_scratch.gpu_addr - adev->gmc.vram_start
index e1c2b4e9c7b23a10ac3b1b2b5375d2bf84eae9c2..73ad02aea2b2e802f0dbce340d70877bdc3b6ca1 100644 (file)
@@ -46,6 +46,7 @@ MODULE_FIRMWARE("amdgpu/tahiti_mc.bin");
 MODULE_FIRMWARE("amdgpu/pitcairn_mc.bin");
 MODULE_FIRMWARE("amdgpu/verde_mc.bin");
 MODULE_FIRMWARE("amdgpu/oland_mc.bin");
+MODULE_FIRMWARE("amdgpu/hainan_mc.bin");
 MODULE_FIRMWARE("amdgpu/si58_mc.bin");
 
 #define MC_SEQ_MISC0__MT__MASK   0xf0000000
index fd23ba1226a57d9d3f1189db15f07daaab7e199d..a0db67adc34cee3d1ee13ca97d8b333ff36dfdc6 100644 (file)
@@ -90,7 +90,7 @@ static void mmhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)
 
        /* Program the system aperture low logical page number. */
        WREG32_SOC15(MMHUB, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR,
-                    min(adev->gmc.vram_start, adev->gmc.agp_start) >> 18);
+                    min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);
 
        if (adev->asic_type == CHIP_RAVEN && adev->rev_id >= 0x8)
                /*
@@ -100,11 +100,11 @@ static void mmhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)
                 * to get rid of the VM fault and hardware hang.
                 */
                WREG32_SOC15(MMHUB, 0, mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
-                            max((adev->gmc.vram_end >> 18) + 0x1,
+                            max((adev->gmc.fb_end >> 18) + 0x1,
                                 adev->gmc.agp_end >> 18));
        else
                WREG32_SOC15(MMHUB, 0, mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR,
-                            max(adev->gmc.vram_end, adev->gmc.agp_end) >> 18);
+                            max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);
 
        /* Set default page address. */
        value = adev->vram_scratch.gpu_addr - adev->gmc.vram_start +
index bf5e6a413dee6e9b5de53f62ad7547ecb5e5b23e..4cc0dcb1a1875bfc559affd1f55e268a25e6282e 100644 (file)
 #define mmMP0_MISC_LIGHT_SLEEP_CTRL                                                             0x01ba
 #define mmMP0_MISC_LIGHT_SLEEP_CTRL_BASE_IDX                                                    0
 
+/* for Vega20 register name change */
+#define mmHDP_MEM_POWER_CTRL   0x00d4
+#define HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK 0x00000001L
+#define HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK   0x00000002L
+#define HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK  0x00010000L
+#define HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK            0x00020000L
+#define mmHDP_MEM_POWER_CTRL_BASE_IDX  0
 /*
  * Indirect registers accessor
  */
@@ -870,15 +877,33 @@ static void soc15_update_hdp_light_sleep(struct amdgpu_device *adev, bool enable
 {
        uint32_t def, data;
 
-       def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS));
+       if (adev->asic_type == CHIP_VEGA20) {
+               def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_CTRL));
 
-       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
-               data |= HDP_MEM_POWER_LS__LS_ENABLE_MASK;
-       else
-               data &= ~HDP_MEM_POWER_LS__LS_ENABLE_MASK;
+               if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
+                       data |= HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK |
+                               HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK |
+                               HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK |
+                               HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK;
+               else
+                       data &= ~(HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK |
+                               HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK |
+                               HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK |
+                               HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK);
 
-       if (def != data)
-               WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS), data);
+               if (def != data)
+                       WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_CTRL), data);
+       } else {
+               def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS));
+
+               if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS))
+                       data |= HDP_MEM_POWER_LS__LS_ENABLE_MASK;
+               else
+                       data &= ~HDP_MEM_POWER_LS__LS_ENABLE_MASK;
+
+               if (def != data)
+                       WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS), data);
+       }
 }
 
 static void soc15_update_drm_clock_gating(struct amdgpu_device *adev, bool enable)
index a99f71797aa359f83217887dd4dcf531d639d45e..a0fda6f9252a52979b5c90569d48b4212f4ea27a 100644 (file)
@@ -129,7 +129,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)
        else
                wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);
        WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off));
-       WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF);
+       WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFFFF);
 
        /* set rptr, wptr to 0 */
        WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0);
index c1262f62cd9f21400c68a6040000d31e4a9a9716..ca925200fe09240ae4f96a2ef7f633726b4cf883 100644 (file)
@@ -2358,8 +2358,15 @@ static void update_stream_scaling_settings(const struct drm_display_mode *mode,
 static enum dc_color_depth
 convert_color_depth_from_display_info(const struct drm_connector *connector)
 {
+       struct dm_connector_state *dm_conn_state =
+               to_dm_connector_state(connector->state);
        uint32_t bpc = connector->display_info.bpc;
 
+       /* TODO: Remove this when there's support for max_bpc in drm */
+       if (dm_conn_state && bpc > dm_conn_state->max_bpc)
+               /* Round down to nearest even number. */
+               bpc = dm_conn_state->max_bpc - (dm_conn_state->max_bpc & 1);
+
        switch (bpc) {
        case 0:
                /*
@@ -2943,6 +2950,9 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector,
        } else if (property == adev->mode_info.underscan_property) {
                dm_new_state->underscan_enable = val;
                ret = 0;
+       } else if (property == adev->mode_info.max_bpc_property) {
+               dm_new_state->max_bpc = val;
+               ret = 0;
        }
 
        return ret;
@@ -2985,6 +2995,9 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector,
        } else if (property == adev->mode_info.underscan_property) {
                *val = dm_state->underscan_enable;
                ret = 0;
+       } else if (property == adev->mode_info.max_bpc_property) {
+               *val = dm_state->max_bpc;
+               ret = 0;
        }
        return ret;
 }
@@ -3795,6 +3808,9 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
        drm_object_attach_property(&aconnector->base.base,
                                adev->mode_info.underscan_vborder_property,
                                0);
+       drm_object_attach_property(&aconnector->base.base,
+                               adev->mode_info.max_bpc_property,
+                               0);
 
 }
 
index 924a38a1fc446019a0aac035b018b952e3be9923..6e069d777ab22d0e733bb7bc1c62d3d3370cc265 100644 (file)
@@ -204,6 +204,7 @@ struct dm_connector_state {
        enum amdgpu_rmx_type scaling;
        uint8_t underscan_vborder;
        uint8_t underscan_hborder;
+       uint8_t max_bpc;
        bool underscan_enable;
        bool freesync_enable;
        bool freesync_capable;
index ed35ec0341e671ab8f5cee4d89d2417283147bf3..88f6b35ea6fee9cb7bdf40df0eeef3b3d71ee233 100644 (file)
@@ -4525,12 +4525,12 @@ static int smu7_get_sclk_od(struct pp_hwmgr *hwmgr)
        struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);
        struct smu7_single_dpm_table *golden_sclk_table =
                        &(data->golden_dpm_table.sclk_table);
-       int value;
+       int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
+       int golden_value = golden_sclk_table->dpm_levels
+                       [golden_sclk_table->count - 1].value;
 
-       value = (sclk_table->dpm_levels[sclk_table->count - 1].value -
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) *
-                       100 /
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
@@ -4567,12 +4567,12 @@ static int smu7_get_mclk_od(struct pp_hwmgr *hwmgr)
        struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);
        struct smu7_single_dpm_table *golden_mclk_table =
                        &(data->golden_dpm_table.mclk_table);
-       int value;
+        int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
+       int golden_value = golden_mclk_table->dpm_levels
+                       [golden_mclk_table->count - 1].value;
 
-       value = (mclk_table->dpm_levels[mclk_table->count - 1].value -
-                       golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) *
-                       100 /
-                       golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value;
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
index 99a33c33a32c9e47fb8bbaf455d8f44efe69c18f..101c09b212ade5690299c823f27aea1ae65cae4a 100644 (file)
@@ -713,20 +713,20 @@ int smu_set_watermarks_for_clocks_ranges(void *wt_table,
        for (i = 0; i < wm_with_clock_ranges->num_wm_dmif_sets; i++) {
                table->WatermarkRow[1][i].MinClock =
                        cpu_to_le16((uint16_t)
-                       (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz) /
-                       1000);
+                       (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz /
+                       1000));
                table->WatermarkRow[1][i].MaxClock =
                        cpu_to_le16((uint16_t)
-                       (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz) /
-                       1000);
+                       (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz /
+                       1000));
                table->WatermarkRow[1][i].MinUclk =
                        cpu_to_le16((uint16_t)
-                       (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz) /
-                       1000);
+                       (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz /
+                       1000));
                table->WatermarkRow[1][i].MaxUclk =
                        cpu_to_le16((uint16_t)
-                       (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz) /
-                       1000);
+                       (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz /
+                       1000));
                table->WatermarkRow[1][i].WmSetting = (uint8_t)
                                wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;
        }
@@ -734,20 +734,20 @@ int smu_set_watermarks_for_clocks_ranges(void *wt_table,
        for (i = 0; i < wm_with_clock_ranges->num_wm_mcif_sets; i++) {
                table->WatermarkRow[0][i].MinClock =
                        cpu_to_le16((uint16_t)
-                       (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz) /
-                       1000);
+                       (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz /
+                       1000));
                table->WatermarkRow[0][i].MaxClock =
                        cpu_to_le16((uint16_t)
-                       (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz) /
-                       1000);
+                       (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz /
+                       1000));
                table->WatermarkRow[0][i].MinUclk =
                        cpu_to_le16((uint16_t)
-                       (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz) /
-                       1000);
+                       (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz /
+                       1000));
                table->WatermarkRow[0][i].MaxUclk =
                        cpu_to_le16((uint16_t)
-                       (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz) /
-                       1000);
+                       (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz /
+                       1000));
                table->WatermarkRow[0][i].WmSetting = (uint8_t)
                                wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;
        }
index 8c4db86bb4b770b345575564ad335d48e2681835..e2bc6e0c229f96dde7baf50d2f2189efce4c2c2e 100644 (file)
@@ -4522,15 +4522,13 @@ static int vega10_get_sclk_od(struct pp_hwmgr *hwmgr)
        struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
        struct vega10_single_dpm_table *golden_sclk_table =
                        &(data->golden_dpm_table.gfx_table);
-       int value;
-
-       value = (sclk_table->dpm_levels[sclk_table->count - 1].value -
-                       golden_sclk_table->dpm_levels
-                       [golden_sclk_table->count - 1].value) *
-                       100 /
-                       golden_sclk_table->dpm_levels
+       int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
+       int golden_value = golden_sclk_table->dpm_levels
                        [golden_sclk_table->count - 1].value;
 
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
+
        return value;
 }
 
@@ -4575,16 +4573,13 @@ static int vega10_get_mclk_od(struct pp_hwmgr *hwmgr)
        struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
        struct vega10_single_dpm_table *golden_mclk_table =
                        &(data->golden_dpm_table.mem_table);
-       int value;
-
-       value = (mclk_table->dpm_levels
-                       [mclk_table->count - 1].value -
-                       golden_mclk_table->dpm_levels
-                       [golden_mclk_table->count - 1].value) *
-                       100 /
-                       golden_mclk_table->dpm_levels
+       int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
+       int golden_value = golden_mclk_table->dpm_levels
                        [golden_mclk_table->count - 1].value;
 
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
+
        return value;
 }
 
index 74bc37308dc09cb8303cd42146c7d88af3a27c58..54364444ecd121dd611c30148f4e292a8ee18e1a 100644 (file)
@@ -2243,12 +2243,12 @@ static int vega12_get_sclk_od(struct pp_hwmgr *hwmgr)
        struct vega12_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);
        struct vega12_single_dpm_table *golden_sclk_table =
                        &(data->golden_dpm_table.gfx_table);
-       int value;
+       int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
+       int golden_value = golden_sclk_table->dpm_levels
+                       [golden_sclk_table->count - 1].value;
 
-       value = (sclk_table->dpm_levels[sclk_table->count - 1].value -
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) *
-                       100 /
-                       golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value;
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
@@ -2264,16 +2264,13 @@ static int vega12_get_mclk_od(struct pp_hwmgr *hwmgr)
        struct vega12_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);
        struct vega12_single_dpm_table *golden_mclk_table =
                        &(data->golden_dpm_table.mem_table);
-       int value;
-
-       value = (mclk_table->dpm_levels
-                       [mclk_table->count - 1].value -
-                       golden_mclk_table->dpm_levels
-                       [golden_mclk_table->count - 1].value) *
-                       100 /
-                       golden_mclk_table->dpm_levels
+       int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
+       int golden_value = golden_mclk_table->dpm_levels
                        [golden_mclk_table->count - 1].value;
 
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
+
        return value;
 }
 
index 99861f32b1f95aedfb5c64d39814baca329662c2..b4eadd47f3a44a22b95ccd12effd99924a493e24 100644 (file)
@@ -75,7 +75,17 @@ static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr)
        data->phy_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
        data->phy_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;
 
-       data->registry_data.disallowed_features = 0x0;
+       /*
+        * Disable the following features for now:
+        *   GFXCLK DS
+        *   SOCLK DS
+        *   LCLK DS
+        *   DCEFCLK DS
+        *   FCLK DS
+        *   MP1CLK DS
+        *   MP0CLK DS
+        */
+       data->registry_data.disallowed_features = 0xE0041C00;
        data->registry_data.od_state_in_dc_support = 0;
        data->registry_data.thermal_support = 1;
        data->registry_data.skip_baco_hardware = 0;
@@ -1313,12 +1323,13 @@ static int vega20_get_sclk_od(
                        &(data->dpm_table.gfx_table);
        struct vega20_single_dpm_table *golden_sclk_table =
                        &(data->golden_dpm_table.gfx_table);
-       int value;
+       int value = sclk_table->dpm_levels[sclk_table->count - 1].value;
+       int golden_value = golden_sclk_table->dpm_levels
+                       [golden_sclk_table->count - 1].value;
 
        /* od percentage */
-       value = DIV_ROUND_UP((sclk_table->dpm_levels[sclk_table->count - 1].value -
-               golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) * 100,
-               golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value);
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
@@ -1358,12 +1369,13 @@ static int vega20_get_mclk_od(
                        &(data->dpm_table.mem_table);
        struct vega20_single_dpm_table *golden_mclk_table =
                        &(data->golden_dpm_table.mem_table);
-       int value;
+       int value = mclk_table->dpm_levels[mclk_table->count - 1].value;
+       int golden_value = golden_mclk_table->dpm_levels
+                       [golden_mclk_table->count - 1].value;
 
        /* od percentage */
-       value = DIV_ROUND_UP((mclk_table->dpm_levels[mclk_table->count - 1].value -
-               golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) * 100,
-               golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value);
+       value -= golden_value;
+       value = DIV_ROUND_UP(value * 100, golden_value);
 
        return value;
 }
index 69dab82a37714853b5dfdb74dbe479f7d6c10fb1..bf589c53b908d66789679df6f4098c883150fa87 100644 (file)
@@ -60,8 +60,29 @@ static const struct pci_device_id pciidlist[] = {
 
 MODULE_DEVICE_TABLE(pci, pciidlist);
 
+static void ast_kick_out_firmware_fb(struct pci_dev *pdev)
+{
+       struct apertures_struct *ap;
+       bool primary = false;
+
+       ap = alloc_apertures(1);
+       if (!ap)
+               return;
+
+       ap->ranges[0].base = pci_resource_start(pdev, 0);
+       ap->ranges[0].size = pci_resource_len(pdev, 0);
+
+#ifdef CONFIG_X86
+       primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
+#endif
+       drm_fb_helper_remove_conflicting_framebuffers(ap, "astdrmfb", primary);
+       kfree(ap);
+}
+
 static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+       ast_kick_out_firmware_fb(pdev);
+
        return drm_get_pci_dev(pdev, ent, &driver);
 }
 
index 5e77d456d9bb9434040107a69536815a270c7865..7c6ac3cadb6b7fabcfe9a309d5fc201db6b75bf7 100644 (file)
@@ -568,6 +568,7 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc,
        }
        ast_bo_unreserve(bo);
 
+       ast_set_offset_reg(crtc);
        ast_set_start_address_crt1(crtc, (u32)gpu_addr);
 
        return 0;
@@ -1254,7 +1255,7 @@ static int ast_cursor_move(struct drm_crtc *crtc,
        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, ((y >> 8) & 0x07));
 
        /* dummy write to fire HWC */
-       ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xCB, 0xFF, 0x00);
+       ast_show_cursor(crtc);
 
        return 0;
 }
index 5ff1d79b86c4a532917e819cfed3c4c702a3ea07..0e0df398222d1e0220b4388d0513bf73f66164ae 100644 (file)
@@ -1275,6 +1275,9 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_
        mutex_lock(&mgr->lock);
        mstb = mgr->mst_primary;
 
+       if (!mstb)
+               goto out;
+
        for (i = 0; i < lct - 1; i++) {
                int shift = (i % 2) ? 0 : 4;
                int port_num = (rad[i / 2] >> shift) & 0xf;
index a502f3e519fdb668c685f392d518361e1e0a1ef2..dd852a25d37540fdf9ee6254f08a68b98df3e9a5 100644 (file)
@@ -219,6 +219,9 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)
        mutex_lock(&fb_helper->lock);
        drm_connector_list_iter_begin(dev, &conn_iter);
        drm_for_each_connector_iter(connector, &conn_iter) {
+               if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
+                       continue;
+
                ret = __drm_fb_helper_add_one_connector(fb_helper, connector);
                if (ret)
                        goto fail;
index 90a1c846fc25aada95b51178060a17d20aa5ed47..8aaa5e86a979ce0985c822201643768200e4a2e3 100644 (file)
@@ -97,9 +97,9 @@ EXPORT_SYMBOL(drm_mode_legacy_fb_format);
 
 /**
  * drm_driver_legacy_fb_format - compute drm fourcc code from legacy description
+ * @dev: DRM device
  * @bpp: bits per pixels
  * @depth: bit depth per pixel
- * @native: use host native byte order
  *
  * Computes a drm fourcc pixel format code for the given @bpp/@depth values.
  * Unlike drm_mode_legacy_fb_format() this looks at the drivers mode_config,
index 1aaccbe7e1debd0c11440ac9acae9c15b07880d5..d4fac09095f862aed3131243957059de2df4f6b0 100644 (file)
@@ -1268,7 +1268,7 @@ relocate_entry(struct i915_vma *vma,
                else if (gen >= 4)
                        len = 4;
                else
-                       len = 3;
+                       len = 6;
 
                batch = reloc_gpu(eb, vma, len);
                if (IS_ERR(batch))
@@ -1309,6 +1309,11 @@ relocate_entry(struct i915_vma *vma,
                        *batch++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL;
                        *batch++ = addr;
                        *batch++ = target_offset;
+
+                       /* And again for good measure (blb/pnv) */
+                       *batch++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL;
+                       *batch++ = addr;
+                       *batch++ = target_offset;
                }
 
                goto out;
index 47c302543799007bee421d85039be8b016aed6e7..07999fe09ad231a037bc73379b5fc27aaf484b94 100644 (file)
@@ -3413,6 +3413,11 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
                ggtt->vm.insert_page    = bxt_vtd_ggtt_insert_page__BKL;
                if (ggtt->vm.clear_range != nop_clear_range)
                        ggtt->vm.clear_range = bxt_vtd_ggtt_clear_range__BKL;
+
+               /* Prevent recursively calling stop_machine() and deadlocks. */
+               dev_info(dev_priv->drm.dev,
+                        "Disabling error capture for VT-d workaround\n");
+               i915_disable_error_state(dev_priv, -ENODEV);
        }
 
        ggtt->invalidate = gen6_ggtt_invalidate;
index 8762d17b66591e2afc8fc9647bef2784145f2c19..3eb33e000d6f00f3ae4b3fdbc8f37f38e97b4d83 100644 (file)
@@ -648,6 +648,9 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
                return 0;
        }
 
+       if (IS_ERR(error))
+               return PTR_ERR(error);
+
        if (*error->error_msg)
                err_printf(m, "%s\n", error->error_msg);
        err_printf(m, "Kernel: " UTS_RELEASE "\n");
@@ -1859,6 +1862,7 @@ void i915_capture_error_state(struct drm_i915_private *i915,
        error = i915_capture_gpu_state(i915);
        if (!error) {
                DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
+               i915_disable_error_state(i915, -ENOMEM);
                return;
        }
 
@@ -1914,5 +1918,14 @@ void i915_reset_error_state(struct drm_i915_private *i915)
        i915->gpu_error.first_error = NULL;
        spin_unlock_irq(&i915->gpu_error.lock);
 
-       i915_gpu_state_put(error);
+       if (!IS_ERR(error))
+               i915_gpu_state_put(error);
+}
+
+void i915_disable_error_state(struct drm_i915_private *i915, int err)
+{
+       spin_lock_irq(&i915->gpu_error.lock);
+       if (!i915->gpu_error.first_error)
+               i915->gpu_error.first_error = ERR_PTR(err);
+       spin_unlock_irq(&i915->gpu_error.lock);
 }
index 8710fb18ed746cface7e9a7b2d6d6ac7cd06b2b4..3ec89a504de52331ade6a9452a844527d84ec515 100644 (file)
@@ -343,6 +343,7 @@ static inline void i915_gpu_state_put(struct i915_gpu_state *gpu)
 
 struct i915_gpu_state *i915_first_error_state(struct drm_i915_private *i915);
 void i915_reset_error_state(struct drm_i915_private *i915);
+void i915_disable_error_state(struct drm_i915_private *i915, int err);
 
 #else
 
@@ -355,13 +356,18 @@ static inline void i915_capture_error_state(struct drm_i915_private *dev_priv,
 static inline struct i915_gpu_state *
 i915_first_error_state(struct drm_i915_private *i915)
 {
-       return NULL;
+       return ERR_PTR(-ENODEV);
 }
 
 static inline void i915_reset_error_state(struct drm_i915_private *i915)
 {
 }
 
+static inline void i915_disable_error_state(struct drm_i915_private *i915,
+                                           int err)
+{
+}
+
 #endif /* IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) */
 
 #endif /* _I915_GPU_ERROR_H_ */
index 0ef0c6448d53a835fbdf5319a8010c64d613bd0f..01fa98299bae65a125862e57c307cdbce07c3d32 100644 (file)
@@ -474,7 +474,7 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv)
                        u8 eu_disabled_mask;
                        u32 n_disabled;
 
-                       if (!(sseu->subslice_mask[ss] & BIT(ss)))
+                       if (!(sseu->subslice_mask[s] & BIT(ss)))
                                /* skip disabled subslice */
                                continue;
 
index 23d8008a93bb690caef898ca5235eeb9fdcd670a..c9878dd1f7cd04dd3a6a7b8877d8f5d95eafc620 100644 (file)
@@ -2890,6 +2890,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
        return;
 
 valid_fb:
+       intel_state->base.rotation = plane_config->rotation;
        intel_fill_fb_ggtt_view(&intel_state->view, fb,
                                intel_state->base.rotation);
        intel_state->color_plane[0].stride =
@@ -4850,8 +4851,31 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe)
  * chroma samples for both of the luma samples, and thus we don't
  * actually get the expected MPEG2 chroma siting convention :(
  * The same behaviour is observed on pre-SKL platforms as well.
+ *
+ * Theory behind the formula (note that we ignore sub-pixel
+ * source coordinates):
+ * s = source sample position
+ * d = destination sample position
+ *
+ * Downscaling 4:1:
+ * -0.5
+ * | 0.0
+ * | |     1.5 (initial phase)
+ * | |     |
+ * v v     v
+ * | s | s | s | s |
+ * |       d       |
+ *
+ * Upscaling 1:4:
+ * -0.5
+ * | -0.375 (initial phase)
+ * | |     0.0
+ * | |     |
+ * v v     v
+ * |       s       |
+ * | d | d | d | d |
  */
-u16 skl_scaler_calc_phase(int sub, bool chroma_cosited)
+u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited)
 {
        int phase = -0x8000;
        u16 trip = 0;
@@ -4859,6 +4883,15 @@ u16 skl_scaler_calc_phase(int sub, bool chroma_cosited)
        if (chroma_cosited)
                phase += (sub - 1) * 0x8000 / sub;
 
+       phase += scale / (2 * sub);
+
+       /*
+        * Hardware initial phase limited to [-0.5:1.5].
+        * Since the max hardware scale factor is 3.0, we
+        * should never actually excdeed 1.0 here.
+        */
+       WARN_ON(phase < -0x8000 || phase > 0x18000);
+
        if (phase < 0)
                phase = 0x10000 + phase;
        else
@@ -5067,13 +5100,20 @@ static void skylake_pfit_enable(struct intel_crtc *crtc)
 
        if (crtc->config->pch_pfit.enabled) {
                u16 uv_rgb_hphase, uv_rgb_vphase;
+               int pfit_w, pfit_h, hscale, vscale;
                int id;
 
                if (WARN_ON(crtc->config->scaler_state.scaler_id < 0))
                        return;
 
-               uv_rgb_hphase = skl_scaler_calc_phase(1, false);
-               uv_rgb_vphase = skl_scaler_calc_phase(1, false);
+               pfit_w = (crtc->config->pch_pfit.size >> 16) & 0xFFFF;
+               pfit_h = crtc->config->pch_pfit.size & 0xFFFF;
+
+               hscale = (crtc->config->pipe_src_w << 16) / pfit_w;
+               vscale = (crtc->config->pipe_src_h << 16) / pfit_h;
+
+               uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
+               uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
 
                id = scaler_state->scaler_id;
                I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN |
@@ -7843,8 +7883,15 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,
                        plane_config->tiling = I915_TILING_X;
                        fb->modifier = I915_FORMAT_MOD_X_TILED;
                }
+
+               if (val & DISPPLANE_ROTATE_180)
+                       plane_config->rotation = DRM_MODE_ROTATE_180;
        }
 
+       if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B &&
+           val & DISPPLANE_MIRROR)
+               plane_config->rotation |= DRM_MODE_REFLECT_X;
+
        pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
        fourcc = i9xx_format_to_fourcc(pixel_format);
        fb->format = drm_format_info(fourcc);
@@ -8913,6 +8960,29 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,
                goto error;
        }
 
+       /*
+        * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr
+        * while i915 HW rotation is clockwise, thats why this swapping.
+        */
+       switch (val & PLANE_CTL_ROTATE_MASK) {
+       case PLANE_CTL_ROTATE_0:
+               plane_config->rotation = DRM_MODE_ROTATE_0;
+               break;
+       case PLANE_CTL_ROTATE_90:
+               plane_config->rotation = DRM_MODE_ROTATE_270;
+               break;
+       case PLANE_CTL_ROTATE_180:
+               plane_config->rotation = DRM_MODE_ROTATE_180;
+               break;
+       case PLANE_CTL_ROTATE_270:
+               plane_config->rotation = DRM_MODE_ROTATE_90;
+               break;
+       }
+
+       if (INTEL_GEN(dev_priv) >= 10 &&
+           val & PLANE_CTL_FLIP_HORIZONTAL)
+               plane_config->rotation |= DRM_MODE_REFLECT_X;
+
        base = I915_READ(PLANE_SURF(pipe, plane_id)) & 0xfffff000;
        plane_config->base = base;
 
@@ -15228,6 +15298,14 @@ retry:
                        ret = drm_atomic_add_affected_planes(state, crtc);
                        if (ret)
                                goto out;
+
+                       /*
+                        * FIXME hack to force a LUT update to avoid the
+                        * plane update forcing the pipe gamma on without
+                        * having a proper LUT loaded. Remove once we
+                        * have readout for pipe gamma enable.
+                        */
+                       crtc_state->color_mgmt_changed = true;
                }
        }
 
index 1b00f8ea145ba3990d17f6e7142755bae8ca6a77..a911691dbd0fdd1837c8cfadec09f8d39eb7ac7d 100644 (file)
@@ -452,6 +452,10 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
        if (!intel_connector)
                return NULL;
 
+       intel_connector->get_hw_state = intel_dp_mst_get_hw_state;
+       intel_connector->mst_port = intel_dp;
+       intel_connector->port = port;
+
        connector = &intel_connector->base;
        ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs,
                                 DRM_MODE_CONNECTOR_DisplayPort);
@@ -462,10 +466,6 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
 
        drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs);
 
-       intel_connector->get_hw_state = intel_dp_mst_get_hw_state;
-       intel_connector->mst_port = intel_dp;
-       intel_connector->port = port;
-
        for_each_pipe(dev_priv, pipe) {
                struct drm_encoder *enc =
                        &intel_dp->mst_encoders[pipe]->base.base;
index f8dc84b2d2d3443dcd47232f013bddb4ae9731f8..db6fa1d0cbdae3efea1e3ddb1c3ce43bf5f8a10e 100644 (file)
@@ -547,6 +547,7 @@ struct intel_initial_plane_config {
        unsigned int tiling;
        int size;
        u32 base;
+       u8 rotation;
 };
 
 #define SKL_MIN_SRC_W 8
@@ -1646,7 +1647,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
                                  struct intel_crtc_state *crtc_state);
 
-u16 skl_scaler_calc_phase(int sub, bool chroma_center);
+u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_center);
 int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);
 int skl_max_scale(const struct intel_crtc_state *crtc_state,
                  u32 pixel_format);
index 648a13c6043c0071ddd495424691d795b39b96a1..9a801813023728e2e0a05bb5feba1f8415eb3269 100644 (file)
@@ -228,7 +228,9 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
                drm_for_each_connector_iter(connector, &conn_iter) {
                        struct intel_connector *intel_connector = to_intel_connector(connector);
 
-                       if (intel_connector->encoder->hpd_pin == pin) {
+                       /* Don't check MST ports, they don't have pins */
+                       if (!intel_connector->mst_port &&
+                           intel_connector->encoder->hpd_pin == pin) {
                                if (connector->polled != intel_connector->polled)
                                        DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n",
                                                         connector->name);
@@ -395,37 +397,54 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
        struct intel_encoder *encoder;
        bool storm_detected = false;
        bool queue_dig = false, queue_hp = false;
+       u32 long_hpd_pulse_mask = 0;
+       u32 short_hpd_pulse_mask = 0;
+       enum hpd_pin pin;
 
        if (!pin_mask)
                return;
 
        spin_lock(&dev_priv->irq_lock);
+
+       /*
+        * Determine whether ->hpd_pulse() exists for each pin, and
+        * whether we have a short or a long pulse. This is needed
+        * as each pin may have up to two encoders (HDMI and DP) and
+        * only the one of them (DP) will have ->hpd_pulse().
+        */
        for_each_intel_encoder(&dev_priv->drm, encoder) {
-               enum hpd_pin pin = encoder->hpd_pin;
                bool has_hpd_pulse = intel_encoder_has_hpd_pulse(encoder);
+               enum port port = encoder->port;
+               bool long_hpd;
 
+               pin = encoder->hpd_pin;
                if (!(BIT(pin) & pin_mask))
                        continue;
 
-               if (has_hpd_pulse) {
-                       bool long_hpd = long_mask & BIT(pin);
-                       enum port port = encoder->port;
+               if (!has_hpd_pulse)
+                       continue;
 
-                       DRM_DEBUG_DRIVER("digital hpd port %c - %s\n", port_name(port),
-                                        long_hpd ? "long" : "short");
-                       /*
-                        * For long HPD pulses we want to have the digital queue happen,
-                        * but we still want HPD storm detection to function.
-                        */
-                       queue_dig = true;
-                       if (long_hpd) {
-                               dev_priv->hotplug.long_port_mask |= (1 << port);
-                       } else {
-                               /* for short HPD just trigger the digital queue */
-                               dev_priv->hotplug.short_port_mask |= (1 << port);
-                               continue;
-                       }
+               long_hpd = long_mask & BIT(pin);
+
+               DRM_DEBUG_DRIVER("digital hpd port %c - %s\n", port_name(port),
+                                long_hpd ? "long" : "short");
+               queue_dig = true;
+
+               if (long_hpd) {
+                       long_hpd_pulse_mask |= BIT(pin);
+                       dev_priv->hotplug.long_port_mask |= BIT(port);
+               } else {
+                       short_hpd_pulse_mask |= BIT(pin);
+                       dev_priv->hotplug.short_port_mask |= BIT(port);
                }
+       }
+
+       /* Now process each pin just once */
+       for_each_hpd_pin(pin) {
+               bool long_hpd;
+
+               if (!(BIT(pin) & pin_mask))
+                       continue;
 
                if (dev_priv->hotplug.stats[pin].state == HPD_DISABLED) {
                        /*
@@ -442,11 +461,22 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
                if (dev_priv->hotplug.stats[pin].state != HPD_ENABLED)
                        continue;
 
-               if (!has_hpd_pulse) {
+               /*
+                * Delegate to ->hpd_pulse() if one of the encoders for this
+                * pin has it, otherwise let the hotplug_work deal with this
+                * pin directly.
+                */
+               if (((short_hpd_pulse_mask | long_hpd_pulse_mask) & BIT(pin))) {
+                       long_hpd = long_hpd_pulse_mask & BIT(pin);
+               } else {
                        dev_priv->hotplug.event_bits |= BIT(pin);
+                       long_hpd = true;
                        queue_hp = true;
                }
 
+               if (!long_hpd)
+                       continue;
+
                if (intel_hpd_irq_storm_detect(dev_priv, pin)) {
                        dev_priv->hotplug.event_bits &= ~BIT(pin);
                        storm_detected = true;
index 43957bb37a42249cfb75793fd688f191eaef2c98..37c94a54efcbb2501509b5a838e61d983985d8b2 100644 (file)
@@ -424,7 +424,8 @@ static u64 execlists_update_context(struct i915_request *rq)
 
        reg_state[CTX_RING_TAIL+1] = intel_ring_set_tail(rq->ring, rq->tail);
 
-       /* True 32b PPGTT with dynamic page allocation: update PDP
+       /*
+        * True 32b PPGTT with dynamic page allocation: update PDP
         * registers and point the unallocated PDPs to scratch page.
         * PML4 is allocated during ppgtt init, so this is not needed
         * in 48-bit mode.
@@ -432,6 +433,17 @@ static u64 execlists_update_context(struct i915_request *rq)
        if (ppgtt && !i915_vm_is_48bit(&ppgtt->vm))
                execlists_update_context_pdps(ppgtt, reg_state);
 
+       /*
+        * Make sure the context image is complete before we submit it to HW.
+        *
+        * Ostensibly, writes (including the WCB) should be flushed prior to
+        * an uncached write such as our mmio register access, the empirical
+        * evidence (esp. on Braswell) suggests that the WC write into memory
+        * may not be visible to the HW prior to the completion of the UC
+        * register write and that we may begin execution from the context
+        * before its image is complete leading to invalid PD chasing.
+        */
+       wmb();
        return ce->lrc_desc;
 }
 
index 245f0022bcfd00c730f020b24326bfba90de4ea2..3fe358db12768f23a2fcf7fe971821c4cac3f1b9 100644 (file)
@@ -2493,6 +2493,9 @@ static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate,
        uint32_t method1, method2;
        int cpp;
 
+       if (mem_value == 0)
+               return U32_MAX;
+
        if (!intel_wm_plane_visible(cstate, pstate))
                return 0;
 
@@ -2522,6 +2525,9 @@ static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate,
        uint32_t method1, method2;
        int cpp;
 
+       if (mem_value == 0)
+               return U32_MAX;
+
        if (!intel_wm_plane_visible(cstate, pstate))
                return 0;
 
@@ -2545,6 +2551,9 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate,
 {
        int cpp;
 
+       if (mem_value == 0)
+               return U32_MAX;
+
        if (!intel_wm_plane_visible(cstate, pstate))
                return 0;
 
@@ -3008,6 +3017,34 @@ static void snb_wm_latency_quirk(struct drm_i915_private *dev_priv)
        intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency);
 }
 
+static void snb_wm_lp3_irq_quirk(struct drm_i915_private *dev_priv)
+{
+       /*
+        * On some SNB machines (Thinkpad X220 Tablet at least)
+        * LP3 usage can cause vblank interrupts to be lost.
+        * The DEIIR bit will go high but it looks like the CPU
+        * never gets interrupted.
+        *
+        * It's not clear whether other interrupt source could
+        * be affected or if this is somehow limited to vblank
+        * interrupts only. To play it safe we disable LP3
+        * watermarks entirely.
+        */
+       if (dev_priv->wm.pri_latency[3] == 0 &&
+           dev_priv->wm.spr_latency[3] == 0 &&
+           dev_priv->wm.cur_latency[3] == 0)
+               return;
+
+       dev_priv->wm.pri_latency[3] = 0;
+       dev_priv->wm.spr_latency[3] = 0;
+       dev_priv->wm.cur_latency[3] = 0;
+
+       DRM_DEBUG_KMS("LP3 watermarks disabled due to potential for lost interrupts\n");
+       intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency);
+       intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency);
+       intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency);
+}
+
 static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv)
 {
        intel_read_wm_latency(dev_priv, dev_priv->wm.pri_latency);
@@ -3024,8 +3061,10 @@ static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv)
        intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency);
        intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency);
 
-       if (IS_GEN6(dev_priv))
+       if (IS_GEN6(dev_priv)) {
                snb_wm_latency_quirk(dev_priv);
+               snb_wm_lp3_irq_quirk(dev_priv);
+       }
 }
 
 static void skl_setup_wm_latency(struct drm_i915_private *dev_priv)
index d0ef50bf930ad747abe7b4510521f8ad79923ba5..187bb0ceb4ac4324b3c12ab72635d4a776b2129c 100644 (file)
@@ -91,6 +91,7 @@ static int
 gen4_render_ring_flush(struct i915_request *rq, u32 mode)
 {
        u32 cmd, *cs;
+       int i;
 
        /*
         * read/write caches:
@@ -127,12 +128,45 @@ gen4_render_ring_flush(struct i915_request *rq, u32 mode)
                        cmd |= MI_INVALIDATE_ISP;
        }
 
-       cs = intel_ring_begin(rq, 2);
+       i = 2;
+       if (mode & EMIT_INVALIDATE)
+               i += 20;
+
+       cs = intel_ring_begin(rq, i);
        if (IS_ERR(cs))
                return PTR_ERR(cs);
 
        *cs++ = cmd;
-       *cs++ = MI_NOOP;
+
+       /*
+        * A random delay to let the CS invalidate take effect? Without this
+        * delay, the GPU relocation path fails as the CS does not see
+        * the updated contents. Just as important, if we apply the flushes
+        * to the EMIT_FLUSH branch (i.e. immediately after the relocation
+        * write and before the invalidate on the next batch), the relocations
+        * still fail. This implies that is a delay following invalidation
+        * that is required to reset the caches as opposed to a delay to
+        * ensure the memory is written.
+        */
+       if (mode & EMIT_INVALIDATE) {
+               *cs++ = GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE;
+               *cs++ = i915_ggtt_offset(rq->engine->scratch) |
+                       PIPE_CONTROL_GLOBAL_GTT;
+               *cs++ = 0;
+               *cs++ = 0;
+
+               for (i = 0; i < 12; i++)
+                       *cs++ = MI_FLUSH;
+
+               *cs++ = GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE;
+               *cs++ = i915_ggtt_offset(rq->engine->scratch) |
+                       PIPE_CONTROL_GLOBAL_GTT;
+               *cs++ = 0;
+               *cs++ = 0;
+       }
+
+       *cs++ = cmd;
+
        intel_ring_advance(rq, cs);
 
        return 0;
index 0fdabce647ab64be1751da09ed705de3889ad969..44e4491a4918994b80ddde101042368263abf8d1 100644 (file)
@@ -2748,6 +2748,12 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                        .hsw.has_fuses = true,
                },
        },
+       {
+               .name = "DC off",
+               .domains = ICL_DISPLAY_DC_OFF_POWER_DOMAINS,
+               .ops = &gen9_dc_off_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+       },
        {
                .name = "power well 2",
                .domains = ICL_PW_2_POWER_DOMAINS,
@@ -2759,12 +2765,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {
                        .hsw.has_fuses = true,
                },
        },
-       {
-               .name = "DC off",
-               .domains = ICL_DISPLAY_DC_OFF_POWER_DOMAINS,
-               .ops = &gen9_dc_off_power_well_ops,
-               .id = DISP_PW_ID_NONE,
-       },
        {
                .name = "power well 3",
                .domains = ICL_PW_3_POWER_DOMAINS,
@@ -3176,8 +3176,7 @@ static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv)
 void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
                            u8 req_slices)
 {
-       u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;
-       u32 val;
+       const u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;
        bool ret;
 
        if (req_slices > intel_dbuf_max_slices(dev_priv)) {
@@ -3188,7 +3187,6 @@ void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
        if (req_slices == hw_enabled_slices || req_slices == 0)
                return;
 
-       val = I915_READ(DBUF_CTL_S2);
        if (req_slices > hw_enabled_slices)
                ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, true);
        else
index 5fd2f7bf3927191a22cdeba959c5fd7c4f6f512a..d3090a7537bb9576c89f69d17541eadbf9353d8c 100644 (file)
@@ -302,13 +302,65 @@ skl_plane_max_stride(struct intel_plane *plane,
                return min(8192 * cpp, 32768);
 }
 
+static void
+skl_program_scaler(struct intel_plane *plane,
+                  const struct intel_crtc_state *crtc_state,
+                  const struct intel_plane_state *plane_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+       enum pipe pipe = plane->pipe;
+       int scaler_id = plane_state->scaler_id;
+       const struct intel_scaler *scaler =
+               &crtc_state->scaler_state.scalers[scaler_id];
+       int crtc_x = plane_state->base.dst.x1;
+       int crtc_y = plane_state->base.dst.y1;
+       uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
+       uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
+       u16 y_hphase, uv_rgb_hphase;
+       u16 y_vphase, uv_rgb_vphase;
+       int hscale, vscale;
+
+       hscale = drm_rect_calc_hscale(&plane_state->base.src,
+                                     &plane_state->base.dst,
+                                     0, INT_MAX);
+       vscale = drm_rect_calc_vscale(&plane_state->base.src,
+                                     &plane_state->base.dst,
+                                     0, INT_MAX);
+
+       /* TODO: handle sub-pixel coordinates */
+       if (plane_state->base.fb->format->format == DRM_FORMAT_NV12) {
+               y_hphase = skl_scaler_calc_phase(1, hscale, false);
+               y_vphase = skl_scaler_calc_phase(1, vscale, false);
+
+               /* MPEG2 chroma siting convention */
+               uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true);
+               uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false);
+       } else {
+               /* not used */
+               y_hphase = 0;
+               y_vphase = 0;
+
+               uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false);
+               uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);
+       }
+
+       I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
+                     PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode);
+       I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
+       I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
+                     PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
+       I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
+                     PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
+       I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
+       I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h);
+}
+
 void
 skl_update_plane(struct intel_plane *plane,
                 const struct intel_crtc_state *crtc_state,
                 const struct intel_plane_state *plane_state)
 {
        struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
-       const struct drm_framebuffer *fb = plane_state->base.fb;
        enum plane_id plane_id = plane->id;
        enum pipe pipe = plane->pipe;
        u32 plane_ctl = plane_state->ctl;
@@ -318,8 +370,6 @@ skl_update_plane(struct intel_plane *plane,
        u32 aux_stride = skl_plane_stride(plane_state, 1);
        int crtc_x = plane_state->base.dst.x1;
        int crtc_y = plane_state->base.dst.y1;
-       uint32_t crtc_w = drm_rect_width(&plane_state->base.dst);
-       uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);
        uint32_t x = plane_state->color_plane[0].x;
        uint32_t y = plane_state->color_plane[0].y;
        uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16;
@@ -329,8 +379,6 @@ skl_update_plane(struct intel_plane *plane,
        /* Sizes are 0 based */
        src_w--;
        src_h--;
-       crtc_w--;
-       crtc_h--;
 
        spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
@@ -353,41 +401,8 @@ skl_update_plane(struct intel_plane *plane,
                      (plane_state->color_plane[1].y << 16) |
                      plane_state->color_plane[1].x);
 
-       /* program plane scaler */
        if (plane_state->scaler_id >= 0) {
-               int scaler_id = plane_state->scaler_id;
-               const struct intel_scaler *scaler =
-                       &crtc_state->scaler_state.scalers[scaler_id];
-               u16 y_hphase, uv_rgb_hphase;
-               u16 y_vphase, uv_rgb_vphase;
-
-               /* TODO: handle sub-pixel coordinates */
-               if (fb->format->format == DRM_FORMAT_NV12) {
-                       y_hphase = skl_scaler_calc_phase(1, false);
-                       y_vphase = skl_scaler_calc_phase(1, false);
-
-                       /* MPEG2 chroma siting convention */
-                       uv_rgb_hphase = skl_scaler_calc_phase(2, true);
-                       uv_rgb_vphase = skl_scaler_calc_phase(2, false);
-               } else {
-                       /* not used */
-                       y_hphase = 0;
-                       y_vphase = 0;
-
-                       uv_rgb_hphase = skl_scaler_calc_phase(1, false);
-                       uv_rgb_vphase = skl_scaler_calc_phase(1, false);
-               }
-
-               I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id),
-                             PS_SCALER_EN | PS_PLANE_SEL(plane_id) | scaler->mode);
-               I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0);
-               I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id),
-                             PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase));
-               I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id),
-                             PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase));
-               I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y);
-               I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id),
-                             ((crtc_w + 1) << 16)|(crtc_h + 1));
+               skl_program_scaler(plane, crtc_state, plane_state);
 
                I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0);
        } else {
index 514245e69b3847d1dc1d5f96249d5e49f849a4ca..acbbad3e322ca56957ff3b34228b694d12de30b3 100644 (file)
@@ -854,6 +854,13 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
        unsigned int sof_lines;
        unsigned int vsync_lines;
 
+       /* Use VENCI for 480i and 576i and double HDMI pixels */
+       if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
+               hdmi_repeat = true;
+               use_enci = true;
+               venc_hdmi_latency = 1;
+       }
+
        if (meson_venc_hdmi_supported_vic(vic)) {
                vmode = meson_venc_hdmi_get_vic_vmode(vic);
                if (!vmode) {
@@ -865,13 +872,7 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
        } else {
                meson_venc_hdmi_get_dmt_vmode(mode, &vmode_dmt);
                vmode = &vmode_dmt;
-       }
-
-       /* Use VENCI for 480i and 576i and double HDMI pixels */
-       if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
-               hdmi_repeat = true;
-               use_enci = true;
-               venc_hdmi_latency = 1;
+               use_enci = false;
        }
 
        /* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */
index 394c129cfb3bb8e03b8970fc839656e3d25becd5..0a485c5b982eb84addaf013dd8241509ca403d04 100644 (file)
@@ -5409,11 +5409,14 @@ static int dsi_probe(struct platform_device *pdev)
 
        /* DSI on OMAP3 doesn't have register DSI_GNQ, set number
         * of data to 3 by default */
-       if (dsi->data->quirks & DSI_QUIRK_GNQ)
+       if (dsi->data->quirks & DSI_QUIRK_GNQ) {
+               dsi_runtime_get(dsi);
                /* NB_DATA_LANES */
                dsi->num_lanes_supported = 1 + REG_GET(dsi, DSI_GNQ, 11, 9);
-       else
+               dsi_runtime_put(dsi);
+       } else {
                dsi->num_lanes_supported = 3;
+       }
 
        r = dsi_init_output(dsi);
        if (r)
@@ -5426,15 +5429,19 @@ static int dsi_probe(struct platform_device *pdev)
        }
 
        r = of_platform_populate(dev->of_node, NULL, NULL, dev);
-       if (r)
+       if (r) {
                DSSERR("Failed to populate DSI child devices: %d\n", r);
+               goto err_uninit_output;
+       }
 
        r = component_add(&pdev->dev, &dsi_component_ops);
        if (r)
-               goto err_uninit_output;
+               goto err_of_depopulate;
 
        return 0;
 
+err_of_depopulate:
+       of_platform_depopulate(dev);
 err_uninit_output:
        dsi_uninit_output(dsi);
 err_pm_disable:
@@ -5470,19 +5477,12 @@ static int dsi_runtime_suspend(struct device *dev)
        /* wait for current handler to finish before turning the DSI off */
        synchronize_irq(dsi->irq);
 
-       dispc_runtime_put(dsi->dss->dispc);
-
        return 0;
 }
 
 static int dsi_runtime_resume(struct device *dev)
 {
        struct dsi_data *dsi = dev_get_drvdata(dev);
-       int r;
-
-       r = dispc_runtime_get(dsi->dss->dispc);
-       if (r)
-               return r;
 
        dsi->is_enabled = true;
        /* ensure the irq handler sees the is_enabled value */
index 1aaf260aa9b8638d2e7fac7aaa36ed3fe14a0880..7553c7fc1c457f23bb456046c17408ba89fc9d24 100644 (file)
@@ -1484,16 +1484,23 @@ static int dss_probe(struct platform_device *pdev)
                                                   dss);
 
        /* Add all the child devices as components. */
+       r = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+       if (r)
+               goto err_uninit_debugfs;
+
        omapdss_gather_components(&pdev->dev);
 
        device_for_each_child(&pdev->dev, &match, dss_add_child_component);
 
        r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);
        if (r)
-               goto err_uninit_debugfs;
+               goto err_of_depopulate;
 
        return 0;
 
+err_of_depopulate:
+       of_platform_depopulate(&pdev->dev);
+
 err_uninit_debugfs:
        dss_debugfs_remove_file(dss->debugfs.clk);
        dss_debugfs_remove_file(dss->debugfs.dss);
@@ -1522,6 +1529,8 @@ static int dss_remove(struct platform_device *pdev)
 {
        struct dss_device *dss = platform_get_drvdata(pdev);
 
+       of_platform_depopulate(&pdev->dev);
+
        component_master_del(&pdev->dev, &dss_component_ops);
 
        dss_debugfs_remove_file(dss->debugfs.clk);
index cf6230eac31a3cffb37f62cb3e7b79ec9a6bb552..aabdda394c9c6f4cf7f93eb0f8e0f9a6126262d1 100644 (file)
@@ -635,10 +635,14 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)
 
        hdmi->dss = dss;
 
-       r = hdmi_pll_init(dss, hdmi->pdev, &hdmi->pll, &hdmi->wp);
+       r = hdmi_runtime_get(hdmi);
        if (r)
                return r;
 
+       r = hdmi_pll_init(dss, hdmi->pdev, &hdmi->pll, &hdmi->wp);
+       if (r)
+               goto err_runtime_put;
+
        r = hdmi4_cec_init(hdmi->pdev, &hdmi->core, &hdmi->wp);
        if (r)
                goto err_pll_uninit;
@@ -652,12 +656,16 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)
        hdmi->debugfs = dss_debugfs_create_file(dss, "hdmi", hdmi_dump_regs,
                                               hdmi);
 
+       hdmi_runtime_put(hdmi);
+
        return 0;
 
 err_cec_uninit:
        hdmi4_cec_uninit(&hdmi->core);
 err_pll_uninit:
        hdmi_pll_uninit(&hdmi->pll);
+err_runtime_put:
+       hdmi_runtime_put(hdmi);
        return r;
 }
 
@@ -833,32 +841,6 @@ static int hdmi4_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int hdmi_runtime_suspend(struct device *dev)
-{
-       struct omap_hdmi *hdmi = dev_get_drvdata(dev);
-
-       dispc_runtime_put(hdmi->dss->dispc);
-
-       return 0;
-}
-
-static int hdmi_runtime_resume(struct device *dev)
-{
-       struct omap_hdmi *hdmi = dev_get_drvdata(dev);
-       int r;
-
-       r = dispc_runtime_get(hdmi->dss->dispc);
-       if (r < 0)
-               return r;
-
-       return 0;
-}
-
-static const struct dev_pm_ops hdmi_pm_ops = {
-       .runtime_suspend = hdmi_runtime_suspend,
-       .runtime_resume = hdmi_runtime_resume,
-};
-
 static const struct of_device_id hdmi_of_match[] = {
        { .compatible = "ti,omap4-hdmi", },
        {},
@@ -869,7 +851,6 @@ struct platform_driver omapdss_hdmi4hw_driver = {
        .remove         = hdmi4_remove,
        .driver         = {
                .name   = "omapdss_hdmi",
-               .pm     = &hdmi_pm_ops,
                .of_match_table = hdmi_of_match,
                .suppress_bind_attrs = true,
        },
index b0e4a7463f8c88517fcb398a049a8f5355df6dc9..9e8556f67a2914aed8ed1b71409956c2bcc07057 100644 (file)
@@ -825,32 +825,6 @@ static int hdmi5_remove(struct platform_device *pdev)
        return 0;
 }
 
-static int hdmi_runtime_suspend(struct device *dev)
-{
-       struct omap_hdmi *hdmi = dev_get_drvdata(dev);
-
-       dispc_runtime_put(hdmi->dss->dispc);
-
-       return 0;
-}
-
-static int hdmi_runtime_resume(struct device *dev)
-{
-       struct omap_hdmi *hdmi = dev_get_drvdata(dev);
-       int r;
-
-       r = dispc_runtime_get(hdmi->dss->dispc);
-       if (r < 0)
-               return r;
-
-       return 0;
-}
-
-static const struct dev_pm_ops hdmi_pm_ops = {
-       .runtime_suspend = hdmi_runtime_suspend,
-       .runtime_resume = hdmi_runtime_resume,
-};
-
 static const struct of_device_id hdmi_of_match[] = {
        { .compatible = "ti,omap5-hdmi", },
        { .compatible = "ti,dra7-hdmi", },
@@ -862,7 +836,6 @@ struct platform_driver omapdss_hdmi5hw_driver = {
        .remove         = hdmi5_remove,
        .driver         = {
                .name   = "omapdss_hdmi5",
-               .pm     = &hdmi_pm_ops,
                .of_match_table = hdmi_of_match,
                .suppress_bind_attrs = true,
        },
index ff0b18c8e4acedc4d2e310d5377a789fecaaf9a2..b5f52727f8b17237f52bbad92e170a488e27b396 100644 (file)
@@ -946,19 +946,12 @@ static int venc_runtime_suspend(struct device *dev)
        if (venc->tv_dac_clk)
                clk_disable_unprepare(venc->tv_dac_clk);
 
-       dispc_runtime_put(venc->dss->dispc);
-
        return 0;
 }
 
 static int venc_runtime_resume(struct device *dev)
 {
        struct venc_device *venc = dev_get_drvdata(dev);
-       int r;
-
-       r = dispc_runtime_get(venc->dss->dispc);
-       if (r < 0)
-               return r;
 
        if (venc->tv_dac_clk)
                clk_prepare_enable(venc->tv_dac_clk);
index 62928ec0e7db7a6fd6c53d1801c62a19dae80758..caffc547ef97e385cb913f77fd3ebe55a082d486 100644 (file)
@@ -350,11 +350,14 @@ static void omap_crtc_arm_event(struct drm_crtc *crtc)
 static void omap_crtc_atomic_enable(struct drm_crtc *crtc,
                                    struct drm_crtc_state *old_state)
 {
+       struct omap_drm_private *priv = crtc->dev->dev_private;
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
        int ret;
 
        DBG("%s", omap_crtc->name);
 
+       priv->dispc_ops->runtime_get(priv->dispc);
+
        spin_lock_irq(&crtc->dev->event_lock);
        drm_crtc_vblank_on(crtc);
        ret = drm_crtc_vblank_get(crtc);
@@ -367,6 +370,7 @@ static void omap_crtc_atomic_enable(struct drm_crtc *crtc,
 static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
                                     struct drm_crtc_state *old_state)
 {
+       struct omap_drm_private *priv = crtc->dev->dev_private;
        struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 
        DBG("%s", omap_crtc->name);
@@ -379,6 +383,8 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
        spin_unlock_irq(&crtc->dev->event_lock);
 
        drm_crtc_vblank_off(crtc);
+
+       priv->dispc_ops->runtime_put(priv->dispc);
 }
 
 static enum drm_mode_status omap_crtc_mode_valid(struct drm_crtc *crtc,
index 127468785f7484495df89a00989c17388548f9c5..1f94b9affe4bbafddede75306c3109b1368bc172 100644 (file)
@@ -214,6 +214,12 @@ static int vc4_atomic_commit(struct drm_device *dev,
                return 0;
        }
 
+       /* We know for sure we don't want an async update here. Set
+        * state->legacy_cursor_update to false to prevent
+        * drm_atomic_helper_setup_commit() from auto-completing
+        * commit->flip_done.
+        */
+       state->legacy_cursor_update = false;
        ret = drm_atomic_helper_setup_commit(state, nonblock);
        if (ret)
                return ret;
index 9dc3fcbd290bef915cea9d12472b79b3dd36db4a..c6635f23918a8c1ec07531fc6aeffede5e6e528f 100644 (file)
@@ -807,7 +807,7 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb)
 static void vc4_plane_atomic_async_update(struct drm_plane *plane,
                                          struct drm_plane_state *state)
 {
-       struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state);
+       struct vc4_plane_state *vc4_state, *new_vc4_state;
 
        if (plane->state->fb != state->fb) {
                vc4_plane_async_set_fb(plane, state->fb);
@@ -828,7 +828,18 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane,
        plane->state->src_y = state->src_y;
 
        /* Update the display list based on the new crtc_x/y. */
-       vc4_plane_atomic_check(plane, plane->state);
+       vc4_plane_atomic_check(plane, state);
+
+       new_vc4_state = to_vc4_plane_state(state);
+       vc4_state = to_vc4_plane_state(plane->state);
+
+       /* Update the current vc4_state pos0, pos2 and ptr0 dlist entries. */
+       vc4_state->dlist[vc4_state->pos0_offset] =
+               new_vc4_state->dlist[vc4_state->pos0_offset];
+       vc4_state->dlist[vc4_state->pos2_offset] =
+               new_vc4_state->dlist[vc4_state->pos2_offset];
+       vc4_state->dlist[vc4_state->ptr0_offset] =
+               new_vc4_state->dlist[vc4_state->ptr0_offset];
 
        /* Note that we can't just call vc4_plane_write_dlist()
         * because that would smash the context data that the HVS is
index a7513a8a8e3728d0de762d62f7337f527df34544..d6106e1a0d4af597d04cb833215c3b27c0b2aa0d 100644 (file)
@@ -353,6 +353,9 @@ static void process_ib_ipinfo(void *in_msg, void *out_msg, int op)
 
                out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled;
 
+               /* fallthrough */
+
+       case KVP_OP_GET_IP_INFO:
                utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id,
                                MAX_ADAPTER_ID_SIZE,
                                UTF16_LITTLE_ENDIAN,
@@ -405,7 +408,11 @@ kvp_send_key(struct work_struct *dummy)
                process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
                break;
        case KVP_OP_GET_IP_INFO:
-               /* We only need to pass on message->kvp_hdr.operation.  */
+               /*
+                * We only need to pass on the info of operation, adapter_id
+                * and addr_family to the userland kvp daemon.
+                */
+               process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
                break;
        case KVP_OP_SET:
                switch (in_msg->body.kvp_set.data.value_type) {
@@ -446,9 +453,9 @@ kvp_send_key(struct work_struct *dummy)
 
                }
 
-               break;
-
-       case KVP_OP_GET:
+               /*
+                * The key is always a string - utf16 encoding.
+                */
                message->body.kvp_set.data.key_size =
                        utf16s_to_utf8s(
                        (wchar_t *)in_msg->body.kvp_set.data.key,
@@ -456,6 +463,17 @@ kvp_send_key(struct work_struct *dummy)
                        UTF16_LITTLE_ENDIAN,
                        message->body.kvp_set.data.key,
                        HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
+
+               break;
+
+       case KVP_OP_GET:
+               message->body.kvp_get.data.key_size =
+                       utf16s_to_utf8s(
+                       (wchar_t *)in_msg->body.kvp_get.data.key,
+                       in_msg->body.kvp_get.data.key_size,
+                       UTF16_LITTLE_ENDIAN,
+                       message->body.kvp_get.data.key,
+                       HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
                break;
 
        case KVP_OP_DELETE:
index bb2cd29e165885d1697e4d77614a42333c5457dc..d8f7000a466aa4d2d3d79874428738fec70a4324 100644 (file)
@@ -797,7 +797,8 @@ static int iommu_init_ga_log(struct amd_iommu *iommu)
        entry = iommu_virt_to_phys(iommu->ga_log) | GA_LOG_SIZE_512;
        memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_BASE_OFFSET,
                    &entry, sizeof(entry));
-       entry = (iommu_virt_to_phys(iommu->ga_log) & 0xFFFFFFFFFFFFFULL) & ~7ULL;
+       entry = (iommu_virt_to_phys(iommu->ga_log_tail) &
+                (BIT_ULL(52)-1)) & ~7ULL;
        memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_TAIL_OFFSET,
                    &entry, sizeof(entry));
        writel(0x00, iommu->mmio_base + MMIO_GA_HEAD_OFFSET);
index f3ccf025108b4c377f2f9bc6de80e8222b817a01..41a4b8808802b8bcc30106c37b748eb3507943c0 100644 (file)
@@ -3075,7 +3075,7 @@ static int copy_context_table(struct intel_iommu *iommu,
                        }
 
                        if (old_ce)
-                               iounmap(old_ce);
+                               memunmap(old_ce);
 
                        ret = 0;
                        if (devfn < 0x80)
index db301efe126d4ac9cf2aeb606489565135db7e7d..88715090752670a5701cde52f8a4ce11baec1da4 100644 (file)
@@ -595,7 +595,7 @@ static irqreturn_t prq_event_thread(int irq, void *d)
                        pr_err("%s: Page request without PASID: %08llx %08llx\n",
                               iommu->name, ((unsigned long long *)req)[0],
                               ((unsigned long long *)req)[1]);
-                       goto bad_req;
+                       goto no_pasid;
                }
 
                if (!svm || svm->pasid != req->pasid) {
index b98a031895803a16b8e2d9d0df0a4b1686789aef..ddf3a492e1d59c1fd867f12881e6c3391038cf0f 100644 (file)
@@ -498,6 +498,9 @@ static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
 
 static void ipmmu_domain_destroy_context(struct ipmmu_vmsa_domain *domain)
 {
+       if (!domain->mmu)
+               return;
+
        /*
         * Disable the context. Flush the TLB as required when modifying the
         * context registers.
index 31d1f4ab915ea7e07f8843d1feb99217409a1af4..65a933a21e685b9c97fadc7662e34ad31c088798 100644 (file)
@@ -807,7 +807,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
        }
 
        if (adap->transmit_queue_sz >= CEC_MAX_MSG_TX_QUEUE_SZ) {
-               dprintk(1, "%s: transmit queue full\n", __func__);
+               dprintk(2, "%s: transmit queue full\n", __func__);
                return -EBUSY;
        }
 
@@ -1180,6 +1180,8 @@ static int cec_config_log_addr(struct cec_adapter *adap,
 {
        struct cec_log_addrs *las = &adap->log_addrs;
        struct cec_msg msg = { };
+       const unsigned int max_retries = 2;
+       unsigned int i;
        int err;
 
        if (cec_has_log_addr(adap, log_addr))
@@ -1188,19 +1190,44 @@ static int cec_config_log_addr(struct cec_adapter *adap,
        /* Send poll message */
        msg.len = 1;
        msg.msg[0] = (log_addr << 4) | log_addr;
-       err = cec_transmit_msg_fh(adap, &msg, NULL, true);
 
-       /*
-        * While trying to poll the physical address was reset
-        * and the adapter was unconfigured, so bail out.
-        */
-       if (!adap->is_configuring)
-               return -EINTR;
+       for (i = 0; i < max_retries; i++) {
+               err = cec_transmit_msg_fh(adap, &msg, NULL, true);
 
-       if (err)
-               return err;
+               /*
+                * While trying to poll the physical address was reset
+                * and the adapter was unconfigured, so bail out.
+                */
+               if (!adap->is_configuring)
+                       return -EINTR;
+
+               if (err)
+                       return err;
 
-       if (msg.tx_status & CEC_TX_STATUS_OK)
+               /*
+                * The message was aborted due to a disconnect or
+                * unconfigure, just bail out.
+                */
+               if (msg.tx_status & CEC_TX_STATUS_ABORTED)
+                       return -EINTR;
+               if (msg.tx_status & CEC_TX_STATUS_OK)
+                       return 0;
+               if (msg.tx_status & CEC_TX_STATUS_NACK)
+                       break;
+               /*
+                * Retry up to max_retries times if the message was neither
+                * OKed or NACKed. This can happen due to e.g. a Lost
+                * Arbitration condition.
+                */
+       }
+
+       /*
+        * If we are unable to get an OK or a NACK after max_retries attempts
+        * (and note that each attempt already consists of four polls), then
+        * then we assume that something is really weird and that it is not a
+        * good idea to try and claim this logical address.
+        */
+       if (i == max_retries)
                return 0;
 
        /*
index ca5d92942820a2fcb439ec1e7d277dd445214276..41d470d9ca943ea84653f9dd8bfb0ab83dafe1a4 100644 (file)
@@ -1918,7 +1918,6 @@ static int tc358743_probe_of(struct tc358743_state *state)
        ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep), &endpoint);
        if (ret) {
                dev_err(dev, "failed to parse endpoint\n");
-               ret = ret;
                goto put_node;
        }
 
index 452eb9b42140bb927e7af8287dcbe99b45ef51dd..447baaebca4486c4b5c3b8c5dc261ec3e4cd2ce8 100644 (file)
@@ -1844,14 +1844,12 @@ fail_mutex_destroy:
 static void cio2_pci_remove(struct pci_dev *pci_dev)
 {
        struct cio2_device *cio2 = pci_get_drvdata(pci_dev);
-       unsigned int i;
 
+       media_device_unregister(&cio2->media_dev);
        cio2_notifier_exit(cio2);
+       cio2_queues_exit(cio2);
        cio2_fbpt_exit_dummy(cio2);
-       for (i = 0; i < CIO2_QUEUES; i++)
-               cio2_queue_exit(cio2, &cio2->queue[i]);
        v4l2_device_unregister(&cio2->v4l2_dev);
-       media_device_unregister(&cio2->media_dev);
        media_device_cleanup(&cio2->media_dev);
        mutex_destroy(&cio2->lock);
 }
index 77fb7987b42f33cda57dc8b6627d4befc2d7a83e..13f2828d880df373ff494d10416ecb16be873bf7 100644 (file)
@@ -1587,6 +1587,8 @@ static void isp_pm_complete(struct device *dev)
 
 static void isp_unregister_entities(struct isp_device *isp)
 {
+       media_device_unregister(&isp->media_dev);
+
        omap3isp_csi2_unregister_entities(&isp->isp_csi2a);
        omap3isp_ccp2_unregister_entities(&isp->isp_ccp2);
        omap3isp_ccdc_unregister_entities(&isp->isp_ccdc);
@@ -1597,7 +1599,6 @@ static void isp_unregister_entities(struct isp_device *isp)
        omap3isp_stat_unregister_entities(&isp->isp_hist);
 
        v4l2_device_unregister(&isp->v4l2_dev);
-       media_device_unregister(&isp->media_dev);
        media_device_cleanup(&isp->media_dev);
 }
 
index 1eb9132bfc85fdad1ab68d81442fb435be0ac0f0..b292cff26c8663636a3cc959688032c8d79e6b3d 100644 (file)
@@ -42,7 +42,7 @@ MODULE_PARM_DESC(debug, " activates debug info");
 #define MAX_WIDTH              4096U
 #define MIN_WIDTH              640U
 #define MAX_HEIGHT             2160U
-#define MIN_HEIGHT             480U
+#define MIN_HEIGHT             360U
 
 #define dprintk(dev, fmt, arg...) \
        v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
index af150a0395dfb55ef55bf606df4825ec5b807912..d82db738f174ef048d663d366b4950cd732c2b43 100644 (file)
@@ -1009,7 +1009,7 @@ static const struct v4l2_m2m_ops m2m_ops = {
 
 static const struct media_device_ops m2m_media_ops = {
        .req_validate = vb2_request_validate,
-       .req_queue = vb2_m2m_request_queue,
+       .req_queue = v4l2_m2m_request_queue,
 };
 
 static int vim2m_probe(struct platform_device *pdev)
index 6e37950292cd9b832d589e1728fba7d28d469794..5f2b033a7a42f1cb35dd13e40a498232bd3a225d 100644 (file)
@@ -1664,6 +1664,11 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
                    p_mpeg2_slice_params->forward_ref_index >= VIDEO_MAX_FRAME)
                        return -EINVAL;
 
+               if (p_mpeg2_slice_params->pad ||
+                   p_mpeg2_slice_params->picture.pad ||
+                   p_mpeg2_slice_params->sequence.pad)
+                       return -EINVAL;
+
                return 0;
 
        case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION:
index a3ef1f50a4b3496dcfbe7cb4332a3bab9a3acc56..481e3c65cf97a63202e1223b106c59b5e670651b 100644 (file)
@@ -193,6 +193,22 @@ int v4l2_event_pending(struct v4l2_fh *fh)
 }
 EXPORT_SYMBOL_GPL(v4l2_event_pending);
 
+static void __v4l2_event_unsubscribe(struct v4l2_subscribed_event *sev)
+{
+       struct v4l2_fh *fh = sev->fh;
+       unsigned int i;
+
+       lockdep_assert_held(&fh->subscribe_lock);
+       assert_spin_locked(&fh->vdev->fh_lock);
+
+       /* Remove any pending events for this subscription */
+       for (i = 0; i < sev->in_use; i++) {
+               list_del(&sev->events[sev_pos(sev, i)].list);
+               fh->navailable--;
+       }
+       list_del(&sev->list);
+}
+
 int v4l2_event_subscribe(struct v4l2_fh *fh,
                         const struct v4l2_event_subscription *sub, unsigned elems,
                         const struct v4l2_subscribed_event_ops *ops)
@@ -224,27 +240,23 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
 
        spin_lock_irqsave(&fh->vdev->fh_lock, flags);
        found_ev = v4l2_event_subscribed(fh, sub->type, sub->id);
+       if (!found_ev)
+               list_add(&sev->list, &fh->subscribed);
        spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
 
        if (found_ev) {
                /* Already listening */
                kvfree(sev);
-               goto out_unlock;
-       }
-
-       if (sev->ops && sev->ops->add) {
+       } else if (sev->ops && sev->ops->add) {
                ret = sev->ops->add(sev, elems);
                if (ret) {
+                       spin_lock_irqsave(&fh->vdev->fh_lock, flags);
+                       __v4l2_event_unsubscribe(sev);
+                       spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
                        kvfree(sev);
-                       goto out_unlock;
                }
        }
 
-       spin_lock_irqsave(&fh->vdev->fh_lock, flags);
-       list_add(&sev->list, &fh->subscribed);
-       spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
-
-out_unlock:
        mutex_unlock(&fh->subscribe_lock);
 
        return ret;
@@ -279,7 +291,6 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
 {
        struct v4l2_subscribed_event *sev;
        unsigned long flags;
-       int i;
 
        if (sub->type == V4L2_EVENT_ALL) {
                v4l2_event_unsubscribe_all(fh);
@@ -291,14 +302,8 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
        spin_lock_irqsave(&fh->vdev->fh_lock, flags);
 
        sev = v4l2_event_subscribed(fh, sub->type, sub->id);
-       if (sev != NULL) {
-               /* Remove any pending events for this subscription */
-               for (i = 0; i < sev->in_use; i++) {
-                       list_del(&sev->events[sev_pos(sev, i)].list);
-                       fh->navailable--;
-               }
-               list_del(&sev->list);
-       }
+       if (sev != NULL)
+               __v4l2_event_unsubscribe(sev);
 
        spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
 
index d7806db222d83b87f39175fb53c06178d98b363e..1ed2465972acab4d0fae6aa4a8d28c966167d224 100644 (file)
@@ -953,7 +953,7 @@ void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx,
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue);
 
-void vb2_m2m_request_queue(struct media_request *req)
+void v4l2_m2m_request_queue(struct media_request *req)
 {
        struct media_request_object *obj, *obj_safe;
        struct v4l2_m2m_ctx *m2m_ctx = NULL;
@@ -997,7 +997,7 @@ void vb2_m2m_request_queue(struct media_request *req)
        if (m2m_ctx)
                v4l2_m2m_try_schedule(m2m_ctx);
 }
-EXPORT_SYMBOL_GPL(vb2_m2m_request_queue);
+EXPORT_SYMBOL_GPL(v4l2_m2m_request_queue);
 
 /* Videobuf2 ioctl helpers */
 
index b2a0340f277e268739c288e6bb73f62321475c30..d8e3cc2dc7470d8deaa3b89a5855b22b034725db 100644 (file)
@@ -132,7 +132,7 @@ static const struct of_device_id atmel_ssc_dt_ids[] = {
 MODULE_DEVICE_TABLE(of, atmel_ssc_dt_ids);
 #endif
 
-static inline const struct atmel_ssc_platform_data * __init
+static inline const struct atmel_ssc_platform_data *
        atmel_ssc_get_driver_data(struct platform_device *pdev)
 {
        if (pdev->dev.of_node) {
index 313da31502626897a61a65606aa117d0d67dc83b..1540a7785e14743ae1b035aeb21d391af8516050 100644 (file)
@@ -27,6 +27,9 @@
 #include <linux/delay.h>
 #include <linux/bitops.h>
 #include <asm/uv/uv_hub.h>
+
+#include <linux/nospec.h>
+
 #include "gru.h"
 #include "grutables.h"
 #include "gruhandles.h"
@@ -196,6 +199,7 @@ int gru_dump_chiplet_request(unsigned long arg)
        /* Currently, only dump by gid is implemented */
        if (req.gid >= gru_max_gids)
                return -EINVAL;
+       req.gid = array_index_nospec(req.gid, gru_max_gids);
 
        gru = GID_TO_GRU(req.gid);
        ubuf = req.buf;
index 7bfd366d970dae374bae6acd36624eb23f719506..c4115bae5db187f1a331efd5c495b20bc31a5c86 100644 (file)
@@ -12,6 +12,7 @@
  *     - JMicron (hardware and technical support)
  */
 
+#include <linux/bitfield.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/highmem.h>
@@ -462,6 +463,9 @@ struct intel_host {
        u32     dsm_fns;
        int     drv_strength;
        bool    d3_retune;
+       bool    rpm_retune_ok;
+       u32     glk_rx_ctrl1;
+       u32     glk_tun_val;
 };
 
 static const guid_t intel_dsm_guid =
@@ -791,6 +795,77 @@ cleanup:
        return ret;
 }
 
+#ifdef CONFIG_PM
+#define GLK_RX_CTRL1   0x834
+#define GLK_TUN_VAL    0x840
+#define GLK_PATH_PLL   GENMASK(13, 8)
+#define GLK_DLY                GENMASK(6, 0)
+/* Workaround firmware failing to restore the tuning value */
+static void glk_rpm_retune_wa(struct sdhci_pci_chip *chip, bool susp)
+{
+       struct sdhci_pci_slot *slot = chip->slots[0];
+       struct intel_host *intel_host = sdhci_pci_priv(slot);
+       struct sdhci_host *host = slot->host;
+       u32 glk_rx_ctrl1;
+       u32 glk_tun_val;
+       u32 dly;
+
+       if (intel_host->rpm_retune_ok || !mmc_can_retune(host->mmc))
+               return;
+
+       glk_rx_ctrl1 = sdhci_readl(host, GLK_RX_CTRL1);
+       glk_tun_val = sdhci_readl(host, GLK_TUN_VAL);
+
+       if (susp) {
+               intel_host->glk_rx_ctrl1 = glk_rx_ctrl1;
+               intel_host->glk_tun_val = glk_tun_val;
+               return;
+       }
+
+       if (!intel_host->glk_tun_val)
+               return;
+
+       if (glk_rx_ctrl1 != intel_host->glk_rx_ctrl1) {
+               intel_host->rpm_retune_ok = true;
+               return;
+       }
+
+       dly = FIELD_PREP(GLK_DLY, FIELD_GET(GLK_PATH_PLL, glk_rx_ctrl1) +
+                                 (intel_host->glk_tun_val << 1));
+       if (dly == FIELD_GET(GLK_DLY, glk_rx_ctrl1))
+               return;
+
+       glk_rx_ctrl1 = (glk_rx_ctrl1 & ~GLK_DLY) | dly;
+       sdhci_writel(host, glk_rx_ctrl1, GLK_RX_CTRL1);
+
+       intel_host->rpm_retune_ok = true;
+       chip->rpm_retune = true;
+       mmc_retune_needed(host->mmc);
+       pr_info("%s: Requiring re-tune after rpm resume", mmc_hostname(host->mmc));
+}
+
+static void glk_rpm_retune_chk(struct sdhci_pci_chip *chip, bool susp)
+{
+       if (chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_EMMC &&
+           !chip->rpm_retune)
+               glk_rpm_retune_wa(chip, susp);
+}
+
+static int glk_runtime_suspend(struct sdhci_pci_chip *chip)
+{
+       glk_rpm_retune_chk(chip, true);
+
+       return sdhci_cqhci_runtime_suspend(chip);
+}
+
+static int glk_runtime_resume(struct sdhci_pci_chip *chip)
+{
+       glk_rpm_retune_chk(chip, false);
+
+       return sdhci_cqhci_runtime_resume(chip);
+}
+#endif
+
 #ifdef CONFIG_ACPI
 static int ni_set_max_freq(struct sdhci_pci_slot *slot)
 {
@@ -879,8 +954,8 @@ static const struct sdhci_pci_fixes sdhci_intel_glk_emmc = {
        .resume                 = sdhci_cqhci_resume,
 #endif
 #ifdef CONFIG_PM
-       .runtime_suspend        = sdhci_cqhci_runtime_suspend,
-       .runtime_resume         = sdhci_cqhci_runtime_resume,
+       .runtime_suspend        = glk_runtime_suspend,
+       .runtime_resume         = glk_runtime_resume,
 #endif
        .quirks                 = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
        .quirks2                = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
@@ -1762,8 +1837,13 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
                device_init_wakeup(&pdev->dev, true);
 
        if (slot->cd_idx >= 0) {
-               ret = mmc_gpiod_request_cd(host->mmc, NULL, slot->cd_idx,
+               ret = mmc_gpiod_request_cd(host->mmc, "cd", slot->cd_idx,
                                           slot->cd_override_level, 0, NULL);
+               if (ret && ret != -EPROBE_DEFER)
+                       ret = mmc_gpiod_request_cd(host->mmc, NULL,
+                                                  slot->cd_idx,
+                                                  slot->cd_override_level,
+                                                  0, NULL);
                if (ret == -EPROBE_DEFER)
                        goto remove;
 
index fb33f6be7c4ff7306f391931e1843f6712edbdb7..ad720494e8f78dfd74995ba067a8ea973f555980 100644 (file)
@@ -2032,8 +2032,7 @@ atmel_hsmc_nand_controller_legacy_init(struct atmel_hsmc_nand_controller *nc)
        int ret;
 
        nand_np = dev->of_node;
-       nfc_np = of_find_compatible_node(dev->of_node, NULL,
-                                        "atmel,sama5d3-nfc");
+       nfc_np = of_get_compatible_child(dev->of_node, "atmel,sama5d3-nfc");
        if (!nfc_np) {
                dev_err(dev, "Could not find device node for sama5d3-nfc\n");
                return -ENODEV;
@@ -2447,15 +2446,19 @@ static int atmel_nand_controller_probe(struct platform_device *pdev)
        }
 
        if (caps->legacy_of_bindings) {
+               struct device_node *nfc_node;
                u32 ale_offs = 21;
 
                /*
                 * If we are parsing legacy DT props and the DT contains a
                 * valid NFC node, forward the request to the sama5 logic.
                 */
-               if (of_find_compatible_node(pdev->dev.of_node, NULL,
-                                           "atmel,sama5d3-nfc"))
+               nfc_node = of_get_compatible_child(pdev->dev.of_node,
+                                                  "atmel,sama5d3-nfc");
+               if (nfc_node) {
                        caps = &atmel_sama5_nand_caps;
+                       of_node_put(nfc_node);
+               }
 
                /*
                 * Even if the compatible says we are dealing with an
index ef75dfa62a4f816f49d6008dcc3bbd7561293530..699d3cf49c6da04b49180cda81d3b5d05fc66563 100644 (file)
 #define        NAND_VERSION_MINOR_SHIFT        16
 
 /* NAND OP_CMDs */
-#define        PAGE_READ                       0x2
-#define        PAGE_READ_WITH_ECC              0x3
-#define        PAGE_READ_WITH_ECC_SPARE        0x4
-#define        PROGRAM_PAGE                    0x6
-#define        PAGE_PROGRAM_WITH_ECC           0x7
-#define        PROGRAM_PAGE_SPARE              0x9
-#define        BLOCK_ERASE                     0xa
-#define        FETCH_ID                        0xb
-#define        RESET_DEVICE                    0xd
+#define        OP_PAGE_READ                    0x2
+#define        OP_PAGE_READ_WITH_ECC           0x3
+#define        OP_PAGE_READ_WITH_ECC_SPARE     0x4
+#define        OP_PROGRAM_PAGE                 0x6
+#define        OP_PAGE_PROGRAM_WITH_ECC        0x7
+#define        OP_PROGRAM_PAGE_SPARE           0x9
+#define        OP_BLOCK_ERASE                  0xa
+#define        OP_FETCH_ID                     0xb
+#define        OP_RESET_DEVICE                 0xd
 
 /* Default Value for NAND_DEV_CMD_VLD */
 #define NAND_DEV_CMD_VLD_VAL           (READ_START_VLD | WRITE_START_VLD | \
@@ -692,11 +692,11 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read)
 
        if (read) {
                if (host->use_ecc)
-                       cmd = PAGE_READ_WITH_ECC | PAGE_ACC | LAST_PAGE;
+                       cmd = OP_PAGE_READ_WITH_ECC | PAGE_ACC | LAST_PAGE;
                else
-                       cmd = PAGE_READ | PAGE_ACC | LAST_PAGE;
+                       cmd = OP_PAGE_READ | PAGE_ACC | LAST_PAGE;
        } else {
-                       cmd = PROGRAM_PAGE | PAGE_ACC | LAST_PAGE;
+               cmd = OP_PROGRAM_PAGE | PAGE_ACC | LAST_PAGE;
        }
 
        if (host->use_ecc) {
@@ -1170,7 +1170,7 @@ static int nandc_param(struct qcom_nand_host *host)
         * in use. we configure the controller to perform a raw read of 512
         * bytes to read onfi params
         */
-       nandc_set_reg(nandc, NAND_FLASH_CMD, PAGE_READ | PAGE_ACC | LAST_PAGE);
+       nandc_set_reg(nandc, NAND_FLASH_CMD, OP_PAGE_READ | PAGE_ACC | LAST_PAGE);
        nandc_set_reg(nandc, NAND_ADDR0, 0);
        nandc_set_reg(nandc, NAND_ADDR1, 0);
        nandc_set_reg(nandc, NAND_DEV0_CFG0, 0 << CW_PER_PAGE
@@ -1224,7 +1224,7 @@ static int erase_block(struct qcom_nand_host *host, int page_addr)
        struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
 
        nandc_set_reg(nandc, NAND_FLASH_CMD,
-                     BLOCK_ERASE | PAGE_ACC | LAST_PAGE);
+                     OP_BLOCK_ERASE | PAGE_ACC | LAST_PAGE);
        nandc_set_reg(nandc, NAND_ADDR0, page_addr);
        nandc_set_reg(nandc, NAND_ADDR1, 0);
        nandc_set_reg(nandc, NAND_DEV0_CFG0,
@@ -1255,7 +1255,7 @@ static int read_id(struct qcom_nand_host *host, int column)
        if (column == -1)
                return 0;
 
-       nandc_set_reg(nandc, NAND_FLASH_CMD, FETCH_ID);
+       nandc_set_reg(nandc, NAND_FLASH_CMD, OP_FETCH_ID);
        nandc_set_reg(nandc, NAND_ADDR0, column);
        nandc_set_reg(nandc, NAND_ADDR1, 0);
        nandc_set_reg(nandc, NAND_FLASH_CHIP_SELECT,
@@ -1276,7 +1276,7 @@ static int reset(struct qcom_nand_host *host)
        struct nand_chip *chip = &host->chip;
        struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
 
-       nandc_set_reg(nandc, NAND_FLASH_CMD, RESET_DEVICE);
+       nandc_set_reg(nandc, NAND_FLASH_CMD, OP_RESET_DEVICE);
        nandc_set_reg(nandc, NAND_EXEC_CMD, 1);
 
        write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL);
index d846428ef038e6b76f84591f73d40e9a4d30db33..04cedd3a2bf6634c5d1f05ef3d27ba302d12935f 100644 (file)
@@ -644,9 +644,23 @@ static int cqspi_indirect_write_execute(struct spi_nor *nor, loff_t to_addr,
                ndelay(cqspi->wr_delay);
 
        while (remaining > 0) {
+               size_t write_words, mod_bytes;
+
                write_bytes = remaining > page_size ? page_size : remaining;
-               iowrite32_rep(cqspi->ahb_base, txbuf,
-                             DIV_ROUND_UP(write_bytes, 4));
+               write_words = write_bytes / 4;
+               mod_bytes = write_bytes % 4;
+               /* Write 4 bytes at a time then single bytes. */
+               if (write_words) {
+                       iowrite32_rep(cqspi->ahb_base, txbuf, write_words);
+                       txbuf += (write_words * 4);
+               }
+               if (mod_bytes) {
+                       unsigned int temp = 0xFFFFFFFF;
+
+                       memcpy(&temp, txbuf, mod_bytes);
+                       iowrite32(temp, cqspi->ahb_base);
+                       txbuf += mod_bytes;
+               }
 
                if (!wait_for_completion_timeout(&cqspi->transfer_complete,
                                        msecs_to_jiffies(CQSPI_TIMEOUT_MS))) {
@@ -655,7 +669,6 @@ static int cqspi_indirect_write_execute(struct spi_nor *nor, loff_t to_addr,
                        goto failwr;
                }
 
-               txbuf += write_bytes;
                remaining -= write_bytes;
 
                if (remaining > 0)
index 3e54e31889c7b53bbba362a5bd497279dc91b128..93c9bc8931fcd9137c99f95c2f34d31e521eb557 100644 (file)
@@ -2156,7 +2156,7 @@ spi_nor_set_pp_settings(struct spi_nor_pp_command *pp,
  * @nor:       pointer to a 'struct spi_nor'
  * @addr:      offset in the serial flash memory
  * @len:       number of bytes to read
- * @buf:       buffer where the data is copied into
+ * @buf:       buffer where the data is copied into (dma-safe memory)
  *
  * Return: 0 on success, -errno otherwise.
  */
@@ -2521,6 +2521,34 @@ static int spi_nor_map_cmp_erase_type(const void *l, const void *r)
        return left->size - right->size;
 }
 
+/**
+ * spi_nor_sort_erase_mask() - sort erase mask
+ * @map:       the erase map of the SPI NOR
+ * @erase_mask:        the erase type mask to be sorted
+ *
+ * Replicate the sort done for the map's erase types in BFPT: sort the erase
+ * mask in ascending order with the smallest erase type size starting from
+ * BIT(0) in the sorted erase mask.
+ *
+ * Return: sorted erase mask.
+ */
+static u8 spi_nor_sort_erase_mask(struct spi_nor_erase_map *map, u8 erase_mask)
+{
+       struct spi_nor_erase_type *erase_type = map->erase_type;
+       int i;
+       u8 sorted_erase_mask = 0;
+
+       if (!erase_mask)
+               return 0;
+
+       /* Replicate the sort done for the map's erase types. */
+       for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
+               if (erase_type[i].size && erase_mask & BIT(erase_type[i].idx))
+                       sorted_erase_mask |= BIT(i);
+
+       return sorted_erase_mask;
+}
+
 /**
  * spi_nor_regions_sort_erase_types() - sort erase types in each region
  * @map:       the erase map of the SPI NOR
@@ -2536,19 +2564,13 @@ static int spi_nor_map_cmp_erase_type(const void *l, const void *r)
 static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map)
 {
        struct spi_nor_erase_region *region = map->regions;
-       struct spi_nor_erase_type *erase_type = map->erase_type;
-       int i;
        u8 region_erase_mask, sorted_erase_mask;
 
        while (region) {
                region_erase_mask = region->offset & SNOR_ERASE_TYPE_MASK;
 
-               /* Replicate the sort done for the map's erase types. */
-               sorted_erase_mask = 0;
-               for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
-                       if (erase_type[i].size &&
-                           region_erase_mask & BIT(erase_type[i].idx))
-                               sorted_erase_mask |= BIT(i);
+               sorted_erase_mask = spi_nor_sort_erase_mask(map,
+                                                           region_erase_mask);
 
                /* Overwrite erase mask. */
                region->offset = (region->offset & ~SNOR_ERASE_TYPE_MASK) |
@@ -2855,52 +2877,84 @@ static u8 spi_nor_smpt_read_dummy(const struct spi_nor *nor, const u32 settings)
  * spi_nor_get_map_in_use() - get the configuration map in use
  * @nor:       pointer to a 'struct spi_nor'
  * @smpt:      pointer to the sector map parameter table
+ * @smpt_len:  sector map parameter table length
+ *
+ * Return: pointer to the map in use, ERR_PTR(-errno) otherwise.
  */
-static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt)
+static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt,
+                                        u8 smpt_len)
 {
-       const u32 *ret = NULL;
-       u32 i, addr;
+       const u32 *ret;
+       u8 *buf;
+       u32 addr;
        int err;
+       u8 i;
        u8 addr_width, read_opcode, read_dummy;
-       u8 read_data_mask, data_byte, map_id;
+       u8 read_data_mask, map_id;
+
+       /* Use a kmalloc'ed bounce buffer to guarantee it is DMA-able. */
+       buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+       if (!buf)
+               return ERR_PTR(-ENOMEM);
 
        addr_width = nor->addr_width;
        read_dummy = nor->read_dummy;
        read_opcode = nor->read_opcode;
 
        map_id = 0;
-       i = 0;
        /* Determine if there are any optional Detection Command Descriptors */
-       while (!(smpt[i] & SMPT_DESC_TYPE_MAP)) {
+       for (i = 0; i < smpt_len; i += 2) {
+               if (smpt[i] & SMPT_DESC_TYPE_MAP)
+                       break;
+
                read_data_mask = SMPT_CMD_READ_DATA(smpt[i]);
                nor->addr_width = spi_nor_smpt_addr_width(nor, smpt[i]);
                nor->read_dummy = spi_nor_smpt_read_dummy(nor, smpt[i]);
                nor->read_opcode = SMPT_CMD_OPCODE(smpt[i]);
                addr = smpt[i + 1];
 
-               err = spi_nor_read_raw(nor, addr, 1, &data_byte);
-               if (err)
+               err = spi_nor_read_raw(nor, addr, 1, buf);
+               if (err) {
+                       ret = ERR_PTR(err);
                        goto out;
+               }
 
                /*
                 * Build an index value that is used to select the Sector Map
                 * Configuration that is currently in use.
                 */
-               map_id = map_id << 1 | !!(data_byte & read_data_mask);
-               i = i + 2;
+               map_id = map_id << 1 | !!(*buf & read_data_mask);
        }
 
-       /* Find the matching configuration map */
-       while (SMPT_MAP_ID(smpt[i]) != map_id) {
+       /*
+        * If command descriptors are provided, they always precede map
+        * descriptors in the table. There is no need to start the iteration
+        * over smpt array all over again.
+        *
+        * Find the matching configuration map.
+        */
+       ret = ERR_PTR(-EINVAL);
+       while (i < smpt_len) {
+               if (SMPT_MAP_ID(smpt[i]) == map_id) {
+                       ret = smpt + i;
+                       break;
+               }
+
+               /*
+                * If there are no more configuration map descriptors and no
+                * configuration ID matched the configuration identifier, the
+                * sector address map is unknown.
+                */
                if (smpt[i] & SMPT_DESC_END)
-                       goto out;
+                       break;
+
                /* increment the table index to the next map */
                i += SMPT_MAP_REGION_COUNT(smpt[i]) + 1;
        }
 
-       ret = smpt + i;
        /* fall through */
 out:
+       kfree(buf);
        nor->addr_width = addr_width;
        nor->read_dummy = read_dummy;
        nor->read_opcode = read_opcode;
@@ -2946,7 +3000,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
        u64 offset;
        u32 region_count;
        int i, j;
-       u8 erase_type;
+       u8 erase_type, uniform_erase_type;
 
        region_count = SMPT_MAP_REGION_COUNT(*smpt);
        /*
@@ -2959,7 +3013,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
                return -ENOMEM;
        map->regions = region;
 
-       map->uniform_erase_type = 0xff;
+       uniform_erase_type = 0xff;
        offset = 0;
        /* Populate regions. */
        for (i = 0; i < region_count; i++) {
@@ -2974,12 +3028,15 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
                 * Save the erase types that are supported in all regions and
                 * can erase the entire flash memory.
                 */
-               map->uniform_erase_type &= erase_type;
+               uniform_erase_type &= erase_type;
 
                offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) +
                         region[i].size;
        }
 
+       map->uniform_erase_type = spi_nor_sort_erase_mask(map,
+                                                         uniform_erase_type);
+
        spi_nor_region_mark_end(&region[i - 1]);
 
        return 0;
@@ -3020,9 +3077,9 @@ static int spi_nor_parse_smpt(struct spi_nor *nor,
        for (i = 0; i < smpt_header->length; i++)
                smpt[i] = le32_to_cpu(smpt[i]);
 
-       sector_map = spi_nor_get_map_in_use(nor, smpt);
-       if (!sector_map) {
-               ret = -EINVAL;
+       sector_map = spi_nor_get_map_in_use(nor, smpt, smpt_header->length);
+       if (IS_ERR(sector_map)) {
+               ret = PTR_ERR(sector_map);
                goto out;
        }
 
@@ -3125,7 +3182,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
        if (err)
                goto exit;
 
-       /* Parse other parameter headers. */
+       /* Parse optional parameter tables. */
        for (i = 0; i < header.nph; i++) {
                param_header = &param_headers[i];
 
@@ -3138,8 +3195,17 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
                        break;
                }
 
-               if (err)
-                       goto exit;
+               if (err) {
+                       dev_warn(dev, "Failed to parse optional parameter table: %04x\n",
+                                SFDP_PARAM_HEADER_ID(param_header));
+                       /*
+                        * Let's not drop all information we extracted so far
+                        * if optional table parsers fail. In case of failing,
+                        * each optional parser is responsible to roll back to
+                        * the previously known spi_nor data.
+                        */
+                       err = 0;
+               }
        }
 
 exit:
index 49163570a63afad2e36777993a57319370d6c8b0..3b3f88ffab53cded04a2c1586727bf82472f43ad 100644 (file)
@@ -477,6 +477,34 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
 }
 EXPORT_SYMBOL_GPL(can_put_echo_skb);
 
+struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
+{
+       struct can_priv *priv = netdev_priv(dev);
+       struct sk_buff *skb = priv->echo_skb[idx];
+       struct canfd_frame *cf;
+
+       if (idx >= priv->echo_skb_max) {
+               netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
+                          __func__, idx, priv->echo_skb_max);
+               return NULL;
+       }
+
+       if (!skb) {
+               netdev_err(dev, "%s: BUG! Trying to echo non existing skb: can_priv::echo_skb[%u]\n",
+                          __func__, idx);
+               return NULL;
+       }
+
+       /* Using "struct canfd_frame::len" for the frame
+        * length is supported on both CAN and CANFD frames.
+        */
+       cf = (struct canfd_frame *)skb->data;
+       *len_ptr = cf->len;
+       priv->echo_skb[idx] = NULL;
+
+       return skb;
+}
+
 /*
  * Get the skb from the stack and loop it back locally
  *
@@ -486,22 +514,16 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb);
  */
 unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
 {
-       struct can_priv *priv = netdev_priv(dev);
-
-       BUG_ON(idx >= priv->echo_skb_max);
-
-       if (priv->echo_skb[idx]) {
-               struct sk_buff *skb = priv->echo_skb[idx];
-               struct can_frame *cf = (struct can_frame *)skb->data;
-               u8 dlc = cf->can_dlc;
+       struct sk_buff *skb;
+       u8 len;
 
-               netif_rx(priv->echo_skb[idx]);
-               priv->echo_skb[idx] = NULL;
+       skb = __can_get_echo_skb(dev, idx, &len);
+       if (!skb)
+               return 0;
 
-               return dlc;
-       }
+       netif_rx(skb);
 
-       return 0;
+       return len;
 }
 EXPORT_SYMBOL_GPL(can_get_echo_skb);
 
index 8e972ef0863769e88a2c9d6cec37408d66566292..75ce11395ee8196f0dc3ed8b1368e591047d5edd 100644 (file)
 
 /* FLEXCAN interrupt flag register (IFLAG) bits */
 /* Errata ERR005829 step7: Reserve first valid MB */
-#define FLEXCAN_TX_MB_RESERVED_OFF_FIFO        8
-#define FLEXCAN_TX_MB_OFF_FIFO         9
+#define FLEXCAN_TX_MB_RESERVED_OFF_FIFO                8
 #define FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP   0
-#define FLEXCAN_TX_MB_OFF_TIMESTAMP            1
-#define FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST      (FLEXCAN_TX_MB_OFF_TIMESTAMP + 1)
-#define FLEXCAN_RX_MB_OFF_TIMESTAMP_LAST       63
-#define FLEXCAN_IFLAG_MB(x)            BIT(x)
+#define FLEXCAN_TX_MB                          63
+#define FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST      (FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP + 1)
+#define FLEXCAN_RX_MB_OFF_TIMESTAMP_LAST       (FLEXCAN_TX_MB - 1)
+#define FLEXCAN_IFLAG_MB(x)            BIT(x & 0x1f)
 #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW BIT(7)
 #define FLEXCAN_IFLAG_RX_FIFO_WARN     BIT(6)
 #define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE        BIT(5)
@@ -259,9 +258,7 @@ struct flexcan_priv {
        struct can_rx_offload offload;
 
        struct flexcan_regs __iomem *regs;
-       struct flexcan_mb __iomem *tx_mb;
        struct flexcan_mb __iomem *tx_mb_reserved;
-       u8 tx_mb_idx;
        u32 reg_ctrl_default;
        u32 reg_imask1_default;
        u32 reg_imask2_default;
@@ -515,6 +512,7 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
 static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        const struct flexcan_priv *priv = netdev_priv(dev);
+       struct flexcan_regs __iomem *regs = priv->regs;
        struct can_frame *cf = (struct can_frame *)skb->data;
        u32 can_id;
        u32 data;
@@ -537,17 +535,17 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
 
        if (cf->can_dlc > 0) {
                data = be32_to_cpup((__be32 *)&cf->data[0]);
-               priv->write(data, &priv->tx_mb->data[0]);
+               priv->write(data, &regs->mb[FLEXCAN_TX_MB].data[0]);
        }
        if (cf->can_dlc > 4) {
                data = be32_to_cpup((__be32 *)&cf->data[4]);
-               priv->write(data, &priv->tx_mb->data[1]);
+               priv->write(data, &regs->mb[FLEXCAN_TX_MB].data[1]);
        }
 
        can_put_echo_skb(skb, dev, 0);
 
-       priv->write(can_id, &priv->tx_mb->can_id);
-       priv->write(ctrl, &priv->tx_mb->can_ctrl);
+       priv->write(can_id, &regs->mb[FLEXCAN_TX_MB].can_id);
+       priv->write(ctrl, &regs->mb[FLEXCAN_TX_MB].can_ctrl);
 
        /* Errata ERR005829 step8:
         * Write twice INACTIVE(0x8) code to first MB.
@@ -563,9 +561,13 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
 static void flexcan_irq_bus_err(struct net_device *dev, u32 reg_esr)
 {
        struct flexcan_priv *priv = netdev_priv(dev);
+       struct flexcan_regs __iomem *regs = priv->regs;
        struct sk_buff *skb;
        struct can_frame *cf;
        bool rx_errors = false, tx_errors = false;
+       u32 timestamp;
+
+       timestamp = priv->read(&regs->timer) << 16;
 
        skb = alloc_can_err_skb(dev, &cf);
        if (unlikely(!skb))
@@ -612,17 +614,21 @@ static void flexcan_irq_bus_err(struct net_device *dev, u32 reg_esr)
        if (tx_errors)
                dev->stats.tx_errors++;
 
-       can_rx_offload_irq_queue_err_skb(&priv->offload, skb);
+       can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
 }
 
 static void flexcan_irq_state(struct net_device *dev, u32 reg_esr)
 {
        struct flexcan_priv *priv = netdev_priv(dev);
+       struct flexcan_regs __iomem *regs = priv->regs;
        struct sk_buff *skb;
        struct can_frame *cf;
        enum can_state new_state, rx_state, tx_state;
        int flt;
        struct can_berr_counter bec;
+       u32 timestamp;
+
+       timestamp = priv->read(&regs->timer) << 16;
 
        flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK;
        if (likely(flt == FLEXCAN_ESR_FLT_CONF_ACTIVE)) {
@@ -652,7 +658,7 @@ static void flexcan_irq_state(struct net_device *dev, u32 reg_esr)
        if (unlikely(new_state == CAN_STATE_BUS_OFF))
                can_bus_off(dev);
 
-       can_rx_offload_irq_queue_err_skb(&priv->offload, skb);
+       can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
 }
 
 static inline struct flexcan_priv *rx_offload_to_priv(struct can_rx_offload *offload)
@@ -720,9 +726,14 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload,
                        priv->write(BIT(n - 32), &regs->iflag2);
        } else {
                priv->write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
-               priv->read(&regs->timer);
        }
 
+       /* Read the Free Running Timer. It is optional but recommended
+        * to unlock Mailbox as soon as possible and make it available
+        * for reception.
+        */
+       priv->read(&regs->timer);
+
        return 1;
 }
 
@@ -732,9 +743,9 @@ static inline u64 flexcan_read_reg_iflag_rx(struct flexcan_priv *priv)
        struct flexcan_regs __iomem *regs = priv->regs;
        u32 iflag1, iflag2;
 
-       iflag2 = priv->read(&regs->iflag2) & priv->reg_imask2_default;
-       iflag1 = priv->read(&regs->iflag1) & priv->reg_imask1_default &
-               ~FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
+       iflag2 = priv->read(&regs->iflag2) & priv->reg_imask2_default &
+               ~FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB);
+       iflag1 = priv->read(&regs->iflag1) & priv->reg_imask1_default;
 
        return (u64)iflag2 << 32 | iflag1;
 }
@@ -746,11 +757,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
        struct flexcan_priv *priv = netdev_priv(dev);
        struct flexcan_regs __iomem *regs = priv->regs;
        irqreturn_t handled = IRQ_NONE;
-       u32 reg_iflag1, reg_esr;
+       u32 reg_iflag2, reg_esr;
        enum can_state last_state = priv->can.state;
 
-       reg_iflag1 = priv->read(&regs->iflag1);
-
        /* reception interrupt */
        if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
                u64 reg_iflag;
@@ -764,6 +773,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
                                break;
                }
        } else {
+               u32 reg_iflag1;
+
+               reg_iflag1 = priv->read(&regs->iflag1);
                if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) {
                        handled = IRQ_HANDLED;
                        can_rx_offload_irq_offload_fifo(&priv->offload);
@@ -779,17 +791,22 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
                }
        }
 
+       reg_iflag2 = priv->read(&regs->iflag2);
+
        /* transmission complete interrupt */
-       if (reg_iflag1 & FLEXCAN_IFLAG_MB(priv->tx_mb_idx)) {
+       if (reg_iflag2 & FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB)) {
+               u32 reg_ctrl = priv->read(&regs->mb[FLEXCAN_TX_MB].can_ctrl);
+
                handled = IRQ_HANDLED;
-               stats->tx_bytes += can_get_echo_skb(dev, 0);
+               stats->tx_bytes += can_rx_offload_get_echo_skb(&priv->offload,
+                                                              0, reg_ctrl << 16);
                stats->tx_packets++;
                can_led_event(dev, CAN_LED_EVENT_TX);
 
                /* after sending a RTR frame MB is in RX mode */
                priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
-                           &priv->tx_mb->can_ctrl);
-               priv->write(FLEXCAN_IFLAG_MB(priv->tx_mb_idx), &regs->iflag1);
+                           &regs->mb[FLEXCAN_TX_MB].can_ctrl);
+               priv->write(FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB), &regs->iflag2);
                netif_wake_queue(dev);
        }
 
@@ -931,15 +948,13 @@ static int flexcan_chip_start(struct net_device *dev)
        reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
        reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV |
                FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_IRMQ |
-               FLEXCAN_MCR_IDAM_C;
+               FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(FLEXCAN_TX_MB);
 
-       if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
+       if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
                reg_mcr &= ~FLEXCAN_MCR_FEN;
-               reg_mcr |= FLEXCAN_MCR_MAXMB(priv->offload.mb_last);
-       } else {
-               reg_mcr |= FLEXCAN_MCR_FEN |
-                       FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
-       }
+       else
+               reg_mcr |= FLEXCAN_MCR_FEN;
+
        netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
        priv->write(reg_mcr, &regs->mcr);
 
@@ -982,16 +997,17 @@ static int flexcan_chip_start(struct net_device *dev)
                priv->write(reg_ctrl2, &regs->ctrl2);
        }
 
-       /* clear and invalidate all mailboxes first */
-       for (i = priv->tx_mb_idx; i < ARRAY_SIZE(regs->mb); i++) {
-               priv->write(FLEXCAN_MB_CODE_RX_INACTIVE,
-                           &regs->mb[i].can_ctrl);
-       }
-
        if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
-               for (i = priv->offload.mb_first; i <= priv->offload.mb_last; i++)
+               for (i = priv->offload.mb_first; i <= priv->offload.mb_last; i++) {
                        priv->write(FLEXCAN_MB_CODE_RX_EMPTY,
                                    &regs->mb[i].can_ctrl);
+               }
+       } else {
+               /* clear and invalidate unused mailboxes first */
+               for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i <= ARRAY_SIZE(regs->mb); i++) {
+                       priv->write(FLEXCAN_MB_CODE_RX_INACTIVE,
+                                   &regs->mb[i].can_ctrl);
+               }
        }
 
        /* Errata ERR005829: mark first TX mailbox as INACTIVE */
@@ -1000,7 +1016,7 @@ static int flexcan_chip_start(struct net_device *dev)
 
        /* mark TX mailbox as INACTIVE */
        priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
-                   &priv->tx_mb->can_ctrl);
+                   &regs->mb[FLEXCAN_TX_MB].can_ctrl);
 
        /* acceptance mask/acceptance code (accept everything) */
        priv->write(0x0, &regs->rxgmask);
@@ -1355,17 +1371,13 @@ static int flexcan_probe(struct platform_device *pdev)
        priv->devtype_data = devtype_data;
        priv->reg_xceiver = reg_xceiver;
 
-       if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
-               priv->tx_mb_idx = FLEXCAN_TX_MB_OFF_TIMESTAMP;
+       if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
                priv->tx_mb_reserved = &regs->mb[FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP];
-       } else {
-               priv->tx_mb_idx = FLEXCAN_TX_MB_OFF_FIFO;
+       else
                priv->tx_mb_reserved = &regs->mb[FLEXCAN_TX_MB_RESERVED_OFF_FIFO];
-       }
-       priv->tx_mb = &regs->mb[priv->tx_mb_idx];
 
-       priv->reg_imask1_default = FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
-       priv->reg_imask2_default = 0;
+       priv->reg_imask1_default = 0;
+       priv->reg_imask2_default = FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB);
 
        priv->offload.mailbox_read = flexcan_mailbox_read;
 
index 11662f479e760ba77f613c90bfc8026b005da3ea..771a4608373978c31b7011a45cf5659f543820c1 100644 (file)
@@ -24,6 +24,9 @@
 
 #define RCAR_CAN_DRV_NAME      "rcar_can"
 
+#define RCAR_SUPPORTED_CLOCKS  (BIT(CLKR_CLKP1) | BIT(CLKR_CLKP2) | \
+                                BIT(CLKR_CLKEXT))
+
 /* Mailbox configuration:
  * mailbox 60 - 63 - Rx FIFO mailboxes
  * mailbox 56 - 59 - Tx FIFO mailboxes
@@ -789,7 +792,7 @@ static int rcar_can_probe(struct platform_device *pdev)
                goto fail_clk;
        }
 
-       if (clock_select >= ARRAY_SIZE(clock_names)) {
+       if (!(BIT(clock_select) & RCAR_SUPPORTED_CLOCKS)) {
                err = -EINVAL;
                dev_err(&pdev->dev, "invalid CAN clock selected\n");
                goto fail_clk;
index c7d05027a7a07ea34f862aa3595ebf6026a93897..2ce4fa8698c73b437051de20e29eaad70b263f64 100644 (file)
@@ -211,7 +211,54 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload)
 }
 EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_fifo);
 
-int can_rx_offload_irq_queue_err_skb(struct can_rx_offload *offload, struct sk_buff *skb)
+int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
+                               struct sk_buff *skb, u32 timestamp)
+{
+       struct can_rx_offload_cb *cb;
+       unsigned long flags;
+
+       if (skb_queue_len(&offload->skb_queue) >
+           offload->skb_queue_len_max)
+               return -ENOMEM;
+
+       cb = can_rx_offload_get_cb(skb);
+       cb->timestamp = timestamp;
+
+       spin_lock_irqsave(&offload->skb_queue.lock, flags);
+       __skb_queue_add_sort(&offload->skb_queue, skb, can_rx_offload_compare);
+       spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
+
+       can_rx_offload_schedule(offload);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_queue_sorted);
+
+unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
+                                        unsigned int idx, u32 timestamp)
+{
+       struct net_device *dev = offload->dev;
+       struct net_device_stats *stats = &dev->stats;
+       struct sk_buff *skb;
+       u8 len;
+       int err;
+
+       skb = __can_get_echo_skb(dev, idx, &len);
+       if (!skb)
+               return 0;
+
+       err = can_rx_offload_queue_sorted(offload, skb, timestamp);
+       if (err) {
+               stats->rx_errors++;
+               stats->tx_fifo_errors++;
+       }
+
+       return len;
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb);
+
+int can_rx_offload_queue_tail(struct can_rx_offload *offload,
+                             struct sk_buff *skb)
 {
        if (skb_queue_len(&offload->skb_queue) >
            offload->skb_queue_len_max)
@@ -222,7 +269,7 @@ int can_rx_offload_irq_queue_err_skb(struct can_rx_offload *offload, struct sk_b
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(can_rx_offload_irq_queue_err_skb);
+EXPORT_SYMBOL_GPL(can_rx_offload_queue_tail);
 
 static int can_rx_offload_init_queue(struct net_device *dev, struct can_rx_offload *offload, unsigned int weight)
 {
index 53e320c92a8be21e286ab4f7ada738fd223a08fa..ddaf46239e39e92337a4ed54ecb3feb1ab94cc59 100644 (file)
@@ -760,7 +760,7 @@ static int hi3110_open(struct net_device *net)
 {
        struct hi3110_priv *priv = netdev_priv(net);
        struct spi_device *spi = priv->spi;
-       unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_RISING;
+       unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_HIGH;
        int ret;
 
        ret = open_candev(net);
index b939a4c10b8409f5fe58e700204fe4e5183b23c0..c89c7d4900d75068badc7a7234c36b5b7345f675 100644 (file)
@@ -528,7 +528,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
                        context = &priv->tx_contexts[i];
 
                        context->echo_index = i;
-                       can_put_echo_skb(skb, netdev, context->echo_index);
                        ++priv->active_tx_contexts;
                        if (priv->active_tx_contexts >= (int)dev->max_tx_urbs)
                                netif_stop_queue(netdev);
@@ -553,7 +552,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
                dev_kfree_skb(skb);
                spin_lock_irqsave(&priv->tx_contexts_lock, flags);
 
-               can_free_echo_skb(netdev, context->echo_index);
                context->echo_index = dev->max_tx_urbs;
                --priv->active_tx_contexts;
                netif_wake_queue(netdev);
@@ -564,6 +562,8 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
 
        context->priv = priv;
 
+       can_put_echo_skb(skb, netdev, context->echo_index);
+
        usb_fill_bulk_urb(urb, dev->udev,
                          usb_sndbulkpipe(dev->udev,
                                          dev->bulk_out->bEndpointAddress),
index c084bae5ec0a4d936f6a7f121272d972903a8023..5fc0be564274375f3d5c579521a2d3b89ecd4a88 100644 (file)
@@ -1019,6 +1019,11 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv,
                                        new_state : CAN_STATE_ERROR_ACTIVE;
 
                        can_change_state(netdev, cf, tx_state, rx_state);
+
+                       if (priv->can.restart_ms &&
+                           old_state >= CAN_STATE_BUS_OFF &&
+                           new_state < CAN_STATE_BUS_OFF)
+                               cf->can_id |= CAN_ERR_RESTARTED;
                }
 
                if (new_state == CAN_STATE_BUS_OFF) {
@@ -1028,11 +1033,6 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv,
 
                        can_bus_off(netdev);
                }
-
-               if (priv->can.restart_ms &&
-                   old_state >= CAN_STATE_BUS_OFF &&
-                   new_state < CAN_STATE_BUS_OFF)
-                       cf->can_id |= CAN_ERR_RESTARTED;
        }
 
        if (!skb) {
index 0678a38b1af4588135f04074c56b37cfe6d09b70..f3d5bda012a107e430bca91bd09dd1d15be1bbf2 100644 (file)
 #include <linux/slab.h>
 #include <linux/usb.h>
 
-#include <linux/can.h>
-#include <linux/can/dev.h>
-#include <linux/can/error.h>
-
 #define UCAN_DRIVER_NAME "ucan"
 #define UCAN_MAX_RX_URBS 8
 /* the CAN controller needs a while to enable/disable the bus */
@@ -1575,11 +1571,8 @@ err_firmware_needs_update:
 /* disconnect the device */
 static void ucan_disconnect(struct usb_interface *intf)
 {
-       struct usb_device *udev;
        struct ucan_priv *up = usb_get_intfdata(intf);
 
-       udev = interface_to_usbdev(intf);
-
        usb_set_intfdata(intf, NULL);
 
        if (up) {
index 18956e7604a318d72de0ed52cf2a0da2e7602348..a70bb1bb90e7d89dc75f6f3dcc4f1455484057bc 100644 (file)
@@ -1848,6 +1848,8 @@ static void ena_down(struct ena_adapter *adapter)
                rc = ena_com_dev_reset(adapter->ena_dev, adapter->reset_reason);
                if (rc)
                        dev_err(&adapter->pdev->dev, "Device reset failed\n");
+               /* stop submitting admin commands on a device that was reset */
+               ena_com_set_admin_running_state(adapter->ena_dev, false);
        }
 
        ena_destroy_all_io_queues(adapter);
@@ -1914,6 +1916,9 @@ static int ena_close(struct net_device *netdev)
 
        netif_dbg(adapter, ifdown, netdev, "%s\n", __func__);
 
+       if (!test_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags))
+               return 0;
+
        if (test_bit(ENA_FLAG_DEV_UP, &adapter->flags))
                ena_down(adapter);
 
@@ -2613,9 +2618,7 @@ static void ena_destroy_device(struct ena_adapter *adapter, bool graceful)
                ena_down(adapter);
 
        /* Stop the device from sending AENQ events (in case reset flag is set
-        *  and device is up, ena_close already reset the device
-        * In case the reset flag is set and the device is up, ena_down()
-        * already perform the reset, so it can be skipped.
+        *  and device is up, ena_down() already reset the device.
         */
        if (!(test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags) && dev_up))
                ena_com_dev_reset(adapter->ena_dev, adapter->reset_reason);
@@ -2694,8 +2697,8 @@ err_device_destroy:
        ena_com_abort_admin_commands(ena_dev);
        ena_com_wait_for_abort_completion(ena_dev);
        ena_com_admin_destroy(ena_dev);
-       ena_com_mmio_reg_read_request_destroy(ena_dev);
        ena_com_dev_reset(ena_dev, ENA_REGS_RESET_DRIVER_INVALID_STATE);
+       ena_com_mmio_reg_read_request_destroy(ena_dev);
 err:
        clear_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags);
        clear_bit(ENA_FLAG_ONGOING_RESET, &adapter->flags);
@@ -3452,6 +3455,8 @@ err_rss:
        ena_com_rss_destroy(ena_dev);
 err_free_msix:
        ena_com_dev_reset(ena_dev, ENA_REGS_RESET_INIT_ERR);
+       /* stop submitting admin commands on a device that was reset */
+       ena_com_set_admin_running_state(ena_dev, false);
        ena_free_mgmnt_irq(adapter);
        ena_disable_msix(adapter);
 err_worker_destroy:
@@ -3498,18 +3503,12 @@ static void ena_remove(struct pci_dev *pdev)
 
        cancel_work_sync(&adapter->reset_task);
 
-       unregister_netdev(netdev);
-
-       /* If the device is running then we want to make sure the device will be
-        * reset to make sure no more events will be issued by the device.
-        */
-       if (test_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags))
-               set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
-
        rtnl_lock();
        ena_destroy_device(adapter, true);
        rtnl_unlock();
 
+       unregister_netdev(netdev);
+
        free_netdev(netdev);
 
        ena_com_rss_destroy(ena_dev);
index 521873642339356fd2053d160ea6ed2230fe4c33..dc8b6173d8d8224a5485480dec81c4f6526d94f0 100644 (file)
@@ -45,7 +45,7 @@
 
 #define DRV_MODULE_VER_MAJOR   2
 #define DRV_MODULE_VER_MINOR   0
-#define DRV_MODULE_VER_SUBMINOR 1
+#define DRV_MODULE_VER_SUBMINOR 2
 
 #define DRV_MODULE_NAME                "ena"
 #ifndef DRV_MODULE_VERSION
index b4fc0ed5bce83796ebe8a40eef3c053ecdb94254..9d489982682336a7cef13186f20557a4a7d7daeb 100644 (file)
@@ -1419,7 +1419,7 @@ static int sparc_lance_probe_one(struct platform_device *op,
 
                        prop = of_get_property(nd, "tpe-link-test?", NULL);
                        if (!prop)
-                               goto no_link_test;
+                               goto node_put;
 
                        if (strcmp(prop, "true")) {
                                printk(KERN_NOTICE "SunLance: warning: overriding option "
@@ -1428,6 +1428,8 @@ static int sparc_lance_probe_one(struct platform_device *op,
                                       "to ecd@skynet.be\n");
                                auxio_set_lte(AUXIO_LTE_ON);
                        }
+node_put:
+                       of_node_put(nd);
 no_link_test:
                        lp->auto_select = 1;
                        lp->tpe = 0;
index be1506169076f0a89f6a621d01dce81afe720ba7..0de487a8f0eb22d7b033c4f9751b68cf2454286e 100644 (file)
@@ -2191,6 +2191,13 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
 #define PMF_DMAE_C(bp)                 (BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
                                         E1HVN_MAX)
 
+/* Following is the DMAE channel number allocation for the clients.
+ *   MFW: OCBB/OCSD implementations use DMAE channels 14/15 respectively.
+ *   Driver: 0-3 and 8-11 (for PF dmae operations)
+ *           4 and 12 (for stats requests)
+ */
+#define BNX2X_FW_DMAE_C                 13 /* Channel for FW DMAE operations */
+
 /* PCIE link and speed */
 #define PCICFG_LINK_WIDTH              0x1f00000
 #define PCICFG_LINK_WIDTH_SHIFT                20
index 3f4d2c8da21a3a848b4149758883333522b6f77a..a9eaaf3e73a4c41f6dc6808f723a400750fd1ba1 100644 (file)
@@ -6149,6 +6149,7 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp,
        rdata->sd_vlan_tag      = cpu_to_le16(start_params->sd_vlan_tag);
        rdata->path_id          = BP_PATH(bp);
        rdata->network_cos_mode = start_params->network_cos_mode;
+       rdata->dmae_cmd_id      = BNX2X_FW_DMAE_C;
 
        rdata->vxlan_dst_port   = cpu_to_le16(start_params->vxlan_dst_port);
        rdata->geneve_dst_port  = cpu_to_le16(start_params->geneve_dst_port);
index dd85d790f638939e552042c642abceb108d61fb3..d4c30011752992ccf6d0f48d6f119e6950041e19 100644 (file)
@@ -1675,7 +1675,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
        } else {
                if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L4_CS_ERR_BITS) {
                        if (dev->features & NETIF_F_RXCSUM)
-                               cpr->rx_l4_csum_errors++;
+                               bnapi->cp_ring.rx_l4_csum_errors++;
                }
        }
 
@@ -8714,6 +8714,26 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features)
        return rc;
 }
 
+static int bnxt_dbg_hwrm_ring_info_get(struct bnxt *bp, u8 ring_type,
+                                      u32 ring_id, u32 *prod, u32 *cons)
+{
+       struct hwrm_dbg_ring_info_get_output *resp = bp->hwrm_cmd_resp_addr;
+       struct hwrm_dbg_ring_info_get_input req = {0};
+       int rc;
+
+       bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_DBG_RING_INFO_GET, -1, -1);
+       req.ring_type = ring_type;
+       req.fw_ring_id = cpu_to_le32(ring_id);
+       mutex_lock(&bp->hwrm_cmd_lock);
+       rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+       if (!rc) {
+               *prod = le32_to_cpu(resp->producer_index);
+               *cons = le32_to_cpu(resp->consumer_index);
+       }
+       mutex_unlock(&bp->hwrm_cmd_lock);
+       return rc;
+}
+
 static void bnxt_dump_tx_sw_state(struct bnxt_napi *bnapi)
 {
        struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
@@ -8821,6 +8841,11 @@ static void bnxt_timer(struct timer_list *t)
                        bnxt_queue_sp_work(bp);
                }
        }
+
+       if ((bp->flags & BNXT_FLAG_CHIP_P5) && netif_carrier_ok(dev)) {
+               set_bit(BNXT_RING_COAL_NOW_SP_EVENT, &bp->sp_event);
+               bnxt_queue_sp_work(bp);
+       }
 bnxt_restart_timer:
        mod_timer(&bp->timer, jiffies + bp->current_interval);
 }
@@ -8851,6 +8876,44 @@ static void bnxt_reset(struct bnxt *bp, bool silent)
        bnxt_rtnl_unlock_sp(bp);
 }
 
+static void bnxt_chk_missed_irq(struct bnxt *bp)
+{
+       int i;
+
+       if (!(bp->flags & BNXT_FLAG_CHIP_P5))
+               return;
+
+       for (i = 0; i < bp->cp_nr_rings; i++) {
+               struct bnxt_napi *bnapi = bp->bnapi[i];
+               struct bnxt_cp_ring_info *cpr;
+               u32 fw_ring_id;
+               int j;
+
+               if (!bnapi)
+                       continue;
+
+               cpr = &bnapi->cp_ring;
+               for (j = 0; j < 2; j++) {
+                       struct bnxt_cp_ring_info *cpr2 = cpr->cp_ring_arr[j];
+                       u32 val[2];
+
+                       if (!cpr2 || cpr2->has_more_work ||
+                           !bnxt_has_work(bp, cpr2))
+                               continue;
+
+                       if (cpr2->cp_raw_cons != cpr2->last_cp_raw_cons) {
+                               cpr2->last_cp_raw_cons = cpr2->cp_raw_cons;
+                               continue;
+                       }
+                       fw_ring_id = cpr2->cp_ring_struct.fw_ring_id;
+                       bnxt_dbg_hwrm_ring_info_get(bp,
+                               DBG_RING_INFO_GET_REQ_RING_TYPE_L2_CMPL,
+                               fw_ring_id, &val[0], &val[1]);
+                       cpr->missed_irqs++;
+               }
+       }
+}
+
 static void bnxt_cfg_ntp_filters(struct bnxt *);
 
 static void bnxt_sp_task(struct work_struct *work)
@@ -8930,6 +8993,9 @@ static void bnxt_sp_task(struct work_struct *work)
        if (test_and_clear_bit(BNXT_FLOW_STATS_SP_EVENT, &bp->sp_event))
                bnxt_tc_flow_stats_work(bp);
 
+       if (test_and_clear_bit(BNXT_RING_COAL_NOW_SP_EVENT, &bp->sp_event))
+               bnxt_chk_missed_irq(bp);
+
        /* These functions below will clear BNXT_STATE_IN_SP_TASK.  They
         * must be the last functions to be called before exiting.
         */
@@ -10087,6 +10153,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 
        bnxt_hwrm_func_qcfg(bp);
+       bnxt_hwrm_vnic_qcaps(bp);
        bnxt_hwrm_port_led_qcaps(bp);
        bnxt_ethtool_init(bp);
        bnxt_dcb_init(bp);
@@ -10120,7 +10187,6 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                                    VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6;
        }
 
-       bnxt_hwrm_vnic_qcaps(bp);
        if (bnxt_rfs_supported(bp)) {
                dev->hw_features |= NETIF_F_NTUPLE;
                if (bnxt_rfs_capable(bp)) {
index 498b373c992d372504278eb666d79f0ad83a9cd6..9e99d4ab3e062fe14fee7cd78b8626032fa5c705 100644 (file)
@@ -798,6 +798,8 @@ struct bnxt_cp_ring_info {
        u8                      had_work_done:1;
        u8                      has_more_work:1;
 
+       u32                     last_cp_raw_cons;
+
        struct bnxt_coal        rx_ring_coal;
        u64                     rx_packets;
        u64                     rx_bytes;
@@ -816,6 +818,7 @@ struct bnxt_cp_ring_info {
        dma_addr_t              hw_stats_map;
        u32                     hw_stats_ctx_id;
        u64                     rx_l4_csum_errors;
+       u64                     missed_irqs;
 
        struct bnxt_ring_struct cp_ring_struct;
 
@@ -1527,6 +1530,7 @@ struct bnxt {
 #define BNXT_LINK_SPEED_CHNG_SP_EVENT  14
 #define BNXT_FLOW_STATS_SP_EVENT       15
 #define BNXT_UPDATE_PHY_SP_EVENT       16
+#define BNXT_RING_COAL_NOW_SP_EVENT    17
 
        struct bnxt_hw_resc     hw_resc;
        struct bnxt_pf_info     pf;
index 48078564f0258cf2d862bd6d57c9d0da79d072a1..6cc69a58478a5ffaad8b7a0511d68e36a93657f3 100644 (file)
@@ -137,7 +137,7 @@ reset_coalesce:
        return rc;
 }
 
-#define BNXT_NUM_STATS 21
+#define BNXT_NUM_STATS 22
 
 #define BNXT_RX_STATS_ENTRY(counter)   \
        { BNXT_RX_STATS_OFFSET(counter), __stringify(counter) }
@@ -384,6 +384,7 @@ static void bnxt_get_ethtool_stats(struct net_device *dev,
                for (k = 0; k < stat_fields; j++, k++)
                        buf[j] = le64_to_cpu(hw_stats[k]);
                buf[j++] = cpr->rx_l4_csum_errors;
+               buf[j++] = cpr->missed_irqs;
 
                bnxt_sw_func_stats[RX_TOTAL_DISCARDS].counter +=
                        le64_to_cpu(cpr->hw_stats->rx_discard_pkts);
@@ -468,6 +469,8 @@ static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
                        buf += ETH_GSTRING_LEN;
                        sprintf(buf, "[%d]: rx_l4_csum_errors", i);
                        buf += ETH_GSTRING_LEN;
+                       sprintf(buf, "[%d]: missed_irqs", i);
+                       buf += ETH_GSTRING_LEN;
                }
                for (i = 0; i < BNXT_NUM_SW_FUNC_STATS; i++) {
                        strcpy(buf, bnxt_sw_func_stats[i].string);
@@ -2942,8 +2945,8 @@ bnxt_fill_coredump_record(struct bnxt *bp, struct bnxt_coredump_record *record,
        record->asic_state = 0;
        strlcpy(record->system_name, utsname()->nodename,
                sizeof(record->system_name));
-       record->year = cpu_to_le16(tm.tm_year);
-       record->month = cpu_to_le16(tm.tm_mon);
+       record->year = cpu_to_le16(tm.tm_year + 1900);
+       record->month = cpu_to_le16(tm.tm_mon + 1);
        record->day = cpu_to_le16(tm.tm_mday);
        record->hour = cpu_to_le16(tm.tm_hour);
        record->minute = cpu_to_le16(tm.tm_min);
index beee61292d5e522bae0842e5e76253eeb4e1d1f4..b59b382d34f94277a9a33e52223fda8ab7f19af3 100644 (file)
@@ -43,6 +43,9 @@ static int bnxt_register_dev(struct bnxt_en_dev *edev, int ulp_id,
        if (ulp_id == BNXT_ROCE_ULP) {
                unsigned int max_stat_ctxs;
 
+               if (bp->flags & BNXT_FLAG_CHIP_P5)
+                       return -EOPNOTSUPP;
+
                max_stat_ctxs = bnxt_get_max_func_stat_ctxs(bp);
                if (max_stat_ctxs <= BNXT_MIN_ROCE_STAT_CTXS ||
                    bp->num_stat_ctxs == max_stat_ctxs)
index 89295306f1615713f6b59202e83e0ae0d1fb2338..432c3b8670848e868e53d4b02096d5c8cf19b87d 100644 (file)
@@ -12422,6 +12422,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
 {
        struct tg3 *tp = netdev_priv(dev);
        int i, irq_sync = 0, err = 0;
+       bool reset_phy = false;
 
        if ((ering->rx_pending > tp->rx_std_ring_mask) ||
            (ering->rx_jumbo_pending > tp->rx_jmb_ring_mask) ||
@@ -12453,7 +12454,13 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
 
        if (netif_running(dev)) {
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-               err = tg3_restart_hw(tp, false);
+               /* Reset PHY to avoid PHY lock up */
+               if (tg3_asic_rev(tp) == ASIC_REV_5717 ||
+                   tg3_asic_rev(tp) == ASIC_REV_5719 ||
+                   tg3_asic_rev(tp) == ASIC_REV_5720)
+                       reset_phy = true;
+
+               err = tg3_restart_hw(tp, reset_phy);
                if (!err)
                        tg3_netif_start(tp);
        }
@@ -12487,6 +12494,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
 {
        struct tg3 *tp = netdev_priv(dev);
        int err = 0;
+       bool reset_phy = false;
 
        if (tp->link_config.autoneg == AUTONEG_ENABLE)
                tg3_warn_mgmt_link_flap(tp);
@@ -12556,7 +12564,13 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
 
                if (netif_running(dev)) {
                        tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-                       err = tg3_restart_hw(tp, false);
+                       /* Reset PHY to avoid PHY lock up */
+                       if (tg3_asic_rev(tp) == ASIC_REV_5717 ||
+                           tg3_asic_rev(tp) == ASIC_REV_5719 ||
+                           tg3_asic_rev(tp) == ASIC_REV_5720)
+                               reset_phy = true;
+
+                       err = tg3_restart_hw(tp, reset_phy);
                        if (!err)
                                tg3_netif_start(tp);
                }
index 55af04fa03a77e850196e82e930e3f85af7c6aa7..6c8dcb65ff031d230303604c2071797027bf11a4 100644 (file)
@@ -1441,6 +1441,9 @@ static void nic_remove(struct pci_dev *pdev)
 {
        struct nicpf *nic = pci_get_drvdata(pdev);
 
+       if (!nic)
+               return;
+
        if (nic->flags & NIC_SRIOV_ENABLED)
                pci_disable_sriov(pdev);
 
index 768f584f8392732b19d6e889ed456a3c6de8e809..88f8a8fa93cdcef2162f1867b46ed9525ef4fbf1 100644 (file)
@@ -1784,6 +1784,7 @@ static int nicvf_xdp_setup(struct nicvf *nic, struct bpf_prog *prog)
        bool if_up = netif_running(nic->netdev);
        struct bpf_prog *old_prog;
        bool bpf_attached = false;
+       int ret = 0;
 
        /* For now just support only the usual MTU sized frames */
        if (prog && (dev->mtu > 1500)) {
@@ -1817,8 +1818,12 @@ static int nicvf_xdp_setup(struct nicvf *nic, struct bpf_prog *prog)
        if (nic->xdp_prog) {
                /* Attach BPF program */
                nic->xdp_prog = bpf_prog_add(nic->xdp_prog, nic->rx_queues - 1);
-               if (!IS_ERR(nic->xdp_prog))
+               if (!IS_ERR(nic->xdp_prog)) {
                        bpf_attached = true;
+               } else {
+                       ret = PTR_ERR(nic->xdp_prog);
+                       nic->xdp_prog = NULL;
+               }
        }
 
        /* Calculate Tx queues needed for XDP and network stack */
@@ -1830,7 +1835,7 @@ static int nicvf_xdp_setup(struct nicvf *nic, struct bpf_prog *prog)
                netif_trans_update(nic->netdev);
        }
 
-       return 0;
+       return ret;
 }
 
 static int nicvf_xdp(struct net_device *netdev, struct netdev_bpf *xdp)
index 187a249ff2d1d2fd4201a4e74b9459cbeb3a4b52..fcaf18fa39048b5b83646a7db8e95fd484e27a1f 100644 (file)
@@ -585,10 +585,12 @@ static void nicvf_free_snd_queue(struct nicvf *nic, struct snd_queue *sq)
        if (!sq->dmem.base)
                return;
 
-       if (sq->tso_hdrs)
+       if (sq->tso_hdrs) {
                dma_free_coherent(&nic->pdev->dev,
                                  sq->dmem.q_len * TSO_HEADER_SIZE,
                                  sq->tso_hdrs, sq->tso_hdrs_phys);
+               sq->tso_hdrs = NULL;
+       }
 
        /* Free pending skbs in the queue */
        smp_rmb();
index 75c1c5ed23878441664d2c7db867b67ee8ba21aa..e2cdfa75673fd58cf6dbacd1e67d7a05dd4b33c8 100644 (file)
@@ -67,7 +67,6 @@ config CHELSIO_T3
 config CHELSIO_T4
        tristate "Chelsio Communications T4/T5/T6 Ethernet support"
        depends on PCI && (IPV6 || IPV6=n)
-       depends on THERMAL || !THERMAL
        select FW_LOADER
        select MDIO
        select ZLIB_DEFLATE
index 78e5d17a1d5fb2306f104ce1bf1c4d02c42003ed..91d8a885deba9b8ea82125c3f0f9009fae9a3f91 100644 (file)
@@ -12,6 +12,4 @@ cxgb4-objs := cxgb4_main.o l2t.o smt.o t4_hw.o sge.o clip_tbl.o cxgb4_ethtool.o
 cxgb4-$(CONFIG_CHELSIO_T4_DCB) +=  cxgb4_dcb.o
 cxgb4-$(CONFIG_CHELSIO_T4_FCOE) +=  cxgb4_fcoe.o
 cxgb4-$(CONFIG_DEBUG_FS) += cxgb4_debugfs.o
-ifdef CONFIG_THERMAL
-cxgb4-objs += cxgb4_thermal.o
-endif
+cxgb4-$(CONFIG_THERMAL) += cxgb4_thermal.o
index 05a46926016a5e2d53bc57b0c9c5ca19f5484f29..d49db46254cd7d528f6f181e8237277069c8a916 100644 (file)
@@ -5863,7 +5863,7 @@ fw_attach_fail:
        if (!is_t4(adapter->params.chip))
                cxgb4_ptp_init(adapter);
 
-       if (IS_ENABLED(CONFIG_THERMAL) &&
+       if (IS_REACHABLE(CONFIG_THERMAL) &&
            !is_t4(adapter->params.chip) && (adapter->flags & FW_OK))
                cxgb4_thermal_init(adapter);
 
@@ -5932,7 +5932,7 @@ static void remove_one(struct pci_dev *pdev)
 
                if (!is_t4(adapter->params.chip))
                        cxgb4_ptp_stop(adapter);
-               if (IS_ENABLED(CONFIG_THERMAL))
+               if (IS_REACHABLE(CONFIG_THERMAL))
                        cxgb4_thermal_remove(adapter);
 
                /* If we allocated filters, free up state associated with any
index ceec467f590d2a382447d087a9e16f7b0fb576de..949103db8a8ad75afab234f879acddc7e8c4a515 100644 (file)
@@ -660,7 +660,7 @@ static void gmac_clean_txq(struct net_device *netdev, struct gmac_txq *txq,
 
                        u64_stats_update_begin(&port->tx_stats_syncp);
                        port->tx_frag_stats[nfrags]++;
-                       u64_stats_update_end(&port->ir_stats_syncp);
+                       u64_stats_update_end(&port->tx_stats_syncp);
                }
        }
 
index 570caeb8ee9edafb723c1f4ffc191274ad903d93..084f24daf2b5a8854dcbb9002314f658f0ceaf26 100644 (file)
@@ -872,11 +872,10 @@ static irqreturn_t ftmac100_interrupt(int irq, void *dev_id)
        struct net_device *netdev = dev_id;
        struct ftmac100 *priv = netdev_priv(netdev);
 
-       if (likely(netif_running(netdev))) {
-               /* Disable interrupts for polling */
-               ftmac100_disable_all_int(priv);
+       /* Disable interrupts for polling */
+       ftmac100_disable_all_int(priv);
+       if (likely(netif_running(netdev)))
                napi_schedule(&priv->napi);
-       }
 
        return IRQ_HANDLED;
 }
index be268dcde8fa2a5db3fd392237d583a4c5cc0d5e..f9a4e76c5a8b73799c61cb7d3a260cc50f9287ee 100644 (file)
@@ -915,10 +915,8 @@ static int hip04_mac_probe(struct platform_device *pdev)
        }
 
        ret = register_netdev(ndev);
-       if (ret) {
-               free_netdev(ndev);
+       if (ret)
                goto alloc_fail;
-       }
 
        return 0;
 
index c9d5d0a7fbf172b14d70b33e62cb3344622b2ce7..c0203a0d5e3b8be87f33a7eb7a1f11b1ecd8ca18 100644 (file)
@@ -485,8 +485,8 @@ static void release_rx_pools(struct ibmvnic_adapter *adapter)
 
                for (j = 0; j < rx_pool->size; j++) {
                        if (rx_pool->rx_buff[j].skb) {
-                               dev_kfree_skb_any(rx_pool->rx_buff[i].skb);
-                               rx_pool->rx_buff[i].skb = NULL;
+                               dev_kfree_skb_any(rx_pool->rx_buff[j].skb);
+                               rx_pool->rx_buff[j].skb = NULL;
                        }
                }
 
@@ -1103,20 +1103,15 @@ static int ibmvnic_open(struct net_device *netdev)
                return 0;
        }
 
-       mutex_lock(&adapter->reset_lock);
-
        if (adapter->state != VNIC_CLOSED) {
                rc = ibmvnic_login(netdev);
-               if (rc) {
-                       mutex_unlock(&adapter->reset_lock);
+               if (rc)
                        return rc;
-               }
 
                rc = init_resources(adapter);
                if (rc) {
                        netdev_err(netdev, "failed to initialize resources\n");
                        release_resources(adapter);
-                       mutex_unlock(&adapter->reset_lock);
                        return rc;
                }
        }
@@ -1124,8 +1119,6 @@ static int ibmvnic_open(struct net_device *netdev)
        rc = __ibmvnic_open(netdev);
        netif_carrier_on(netdev);
 
-       mutex_unlock(&adapter->reset_lock);
-
        return rc;
 }
 
@@ -1269,10 +1262,8 @@ static int ibmvnic_close(struct net_device *netdev)
                return 0;
        }
 
-       mutex_lock(&adapter->reset_lock);
        rc = __ibmvnic_close(netdev);
        ibmvnic_cleanup(netdev);
-       mutex_unlock(&adapter->reset_lock);
 
        return rc;
 }
@@ -1746,6 +1737,7 @@ static int do_reset(struct ibmvnic_adapter *adapter,
                    struct ibmvnic_rwi *rwi, u32 reset_state)
 {
        u64 old_num_rx_queues, old_num_tx_queues;
+       u64 old_num_rx_slots, old_num_tx_slots;
        struct net_device *netdev = adapter->netdev;
        int i, rc;
 
@@ -1757,6 +1749,8 @@ static int do_reset(struct ibmvnic_adapter *adapter,
 
        old_num_rx_queues = adapter->req_rx_queues;
        old_num_tx_queues = adapter->req_tx_queues;
+       old_num_rx_slots = adapter->req_rx_add_entries_per_subcrq;
+       old_num_tx_slots = adapter->req_tx_entries_per_subcrq;
 
        ibmvnic_cleanup(netdev);
 
@@ -1819,21 +1813,20 @@ static int do_reset(struct ibmvnic_adapter *adapter,
                        if (rc)
                                return rc;
                } else if (adapter->req_rx_queues != old_num_rx_queues ||
-                          adapter->req_tx_queues != old_num_tx_queues) {
-                       adapter->map_id = 1;
+                          adapter->req_tx_queues != old_num_tx_queues ||
+                          adapter->req_rx_add_entries_per_subcrq !=
+                                                       old_num_rx_slots ||
+                          adapter->req_tx_entries_per_subcrq !=
+                                                       old_num_tx_slots) {
                        release_rx_pools(adapter);
                        release_tx_pools(adapter);
-                       rc = init_rx_pools(netdev);
-                       if (rc)
-                               return rc;
-                       rc = init_tx_pools(netdev);
-                       if (rc)
-                               return rc;
-
                        release_napi(adapter);
-                       rc = init_napi(adapter);
+                       release_vpd_data(adapter);
+
+                       rc = init_resources(adapter);
                        if (rc)
                                return rc;
+
                } else {
                        rc = reset_tx_pools(adapter);
                        if (rc)
@@ -1917,17 +1910,8 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter,
                adapter->state = VNIC_PROBED;
                return 0;
        }
-       /* netif_set_real_num_xx_queues needs to take rtnl lock here
-        * unless wait_for_reset is set, in which case the rtnl lock
-        * has already been taken before initializing the reset
-        */
-       if (!adapter->wait_for_reset) {
-               rtnl_lock();
-               rc = init_resources(adapter);
-               rtnl_unlock();
-       } else {
-               rc = init_resources(adapter);
-       }
+
+       rc = init_resources(adapter);
        if (rc)
                return rc;
 
@@ -1986,13 +1970,21 @@ static void __ibmvnic_reset(struct work_struct *work)
        struct ibmvnic_rwi *rwi;
        struct ibmvnic_adapter *adapter;
        struct net_device *netdev;
+       bool we_lock_rtnl = false;
        u32 reset_state;
        int rc = 0;
 
        adapter = container_of(work, struct ibmvnic_adapter, ibmvnic_reset);
        netdev = adapter->netdev;
 
-       mutex_lock(&adapter->reset_lock);
+       /* netif_set_real_num_xx_queues needs to take rtnl lock here
+        * unless wait_for_reset is set, in which case the rtnl lock
+        * has already been taken before initializing the reset
+        */
+       if (!adapter->wait_for_reset) {
+               rtnl_lock();
+               we_lock_rtnl = true;
+       }
        reset_state = adapter->state;
 
        rwi = get_next_rwi(adapter);
@@ -2020,12 +2012,11 @@ static void __ibmvnic_reset(struct work_struct *work)
        if (rc) {
                netdev_dbg(adapter->netdev, "Reset failed\n");
                free_all_rwi(adapter);
-               mutex_unlock(&adapter->reset_lock);
-               return;
        }
 
        adapter->resetting = false;
-       mutex_unlock(&adapter->reset_lock);
+       if (we_lock_rtnl)
+               rtnl_unlock();
 }
 
 static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
@@ -4768,7 +4759,6 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
 
        INIT_WORK(&adapter->ibmvnic_reset, __ibmvnic_reset);
        INIT_LIST_HEAD(&adapter->rwi_list);
-       mutex_init(&adapter->reset_lock);
        mutex_init(&adapter->rwi_lock);
        adapter->resetting = false;
 
@@ -4840,8 +4830,8 @@ static int ibmvnic_remove(struct vio_dev *dev)
        struct ibmvnic_adapter *adapter = netdev_priv(netdev);
 
        adapter->state = VNIC_REMOVING;
-       unregister_netdev(netdev);
-       mutex_lock(&adapter->reset_lock);
+       rtnl_lock();
+       unregister_netdevice(netdev);
 
        release_resources(adapter);
        release_sub_crqs(adapter, 1);
@@ -4852,7 +4842,7 @@ static int ibmvnic_remove(struct vio_dev *dev)
 
        adapter->state = VNIC_REMOVED;
 
-       mutex_unlock(&adapter->reset_lock);
+       rtnl_unlock();
        device_remove_file(&dev->dev, &dev_attr_failover);
        free_netdev(netdev);
        dev_set_drvdata(&dev->dev, NULL);
index 18103b811d4db398df7ce6a6e27c6bda2077c4c2..99c4f8d331ce7c489c4b3badb1d5fbbe57ff8dea 100644 (file)
@@ -1075,7 +1075,7 @@ struct ibmvnic_adapter {
        struct tasklet_struct tasklet;
        enum vnic_state state;
        enum ibmvnic_reset_reason reset_reason;
-       struct mutex reset_lock, rwi_lock;
+       struct mutex rwi_lock;
        struct list_head rwi_list;
        struct work_struct ibmvnic_reset;
        bool resetting;
index 8c5ba4b81fb7332aba15a0f4199155f39a4da8a3..2d4d10a017e59bfc96870e9fd94338986f6ef7f2 100644 (file)
@@ -512,7 +512,8 @@ static int xrx200_probe(struct platform_device *pdev)
        err = register_netdev(net_dev);
        if (err)
                goto err_unprepare_clk;
-       return err;
+
+       return 0;
 
 err_unprepare_clk:
        clk_disable_unprepare(priv->clk);
@@ -520,7 +521,7 @@ err_unprepare_clk:
 err_uninit_dma:
        xrx200_hw_cleanup(priv);
 
-       return 0;
+       return err;
 }
 
 static int xrx200_remove(struct platform_device *pdev)
index 3ba672e9e353d2cf6cd38ad64172e4219b9f5602..e5397c8197b9c3713c48e925dad0dfcee732c0b9 100644 (file)
@@ -3343,7 +3343,6 @@ static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
        if (state->interface != PHY_INTERFACE_MODE_NA &&
            state->interface != PHY_INTERFACE_MODE_QSGMII &&
            state->interface != PHY_INTERFACE_MODE_SGMII &&
-           state->interface != PHY_INTERFACE_MODE_2500BASEX &&
            !phy_interface_mode_is_8023z(state->interface) &&
            !phy_interface_mode_is_rgmii(state->interface)) {
                bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
@@ -3357,14 +3356,9 @@ static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
        /* Asymmetric pause is unsupported */
        phylink_set(mask, Pause);
 
-       /* We cannot use 1Gbps when using the 2.5G interface. */
-       if (state->interface == PHY_INTERFACE_MODE_2500BASEX) {
-               phylink_set(mask, 2500baseT_Full);
-               phylink_set(mask, 2500baseX_Full);
-       } else {
-               phylink_set(mask, 1000baseT_Full);
-               phylink_set(mask, 1000baseX_Full);
-       }
+       /* Half-duplex at speeds higher than 100Mbit is unsupported */
+       phylink_set(mask, 1000baseT_Full);
+       phylink_set(mask, 1000baseX_Full);
 
        if (!phy_interface_mode_is_8023z(state->interface)) {
                /* 10M and 100M are only supported in non-802.3z mode */
index deef5a998985a9f8398d693b8bd219a5fc083313..9af34e03892c19e780149a3a8405d936fe417d45 100644 (file)
@@ -337,7 +337,7 @@ void mlx4_zone_allocator_destroy(struct mlx4_zone_allocator *zone_alloc)
 static u32 __mlx4_alloc_from_zone(struct mlx4_zone_entry *zone, int count,
                                  int align, u32 skip_mask, u32 *puid)
 {
-       u32 uid;
+       u32 uid = 0;
        u32 res;
        struct mlx4_zone_allocator *zone_alloc = zone->allocator;
        struct mlx4_zone_entry *curr_node;
index ebcd2778eeb3e1f22524064ff2db7762e1f852ba..23f1b5b512c2198cb664167e42fb91ff9c549f13 100644 (file)
@@ -540,8 +540,8 @@ struct slave_list {
 struct resource_allocator {
        spinlock_t alloc_lock; /* protect quotas */
        union {
-               int res_reserved;
-               int res_port_rsvd[MLX4_MAX_PORTS];
+               unsigned int res_reserved;
+               unsigned int res_port_rsvd[MLX4_MAX_PORTS];
        };
        union {
                int res_free;
index 2e84f10f59ba9ca0a69d980b87368f7310e5bb13..1a11bc0e16123e918e68e7a8f8bed703825665fa 100644 (file)
@@ -363,6 +363,7 @@ int mlx4_mr_hw_write_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr,
                        container_of((void *)mpt_entry, struct mlx4_cmd_mailbox,
                                     buf);
 
+               (*mpt_entry)->lkey = 0;
                err = mlx4_SW2HW_MPT(dev, mailbox, key);
        }
 
index d7fbd5b6ac957d0b3b9ed9fa0000eed1ae0e73bc..11832480292646c9fcbd881402ed95497218c67e 100644 (file)
@@ -569,6 +569,7 @@ struct mlx5e_rq {
 
        unsigned long          state;
        int                    ix;
+       unsigned int           hw_mtu;
 
        struct net_dim         dim; /* Dynamic Interrupt Moderation */
 
index 023dc4bccd289e5fea787a5fe81f8c0e3617e03b..4a37713023be58311a52f62672e22b321aa80cdf 100644 (file)
@@ -88,10 +88,8 @@ int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
 
        eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
        *speed = mlx5e_port_ptys2speed(eth_proto_oper);
-       if (!(*speed)) {
-               mlx5_core_warn(mdev, "cannot get port speed\n");
+       if (!(*speed))
                err = -EINVAL;
-       }
 
        return err;
 }
@@ -258,7 +256,7 @@ static int mlx5e_fec_admin_field(u32 *pplm,
        case 40000:
                if (!write)
                        *fec_policy = MLX5_GET(pplm_reg, pplm,
-                                              fec_override_cap_10g_40g);
+                                              fec_override_admin_10g_40g);
                else
                        MLX5_SET(pplm_reg, pplm,
                                 fec_override_admin_10g_40g, *fec_policy);
@@ -310,7 +308,7 @@ static int mlx5e_get_fec_cap_field(u32 *pplm,
        case 10000:
        case 40000:
                *fec_cap = MLX5_GET(pplm_reg, pplm,
-                                   fec_override_admin_10g_40g);
+                                   fec_override_cap_10g_40g);
                break;
        case 25000:
                *fec_cap = MLX5_GET(pplm_reg, pplm,
@@ -394,12 +392,12 @@ int mlx5e_get_fec_mode(struct mlx5_core_dev *dev, u32 *fec_mode_active,
 
 int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u8 fec_policy)
 {
+       u8 fec_policy_nofec = BIT(MLX5E_FEC_NOFEC);
        bool fec_mode_not_supp_in_speed = false;
-       u8 no_fec_policy = BIT(MLX5E_FEC_NOFEC);
        u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};
        u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};
        int sz = MLX5_ST_SZ_BYTES(pplm_reg);
-       u32 current_fec_speed;
+       u8 fec_policy_auto = 0;
        u8 fec_caps = 0;
        int err;
        int i;
@@ -415,23 +413,19 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u8 fec_policy)
        if (err)
                return err;
 
-       err = mlx5e_port_linkspeed(dev, &current_fec_speed);
-       if (err)
-               return err;
+       MLX5_SET(pplm_reg, out, local_port, 1);
 
-       memset(in, 0, sz);
-       MLX5_SET(pplm_reg, in, local_port, 1);
-       for (i = 0; i < MLX5E_FEC_SUPPORTED_SPEEDS && !!fec_policy; i++) {
+       for (i = 0; i < MLX5E_FEC_SUPPORTED_SPEEDS; i++) {
                mlx5e_get_fec_cap_field(out, &fec_caps, fec_supported_speeds[i]);
-               /* policy supported for link speed */
-               if (!!(fec_caps & fec_policy)) {
-                       mlx5e_fec_admin_field(in, &fec_policy, 1,
+               /* policy supported for link speed, or policy is auto */
+               if (fec_caps & fec_policy || fec_policy == fec_policy_auto) {
+                       mlx5e_fec_admin_field(out, &fec_policy, 1,
                                              fec_supported_speeds[i]);
                } else {
-                       if (fec_supported_speeds[i] == current_fec_speed)
-                               return -EOPNOTSUPP;
-                       mlx5e_fec_admin_field(in, &no_fec_policy, 1,
-                                             fec_supported_speeds[i]);
+                       /* turn off FEC if supported. Else, leave it the same */
+                       if (fec_caps & fec_policy_nofec)
+                               mlx5e_fec_admin_field(out, &fec_policy_nofec, 1,
+                                                     fec_supported_speeds[i]);
                        fec_mode_not_supp_in_speed = true;
                }
        }
@@ -441,5 +435,5 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u8 fec_policy)
                              "FEC policy 0x%x is not supported for some speeds",
                              fec_policy);
 
-       return mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 1);
+       return mlx5_core_access_reg(dev, out, sz, out, sz, MLX5_REG_PPLM, 0, 1);
 }
index c047da8752daa80bf856373037ead5ba26adbefc..eac245a93f918c588dc8237e1af5996f3d0f73f0 100644 (file)
@@ -130,8 +130,10 @@ static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu)
        int err;
 
        err = mlx5e_port_linkspeed(priv->mdev, &speed);
-       if (err)
+       if (err) {
+               mlx5_core_warn(priv->mdev, "cannot get port speed\n");
                return 0;
+       }
 
        xoff = (301 + 216 * priv->dcbx.cable_len / 100) * speed / 1000 + 272 * mtu / 100;
 
index 3e770abfd80212d70e3b7952fa05ba57ae1490e1..25c1c4f96841244336c3257abbd213707655ad51 100644 (file)
@@ -843,8 +843,7 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
        ethtool_link_ksettings_add_link_mode(link_ksettings, supported,
                                             Autoneg);
 
-       err = get_fec_supported_advertised(mdev, link_ksettings);
-       if (err)
+       if (get_fec_supported_advertised(mdev, link_ksettings))
                netdev_dbg(netdev, "%s: FEC caps query failed: %d\n",
                           __func__, err);
 
index 1243edbedc9e96c90196f7b7f311129f2eb0cb04..871313d6b34d1b315e6ef1a9c07cba396de14186 100644 (file)
@@ -502,6 +502,7 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
        rq->channel = c;
        rq->ix      = c->ix;
        rq->mdev    = mdev;
+       rq->hw_mtu  = MLX5E_SW2HW_MTU(params, params->sw_mtu);
        rq->stats   = &c->priv->channel_stats[c->ix].rq;
 
        rq->xdp_prog = params->xdp_prog ? bpf_prog_inc(params->xdp_prog) : NULL;
@@ -1623,13 +1624,15 @@ static int mlx5e_alloc_cq_common(struct mlx5_core_dev *mdev,
        int err;
        u32 i;
 
+       err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn_not_used, &irqn);
+       if (err)
+               return err;
+
        err = mlx5_cqwq_create(mdev, &param->wq, param->cqc, &cq->wq,
                               &cq->wq_ctrl);
        if (err)
                return err;
 
-       mlx5_vector2eqn(mdev, param->eq_ix, &eqn_not_used, &irqn);
-
        mcq->cqe_sz     = 64;
        mcq->set_ci_db  = cq->wq_ctrl.db.db;
        mcq->arm_db     = cq->wq_ctrl.db.db + 1;
@@ -1687,6 +1690,10 @@ static int mlx5e_create_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
        int eqn;
        int err;
 
+       err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn, &irqn_not_used);
+       if (err)
+               return err;
+
        inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
                sizeof(u64) * cq->wq_ctrl.buf.npages;
        in = kvzalloc(inlen, GFP_KERNEL);
@@ -1700,8 +1707,6 @@ static int mlx5e_create_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
        mlx5_fill_page_frag_array(&cq->wq_ctrl.buf,
                                  (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas));
 
-       mlx5_vector2eqn(mdev, param->eq_ix, &eqn, &irqn_not_used);
-
        MLX5_SET(cqc,   cqc, cq_period_mode, param->cq_period_mode);
        MLX5_SET(cqc,   cqc, c_eqn,         eqn);
        MLX5_SET(cqc,   cqc, uar_page,      mdev->priv.uar->index);
@@ -1921,6 +1926,10 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
        int err;
        int eqn;
 
+       err = mlx5_vector2eqn(priv->mdev, ix, &eqn, &irq);
+       if (err)
+               return err;
+
        c = kvzalloc_node(sizeof(*c), GFP_KERNEL, cpu_to_node(cpu));
        if (!c)
                return -ENOMEM;
@@ -1937,7 +1946,6 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
        c->xdp      = !!params->xdp_prog;
        c->stats    = &priv->channel_stats[ix].ch;
 
-       mlx5_vector2eqn(priv->mdev, ix, &eqn, &irq);
        c->irq_desc = irq_to_desc(irq);
 
        netif_napi_add(netdev, &c->napi, mlx5e_napi_poll, 64);
@@ -3574,6 +3582,7 @@ static int set_feature_cvlan_filter(struct net_device *netdev, bool enable)
        return 0;
 }
 
+#ifdef CONFIG_MLX5_ESWITCH
 static int set_feature_tc_num_filters(struct net_device *netdev, bool enable)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -3586,6 +3595,7 @@ static int set_feature_tc_num_filters(struct net_device *netdev, bool enable)
 
        return 0;
 }
+#endif
 
 static int set_feature_rx_all(struct net_device *netdev, bool enable)
 {
@@ -3684,7 +3694,9 @@ static int mlx5e_set_features(struct net_device *netdev,
        err |= MLX5E_HANDLE_FEATURE(NETIF_F_LRO, set_feature_lro);
        err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_FILTER,
                                    set_feature_cvlan_filter);
+#ifdef CONFIG_MLX5_ESWITCH
        err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_TC, set_feature_tc_num_filters);
+#endif
        err |= MLX5E_HANDLE_FEATURE(NETIF_F_RXALL, set_feature_rx_all);
        err |= MLX5E_HANDLE_FEATURE(NETIF_F_RXFCS, set_feature_rx_fcs);
        err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_RX, set_feature_rx_vlan);
@@ -3755,10 +3767,11 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu,
        }
 
        if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
+               bool is_linear = mlx5e_rx_mpwqe_is_linear_skb(priv->mdev, &new_channels.params);
                u8 ppw_old = mlx5e_mpwqe_log_pkts_per_wqe(params);
                u8 ppw_new = mlx5e_mpwqe_log_pkts_per_wqe(&new_channels.params);
 
-               reset = reset && (ppw_old != ppw_new);
+               reset = reset && (is_linear || (ppw_old != ppw_new));
        }
 
        if (!reset) {
@@ -4678,7 +4691,9 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
            FT_CAP(modify_root) &&
            FT_CAP(identified_miss_table_mode) &&
            FT_CAP(flow_table_modify)) {
+#ifdef CONFIG_MLX5_ESWITCH
                netdev->hw_features      |= NETIF_F_HW_TC;
+#endif
 #ifdef CONFIG_MLX5_EN_ARFS
                netdev->hw_features      |= NETIF_F_NTUPLE;
 #endif
@@ -5004,11 +5019,21 @@ err_free_netdev:
 int mlx5e_attach_netdev(struct mlx5e_priv *priv)
 {
        const struct mlx5e_profile *profile;
+       int max_nch;
        int err;
 
        profile = priv->profile;
        clear_bit(MLX5E_STATE_DESTROYING, &priv->state);
 
+       /* max number of channels may have changed */
+       max_nch = mlx5e_get_max_num_channels(priv->mdev);
+       if (priv->channels.params.num_channels > max_nch) {
+               mlx5_core_warn(priv->mdev, "MLX5E: Reducing number of channels to %d\n", max_nch);
+               priv->channels.params.num_channels = max_nch;
+               mlx5e_build_default_indir_rqt(priv->channels.params.indirection_rqt,
+                                             MLX5E_INDIR_RQT_SIZE, max_nch);
+       }
+
        err = profile->init_tx(priv);
        if (err)
                goto out;
index 79638dcbae78395fb723c9bf3fa877e7a42d91cd..16985ca3248d72c4001f5997f0ead50ac10e6d0a 100644 (file)
@@ -1104,6 +1104,12 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
        u32 frag_size;
        bool consumed;
 
+       /* Check packet size. Note LRO doesn't use linear SKB */
+       if (unlikely(cqe_bcnt > rq->hw_mtu)) {
+               rq->stats->oversize_pkts_sw_drop++;
+               return NULL;
+       }
+
        va             = page_address(di->page) + head_offset;
        data           = va + rx_headroom;
        frag_size      = MLX5_SKB_FRAG_SZ(rx_headroom + cqe_bcnt32);
index 35ded91203f52984dfa451c3fcebaad1d4c07664..4382ef85488c5b6e936424dc902fd590d8030294 100644 (file)
@@ -98,18 +98,17 @@ static int mlx5e_test_link_speed(struct mlx5e_priv *priv)
        return 1;
 }
 
-#ifdef CONFIG_INET
-/* loopback test */
-#define MLX5E_TEST_PKT_SIZE (MLX5E_RX_MAX_HEAD - NET_IP_ALIGN)
-static const char mlx5e_test_text[ETH_GSTRING_LEN] = "MLX5E SELF TEST";
-#define MLX5E_TEST_MAGIC 0x5AEED15C001ULL
-
 struct mlx5ehdr {
        __be32 version;
        __be64 magic;
-       char   text[ETH_GSTRING_LEN];
 };
 
+#ifdef CONFIG_INET
+/* loopback test */
+#define MLX5E_TEST_PKT_SIZE (sizeof(struct ethhdr) + sizeof(struct iphdr) +\
+                            sizeof(struct udphdr) + sizeof(struct mlx5ehdr))
+#define MLX5E_TEST_MAGIC 0x5AEED15C001ULL
+
 static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)
 {
        struct sk_buff *skb = NULL;
@@ -117,10 +116,7 @@ static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)
        struct ethhdr *ethh;
        struct udphdr *udph;
        struct iphdr *iph;
-       int datalen, iplen;
-
-       datalen = MLX5E_TEST_PKT_SIZE -
-                 (sizeof(*ethh) + sizeof(*iph) + sizeof(*udph));
+       int    iplen;
 
        skb = netdev_alloc_skb(priv->netdev, MLX5E_TEST_PKT_SIZE);
        if (!skb) {
@@ -149,7 +145,7 @@ static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)
        /* Fill UDP header */
        udph->source = htons(9);
        udph->dest = htons(9); /* Discard Protocol */
-       udph->len = htons(datalen + sizeof(struct udphdr));
+       udph->len = htons(sizeof(struct mlx5ehdr) + sizeof(struct udphdr));
        udph->check = 0;
 
        /* Fill IP header */
@@ -157,7 +153,8 @@ static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)
        iph->ttl = 32;
        iph->version = 4;
        iph->protocol = IPPROTO_UDP;
-       iplen = sizeof(struct iphdr) + sizeof(struct udphdr) + datalen;
+       iplen = sizeof(struct iphdr) + sizeof(struct udphdr) +
+               sizeof(struct mlx5ehdr);
        iph->tot_len = htons(iplen);
        iph->frag_off = 0;
        iph->saddr = 0;
@@ -170,9 +167,6 @@ static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)
        mlxh = skb_put(skb, sizeof(*mlxh));
        mlxh->version = 0;
        mlxh->magic = cpu_to_be64(MLX5E_TEST_MAGIC);
-       strlcpy(mlxh->text, mlx5e_test_text, sizeof(mlxh->text));
-       datalen -= sizeof(*mlxh);
-       skb_put_zero(skb, datalen);
 
        skb->csum = 0;
        skb->ip_summed = CHECKSUM_PARTIAL;
index 1e55b9c27ffc0f1c3c20156458d85765cd5d6703..3e99d0728b2f2c5366a13f01400d4354d3c80b2c 100644 (file)
@@ -83,6 +83,7 @@ static const struct counter_desc sw_stats_desc[] = {
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_wqe_err) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_mpwqe_filler_cqes) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_mpwqe_filler_strides) },
+       { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_oversize_pkts_sw_drop) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_buff_alloc_err) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_cqe_compress_blks) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_cqe_compress_pkts) },
@@ -161,6 +162,7 @@ void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
                s->rx_wqe_err   += rq_stats->wqe_err;
                s->rx_mpwqe_filler_cqes    += rq_stats->mpwqe_filler_cqes;
                s->rx_mpwqe_filler_strides += rq_stats->mpwqe_filler_strides;
+               s->rx_oversize_pkts_sw_drop += rq_stats->oversize_pkts_sw_drop;
                s->rx_buff_alloc_err += rq_stats->buff_alloc_err;
                s->rx_cqe_compress_blks += rq_stats->cqe_compress_blks;
                s->rx_cqe_compress_pkts += rq_stats->cqe_compress_pkts;
@@ -1189,6 +1191,7 @@ static const struct counter_desc rq_stats_desc[] = {
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, wqe_err) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, mpwqe_filler_cqes) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, mpwqe_filler_strides) },
+       { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, oversize_pkts_sw_drop) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, buff_alloc_err) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, cqe_compress_blks) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, cqe_compress_pkts) },
index 77f74ce11280e26a461343adc92e56d63b387812..3f8e870ef4c903bbca01e894bc2608bbb8ead182 100644 (file)
@@ -96,6 +96,7 @@ struct mlx5e_sw_stats {
        u64 rx_wqe_err;
        u64 rx_mpwqe_filler_cqes;
        u64 rx_mpwqe_filler_strides;
+       u64 rx_oversize_pkts_sw_drop;
        u64 rx_buff_alloc_err;
        u64 rx_cqe_compress_blks;
        u64 rx_cqe_compress_pkts;
@@ -193,6 +194,7 @@ struct mlx5e_rq_stats {
        u64 wqe_err;
        u64 mpwqe_filler_cqes;
        u64 mpwqe_filler_strides;
+       u64 oversize_pkts_sw_drop;
        u64 buff_alloc_err;
        u64 cqe_compress_blks;
        u64 cqe_compress_pkts;
index 608025ca5c04d3d5249595db31edf802bb47615f..fca6f4132c91a51ac2a03eaaf64b0bbc5b6ff2c3 100644 (file)
@@ -1447,31 +1447,21 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                                         inner_headers);
        }
 
-       if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
-               struct flow_dissector_key_eth_addrs *key =
+       if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
+               struct flow_dissector_key_basic *key =
                        skb_flow_dissector_target(f->dissector,
-                                                 FLOW_DISSECTOR_KEY_ETH_ADDRS,
+                                                 FLOW_DISSECTOR_KEY_BASIC,
                                                  f->key);
-               struct flow_dissector_key_eth_addrs *mask =
+               struct flow_dissector_key_basic *mask =
                        skb_flow_dissector_target(f->dissector,
-                                                 FLOW_DISSECTOR_KEY_ETH_ADDRS,
+                                                 FLOW_DISSECTOR_KEY_BASIC,
                                                  f->mask);
+               MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype,
+                        ntohs(mask->n_proto));
+               MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype,
+                        ntohs(key->n_proto));
 
-               ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
-                                            dmac_47_16),
-                               mask->dst);
-               ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
-                                            dmac_47_16),
-                               key->dst);
-
-               ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
-                                            smac_47_16),
-                               mask->src);
-               ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
-                                            smac_47_16),
-                               key->src);
-
-               if (!is_zero_ether_addr(mask->src) || !is_zero_ether_addr(mask->dst))
+               if (mask->n_proto)
                        *match_level = MLX5_MATCH_L2;
        }
 
@@ -1505,9 +1495,10 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
 
                        *match_level = MLX5_MATCH_L2;
                }
-       } else {
+       } else if (*match_level != MLX5_MATCH_NONE) {
                MLX5_SET(fte_match_set_lyr_2_4, headers_c, svlan_tag, 1);
                MLX5_SET(fte_match_set_lyr_2_4, headers_c, cvlan_tag, 1);
+               *match_level = MLX5_MATCH_L2;
        }
 
        if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CVLAN)) {
@@ -1545,21 +1536,31 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                }
        }
 
-       if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
-               struct flow_dissector_key_basic *key =
+       if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
+               struct flow_dissector_key_eth_addrs *key =
                        skb_flow_dissector_target(f->dissector,
-                                                 FLOW_DISSECTOR_KEY_BASIC,
+                                                 FLOW_DISSECTOR_KEY_ETH_ADDRS,
                                                  f->key);
-               struct flow_dissector_key_basic *mask =
+               struct flow_dissector_key_eth_addrs *mask =
                        skb_flow_dissector_target(f->dissector,
-                                                 FLOW_DISSECTOR_KEY_BASIC,
+                                                 FLOW_DISSECTOR_KEY_ETH_ADDRS,
                                                  f->mask);
-               MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype,
-                        ntohs(mask->n_proto));
-               MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype,
-                        ntohs(key->n_proto));
 
-               if (mask->n_proto)
+               ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
+                                            dmac_47_16),
+                               mask->dst);
+               ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
+                                            dmac_47_16),
+                               key->dst);
+
+               ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
+                                            smac_47_16),
+                               mask->src);
+               ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
+                                            smac_47_16),
+                               key->src);
+
+               if (!is_zero_ether_addr(mask->src) || !is_zero_ether_addr(mask->dst))
                        *match_level = MLX5_MATCH_L2;
        }
 
@@ -1586,10 +1587,10 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
 
                        /* the HW doesn't need L3 inline to match on frag=no */
                        if (!(key->flags & FLOW_DIS_IS_FRAGMENT))
-                               *match_level = MLX5_INLINE_MODE_L2;
+                               *match_level = MLX5_MATCH_L2;
        /* ***  L2 attributes parsing up to here *** */
                        else
-                               *match_level = MLX5_INLINE_MODE_IP;
+                               *match_level = MLX5_MATCH_L3;
                }
        }
 
@@ -2979,7 +2980,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
        if (!actions_match_supported(priv, exts, parse_attr, flow, extack))
                return -EOPNOTSUPP;
 
-       if (attr->out_count > 1 && !mlx5_esw_has_fwd_fdb(priv->mdev)) {
+       if (attr->mirror_count > 0 && !mlx5_esw_has_fwd_fdb(priv->mdev)) {
                NL_SET_ERR_MSG_MOD(extack,
                                   "current firmware doesn't support split rule for port mirroring");
                netdev_warn_once(priv->netdev, "current firmware doesn't support split rule for port mirroring\n");
index 515e3d6de05165fa4564e841709a0207f8e19bd5..5a22c5874f3bc30789ffe5fade6ebda0d50ee2b3 100644 (file)
@@ -83,8 +83,14 @@ struct mlx5_fpga_ipsec_rule {
 };
 
 static const struct rhashtable_params rhash_sa = {
-       .key_len = FIELD_SIZEOF(struct mlx5_fpga_ipsec_sa_ctx, hw_sa),
-       .key_offset = offsetof(struct mlx5_fpga_ipsec_sa_ctx, hw_sa),
+       /* Keep out "cmd" field from the key as it's
+        * value is not constant during the lifetime
+        * of the key object.
+        */
+       .key_len = FIELD_SIZEOF(struct mlx5_fpga_ipsec_sa_ctx, hw_sa) -
+                  FIELD_SIZEOF(struct mlx5_ifc_fpga_ipsec_sa_v1, cmd),
+       .key_offset = offsetof(struct mlx5_fpga_ipsec_sa_ctx, hw_sa) +
+                     FIELD_SIZEOF(struct mlx5_ifc_fpga_ipsec_sa_v1, cmd),
        .head_offset = offsetof(struct mlx5_fpga_ipsec_sa_ctx, hash),
        .automatic_shrinking = true,
        .min_size = 1,
index b59953daf8b440e50268c7c1c9a812ba286746d8..11dabd62e2c757e24e0947688d7f25fdd172e88c 100644 (file)
@@ -560,9 +560,9 @@ static int mlx5i_close(struct net_device *netdev)
 
        netif_carrier_off(epriv->netdev);
        mlx5_fs_remove_rx_underlay_qpn(mdev, ipriv->qp.qpn);
-       mlx5i_uninit_underlay_qp(epriv);
        mlx5e_deactivate_priv_channels(epriv);
        mlx5e_close_channels(&epriv->channels);
+       mlx5i_uninit_underlay_qp(epriv);
 unlock:
        mutex_unlock(&epriv->state_lock);
        return 0;
index 867cddba840feb07aa93c1b58908023572951e7a..e8ca98c070f68443c6460ecb10d3eb4b3ee9a2f2 100644 (file)
@@ -1672,7 +1672,7 @@ static int lan743x_tx_napi_poll(struct napi_struct *napi, int weight)
                netif_wake_queue(adapter->netdev);
        }
 
-       if (!napi_complete_done(napi, weight))
+       if (!napi_complete(napi))
                goto done;
 
        /* enable isr */
@@ -1681,7 +1681,7 @@ static int lan743x_tx_napi_poll(struct napi_struct *napi, int weight)
        lan743x_csr_read(adapter, INT_STS);
 
 done:
-       return weight;
+       return 0;
 }
 
 static void lan743x_tx_ring_cleanup(struct lan743x_tx *tx)
@@ -1870,9 +1870,9 @@ static int lan743x_tx_open(struct lan743x_tx *tx)
        tx->vector_flags = lan743x_intr_get_vector_flags(adapter,
                                                         INT_BIT_DMA_TX_
                                                         (tx->channel_number));
-       netif_napi_add(adapter->netdev,
-                      &tx->napi, lan743x_tx_napi_poll,
-                      tx->ring_size - 1);
+       netif_tx_napi_add(adapter->netdev,
+                         &tx->napi, lan743x_tx_napi_poll,
+                         tx->ring_size - 1);
        napi_enable(&tx->napi);
 
        data = 0;
@@ -3017,6 +3017,7 @@ static const struct dev_pm_ops lan743x_pm_ops = {
 
 static const struct pci_device_id lan743x_pcidev_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_SMSC, PCI_DEVICE_ID_SMSC_LAN7430) },
+       { PCI_DEVICE(PCI_VENDOR_ID_SMSC, PCI_DEVICE_ID_SMSC_LAN7431) },
        { 0, }
 };
 
index 0e82b6368798a2cf02cfef922b4feffa2ff779d1..2d6eea18973e8f4c8b5c733d825a5a0cc8492c39 100644 (file)
@@ -548,6 +548,7 @@ struct lan743x_adapter;
 /* SMSC acquired EFAR late 1990's, MCHP acquired SMSC 2012 */
 #define PCI_VENDOR_ID_SMSC             PCI_VENDOR_ID_EFAR
 #define PCI_DEVICE_ID_SMSC_LAN7430     (0x7430)
+#define PCI_DEVICE_ID_SMSC_LAN7431     (0x7431)
 
 #define PCI_CONFIG_LENGTH              (0x1000)
 
index 8e8fa823d611878c1ce166ae271a082b5ec84acd..69966dfc6e3d12f6b754dd94f0ca7fcc4018713f 100644 (file)
@@ -191,7 +191,7 @@ qed_dcbx_dp_protocol(struct qed_hwfn *p_hwfn, struct qed_dcbx_results *p_data)
 static void
 qed_dcbx_set_params(struct qed_dcbx_results *p_data,
                    struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
-                   bool enable, u8 prio, u8 tc,
+                   bool app_tlv, bool enable, u8 prio, u8 tc,
                    enum dcbx_protocol_type type,
                    enum qed_pci_personality personality)
 {
@@ -210,7 +210,7 @@ qed_dcbx_set_params(struct qed_dcbx_results *p_data,
                p_data->arr[type].dont_add_vlan0 = true;
 
        /* QM reconf data */
-       if (p_hwfn->hw_info.personality == personality)
+       if (app_tlv && p_hwfn->hw_info.personality == personality)
                qed_hw_info_set_offload_tc(&p_hwfn->hw_info, tc);
 
        /* Configure dcbx vlan priority in doorbell block for roce EDPM */
@@ -225,7 +225,7 @@ qed_dcbx_set_params(struct qed_dcbx_results *p_data,
 static void
 qed_dcbx_update_app_info(struct qed_dcbx_results *p_data,
                         struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
-                        bool enable, u8 prio, u8 tc,
+                        bool app_tlv, bool enable, u8 prio, u8 tc,
                         enum dcbx_protocol_type type)
 {
        enum qed_pci_personality personality;
@@ -240,7 +240,7 @@ qed_dcbx_update_app_info(struct qed_dcbx_results *p_data,
 
                personality = qed_dcbx_app_update[i].personality;
 
-               qed_dcbx_set_params(p_data, p_hwfn, p_ptt, enable,
+               qed_dcbx_set_params(p_data, p_hwfn, p_ptt, app_tlv, enable,
                                    prio, tc, type, personality);
        }
 }
@@ -319,8 +319,8 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
                                enable = true;
                        }
 
-                       qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, enable,
-                                                priority, tc, type);
+                       qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, true,
+                                                enable, priority, tc, type);
                }
        }
 
@@ -341,7 +341,7 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
                        continue;
 
                enable = (type == DCBX_PROTOCOL_ETH) ? false : !!dcbx_version;
-               qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, enable,
+               qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, false, enable,
                                         priority, tc, type);
        }
 
index 78a638ec7c0aee931c9d56aa278430891e76562f..979f1e4bc18bfbc38946198ea6667ff516edc580 100644 (file)
@@ -6071,7 +6071,7 @@ static const char * const s_igu_fifo_error_strs[] = {
        "no error",
        "length error",
        "function disabled",
-       "VF sent command to attnetion address",
+       "VF sent command to attention address",
        "host sent prod update command",
        "read of during interrupt register while in MIMD mode",
        "access to PXP BAR reserved address",
index 7ceb2b97538d25d767c3d8cc7e7ab79d8b03e760..88a8576ca9ceae1b4adc69b8702f1b626e82e54f 100644 (file)
@@ -185,6 +185,10 @@ void qed_resc_free(struct qed_dev *cdev)
                        qed_iscsi_free(p_hwfn);
                        qed_ooo_free(p_hwfn);
                }
+
+               if (QED_IS_RDMA_PERSONALITY(p_hwfn))
+                       qed_rdma_info_free(p_hwfn);
+
                qed_iov_free(p_hwfn);
                qed_l2_free(p_hwfn);
                qed_dmae_info_free(p_hwfn);
@@ -481,8 +485,16 @@ static u16 *qed_init_qm_get_idx_from_flags(struct qed_hwfn *p_hwfn,
        struct qed_qm_info *qm_info = &p_hwfn->qm_info;
 
        /* Can't have multiple flags set here */
-       if (bitmap_weight((unsigned long *)&pq_flags, sizeof(pq_flags)) > 1)
+       if (bitmap_weight((unsigned long *)&pq_flags,
+                         sizeof(pq_flags) * BITS_PER_BYTE) > 1) {
+               DP_ERR(p_hwfn, "requested multiple pq flags 0x%x\n", pq_flags);
+               goto err;
+       }
+
+       if (!(qed_get_pq_flags(p_hwfn) & pq_flags)) {
+               DP_ERR(p_hwfn, "pq flag 0x%x is not set\n", pq_flags);
                goto err;
+       }
 
        switch (pq_flags) {
        case PQ_FLAGS_RLS:
@@ -506,8 +518,7 @@ static u16 *qed_init_qm_get_idx_from_flags(struct qed_hwfn *p_hwfn,
        }
 
 err:
-       DP_ERR(p_hwfn, "BAD pq flags %d\n", pq_flags);
-       return NULL;
+       return &qm_info->start_pq;
 }
 
 /* save pq index in qm info */
@@ -531,20 +542,32 @@ u16 qed_get_cm_pq_idx_mcos(struct qed_hwfn *p_hwfn, u8 tc)
 {
        u8 max_tc = qed_init_qm_get_num_tcs(p_hwfn);
 
+       if (max_tc == 0) {
+               DP_ERR(p_hwfn, "pq with flag 0x%lx do not exist\n",
+                      PQ_FLAGS_MCOS);
+               return p_hwfn->qm_info.start_pq;
+       }
+
        if (tc > max_tc)
                DP_ERR(p_hwfn, "tc %d must be smaller than %d\n", tc, max_tc);
 
-       return qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_MCOS) + tc;
+       return qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_MCOS) + (tc % max_tc);
 }
 
 u16 qed_get_cm_pq_idx_vf(struct qed_hwfn *p_hwfn, u16 vf)
 {
        u16 max_vf = qed_init_qm_get_num_vfs(p_hwfn);
 
+       if (max_vf == 0) {
+               DP_ERR(p_hwfn, "pq with flag 0x%lx do not exist\n",
+                      PQ_FLAGS_VFS);
+               return p_hwfn->qm_info.start_pq;
+       }
+
        if (vf > max_vf)
                DP_ERR(p_hwfn, "vf %d must be smaller than %d\n", vf, max_vf);
 
-       return qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_VFS) + vf;
+       return qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_VFS) + (vf % max_vf);
 }
 
 u16 qed_get_cm_pq_idx_ofld_mtc(struct qed_hwfn *p_hwfn, u8 tc)
@@ -1081,6 +1104,12 @@ int qed_resc_alloc(struct qed_dev *cdev)
                                goto alloc_err;
                }
 
+               if (QED_IS_RDMA_PERSONALITY(p_hwfn)) {
+                       rc = qed_rdma_info_alloc(p_hwfn);
+                       if (rc)
+                               goto alloc_err;
+               }
+
                /* DMA info initialization */
                rc = qed_dmae_info_alloc(p_hwfn);
                if (rc)
@@ -2102,11 +2131,8 @@ int qed_hw_start_fastpath(struct qed_hwfn *p_hwfn)
        if (!p_ptt)
                return -EAGAIN;
 
-       /* If roce info is allocated it means roce is initialized and should
-        * be enabled in searcher.
-        */
        if (p_hwfn->p_rdma_info &&
-           p_hwfn->b_rdma_enabled_in_prs)
+           p_hwfn->p_rdma_info->active && p_hwfn->b_rdma_enabled_in_prs)
                qed_wr(p_hwfn, p_ptt, p_hwfn->rdma_prs_search_reg, 0x1);
 
        /* Re-open incoming traffic */
index 0f0aba793352c406404b53306f4bfb454b70a8b6..b22f464ea3fa770e94327640e32a35972ee35745 100644 (file)
@@ -992,6 +992,8 @@ static int qed_int_attentions(struct qed_hwfn *p_hwfn)
         */
        do {
                index = p_sb_attn->sb_index;
+               /* finish reading index before the loop condition */
+               dma_rmb();
                attn_bits = le32_to_cpu(p_sb_attn->atten_bits);
                attn_acks = le32_to_cpu(p_sb_attn->atten_ack);
        } while (index != p_sb_attn->sb_index);
index 35fd0db6a67777629fbaa7e1ab89c21b8030d31e..fff7f04d4525c51f15f7e349670a698354edc0f3 100644 (file)
@@ -1782,9 +1782,9 @@ static int qed_drain(struct qed_dev *cdev)
                        return -EBUSY;
                }
                rc = qed_mcp_drain(hwfn, ptt);
+               qed_ptt_release(hwfn, ptt);
                if (rc)
                        return rc;
-               qed_ptt_release(hwfn, ptt);
        }
 
        return 0;
index 62113438c8809c34e5c2dc48bccda67fc9ae21ad..7873d6dfd91f55607a6d60b23b568488edf7d360 100644 (file)
@@ -140,22 +140,34 @@ static u32 qed_rdma_get_sb_id(void *p_hwfn, u32 rel_sb_id)
        return FEAT_NUM((struct qed_hwfn *)p_hwfn, QED_PF_L2_QUE) + rel_sb_id;
 }
 
-static int qed_rdma_alloc(struct qed_hwfn *p_hwfn,
-                         struct qed_ptt *p_ptt,
-                         struct qed_rdma_start_in_params *params)
+int qed_rdma_info_alloc(struct qed_hwfn *p_hwfn)
 {
        struct qed_rdma_info *p_rdma_info;
-       u32 num_cons, num_tasks;
-       int rc = -ENOMEM;
 
-       DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "Allocating RDMA\n");
-
-       /* Allocate a struct with current pf rdma info */
        p_rdma_info = kzalloc(sizeof(*p_rdma_info), GFP_KERNEL);
        if (!p_rdma_info)
-               return rc;
+               return -ENOMEM;
+
+       spin_lock_init(&p_rdma_info->lock);
 
        p_hwfn->p_rdma_info = p_rdma_info;
+       return 0;
+}
+
+void qed_rdma_info_free(struct qed_hwfn *p_hwfn)
+{
+       kfree(p_hwfn->p_rdma_info);
+       p_hwfn->p_rdma_info = NULL;
+}
+
+static int qed_rdma_alloc(struct qed_hwfn *p_hwfn)
+{
+       struct qed_rdma_info *p_rdma_info = p_hwfn->p_rdma_info;
+       u32 num_cons, num_tasks;
+       int rc = -ENOMEM;
+
+       DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "Allocating RDMA\n");
+
        if (QED_IS_IWARP_PERSONALITY(p_hwfn))
                p_rdma_info->proto = PROTOCOLID_IWARP;
        else
@@ -183,7 +195,7 @@ static int qed_rdma_alloc(struct qed_hwfn *p_hwfn,
        /* Allocate a struct with device params and fill it */
        p_rdma_info->dev = kzalloc(sizeof(*p_rdma_info->dev), GFP_KERNEL);
        if (!p_rdma_info->dev)
-               goto free_rdma_info;
+               return rc;
 
        /* Allocate a struct with port params and fill it */
        p_rdma_info->port = kzalloc(sizeof(*p_rdma_info->port), GFP_KERNEL);
@@ -298,8 +310,6 @@ free_rdma_port:
        kfree(p_rdma_info->port);
 free_rdma_dev:
        kfree(p_rdma_info->dev);
-free_rdma_info:
-       kfree(p_rdma_info);
 
        return rc;
 }
@@ -370,8 +380,6 @@ static void qed_rdma_resc_free(struct qed_hwfn *p_hwfn)
 
        kfree(p_rdma_info->port);
        kfree(p_rdma_info->dev);
-
-       kfree(p_rdma_info);
 }
 
 static void qed_rdma_free_tid(void *rdma_cxt, u32 itid)
@@ -679,8 +687,6 @@ static int qed_rdma_setup(struct qed_hwfn *p_hwfn,
 
        DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "RDMA setup\n");
 
-       spin_lock_init(&p_hwfn->p_rdma_info->lock);
-
        qed_rdma_init_devinfo(p_hwfn, params);
        qed_rdma_init_port(p_hwfn);
        qed_rdma_init_events(p_hwfn, params);
@@ -727,7 +733,7 @@ static int qed_rdma_stop(void *rdma_cxt)
        /* Disable RoCE search */
        qed_wr(p_hwfn, p_ptt, p_hwfn->rdma_prs_search_reg, 0);
        p_hwfn->b_rdma_enabled_in_prs = false;
-
+       p_hwfn->p_rdma_info->active = 0;
        qed_wr(p_hwfn, p_ptt, PRS_REG_ROCE_DEST_QP_MAX_PF, 0);
 
        ll2_ethertype_en = qed_rd(p_hwfn, p_ptt, PRS_REG_LIGHT_L2_ETHERTYPE_EN);
@@ -1236,7 +1242,8 @@ qed_rdma_create_qp(void *rdma_cxt,
        u8 max_stats_queues;
        int rc;
 
-       if (!rdma_cxt || !in_params || !out_params || !p_hwfn->p_rdma_info) {
+       if (!rdma_cxt || !in_params || !out_params ||
+           !p_hwfn->p_rdma_info->active) {
                DP_ERR(p_hwfn->cdev,
                       "qed roce create qp failed due to NULL entry (rdma_cxt=%p, in=%p, out=%p, roce_info=?\n",
                       rdma_cxt, in_params, out_params);
@@ -1802,8 +1809,8 @@ bool qed_rdma_allocated_qps(struct qed_hwfn *p_hwfn)
 {
        bool result;
 
-       /* if rdma info has not been allocated, naturally there are no qps */
-       if (!p_hwfn->p_rdma_info)
+       /* if rdma wasn't activated yet, naturally there are no qps */
+       if (!p_hwfn->p_rdma_info->active)
                return false;
 
        spin_lock_bh(&p_hwfn->p_rdma_info->lock);
@@ -1849,7 +1856,7 @@ static int qed_rdma_start(void *rdma_cxt,
        if (!p_ptt)
                goto err;
 
-       rc = qed_rdma_alloc(p_hwfn, p_ptt, params);
+       rc = qed_rdma_alloc(p_hwfn);
        if (rc)
                goto err1;
 
@@ -1858,6 +1865,7 @@ static int qed_rdma_start(void *rdma_cxt,
                goto err2;
 
        qed_ptt_release(p_hwfn, p_ptt);
+       p_hwfn->p_rdma_info->active = 1;
 
        return rc;
 
index 6f722ee8ee945b13ee6f33df82d1692c0ae18304..3689fe3e593542fc487167aae73da99156add030 100644 (file)
@@ -102,6 +102,7 @@ struct qed_rdma_info {
        u16 max_queue_zones;
        enum protocol_type proto;
        struct qed_iwarp_info iwarp;
+       u8 active:1;
 };
 
 struct qed_rdma_qp {
@@ -176,10 +177,14 @@ struct qed_rdma_qp {
 #if IS_ENABLED(CONFIG_QED_RDMA)
 void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
 void qed_rdma_dpm_conf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
+int qed_rdma_info_alloc(struct qed_hwfn *p_hwfn);
+void qed_rdma_info_free(struct qed_hwfn *p_hwfn);
 #else
 static inline void qed_rdma_dpm_conf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) {}
 static inline void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn,
                                    struct qed_ptt *p_ptt) {}
+static inline int qed_rdma_info_alloc(struct qed_hwfn *p_hwfn) {return -EINVAL;}
+static inline void qed_rdma_info_free(struct qed_hwfn *p_hwfn) {}
 #endif
 
 int
index ef9538ee53d0db7f43eae4298dd39258b4c39122..82412691ee66bf13b488db6d61072f239d27d9c3 100644 (file)
@@ -3605,7 +3605,7 @@ static const char velocity_gstrings[][ETH_GSTRING_LEN] = {
        "tx_jumbo",
        "rx_mac_control_frames",
        "tx_mac_control_frames",
-       "rx_frame_alignement_errors",
+       "rx_frame_alignment_errors",
        "rx_long_ok",
        "rx_long_err",
        "tx_sqe_errors",
index 33265747bf3994c668cfcb2a8f7f3d9f768d370a..0fbcedcdf6e2ae5b6d9d8ecca66937532db263cb 100644 (file)
@@ -63,7 +63,7 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
                 * assume the pin serves as pull-up. If direction is
                 * output, the default value is high.
                 */
-               gpiod_set_value(bitbang->mdo, 1);
+               gpiod_set_value_cansleep(bitbang->mdo, 1);
                return;
        }
 
@@ -78,7 +78,7 @@ static int mdio_get(struct mdiobb_ctrl *ctrl)
        struct mdio_gpio_info *bitbang =
                container_of(ctrl, struct mdio_gpio_info, ctrl);
 
-       return gpiod_get_value(bitbang->mdio);
+       return gpiod_get_value_cansleep(bitbang->mdio);
 }
 
 static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
@@ -87,9 +87,9 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
                container_of(ctrl, struct mdio_gpio_info, ctrl);
 
        if (bitbang->mdo)
-               gpiod_set_value(bitbang->mdo, what);
+               gpiod_set_value_cansleep(bitbang->mdo, what);
        else
-               gpiod_set_value(bitbang->mdio, what);
+               gpiod_set_value_cansleep(bitbang->mdio, what);
 }
 
 static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
@@ -97,7 +97,7 @@ static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
        struct mdio_gpio_info *bitbang =
                container_of(ctrl, struct mdio_gpio_info, ctrl);
 
-       gpiod_set_value(bitbang->mdc, what);
+       gpiod_set_value_cansleep(bitbang->mdc, what);
 }
 
 static const struct mdiobb_ops mdio_gpio_ops = {
index a2e59f4f6f01fcfa5b4c754529a68ac1fb57e095..7cae175177449fc4eacae8a3a972bba59043ce6e 100644 (file)
@@ -810,17 +810,13 @@ static int vsc85xx_default_config(struct phy_device *phydev)
 
        phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
        mutex_lock(&phydev->lock);
-       rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
-       if (rc < 0)
-               goto out_unlock;
 
-       reg_val = phy_read(phydev, MSCC_PHY_RGMII_CNTL);
-       reg_val &= ~(RGMII_RX_CLK_DELAY_MASK);
-       reg_val |= (RGMII_RX_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS);
-       phy_write(phydev, MSCC_PHY_RGMII_CNTL, reg_val);
+       reg_val = RGMII_RX_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS;
+
+       rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
+                             MSCC_PHY_RGMII_CNTL, RGMII_RX_CLK_DELAY_MASK,
+                             reg_val);
 
-out_unlock:
-       rc = phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
        mutex_unlock(&phydev->lock);
 
        return rc;
index ab33d1777132e62a141e7ca76c11ef694a6f4e63..23ee3967c166713bac24906f1705a53c8eed8d70 100644 (file)
@@ -2197,6 +2197,14 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner)
        new_driver->mdiodrv.driver.remove = phy_remove;
        new_driver->mdiodrv.driver.owner = owner;
 
+       /* The following works around an issue where the PHY driver doesn't bind
+        * to the device, resulting in the genphy driver being used instead of
+        * the dedicated driver. The root cause of the issue isn't known yet
+        * and seems to be in the base driver core. Once this is fixed we may
+        * remove this workaround.
+        */
+       new_driver->mdiodrv.driver.probe_type = PROBE_FORCE_SYNCHRONOUS;
+
        retval = driver_register(&new_driver->mdiodrv.driver);
        if (retval) {
                pr_err("%s: Error %d in registering driver\n",
index e9f101c9bae2ce1d9bde5dbe0d473119ead760e6..bfbb39f935545794c151c18de29655a574fd8bcd 100644 (file)
@@ -216,9 +216,9 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                         * it just report sending a packet to the target
                         * (without actual packet transfer).
                         */
-                       dev_kfree_skb_any(skb);
                        ndev->stats.tx_packets++;
                        ndev->stats.tx_bytes += skb->len;
+                       dev_kfree_skb_any(skb);
                }
        }
 
index db633ae9f784a7cf0128e922a046160d25b898e1..364f514d56d87368e173c56a8e28b45debe08af3 100644 (file)
@@ -985,8 +985,6 @@ static void team_port_disable(struct team *team,
        team->en_port_count--;
        team_queue_override_port_del(team, port);
        team_adjust_ops(team);
-       team_notify_peers(team);
-       team_mcast_rejoin(team);
        team_lower_state_changed(port);
 }
 
index 060135ceaf0e1a76615b2e6cd6830d42ac8becdf..e244f5d7512a6e8f8a2a5b5eb141a2024f80a078 100644 (file)
@@ -1536,6 +1536,7 @@ static void tun_rx_batched(struct tun_struct *tun, struct tun_file *tfile,
 
        if (!rx_batched || (!more && skb_queue_empty(queue))) {
                local_bh_disable();
+               skb_record_rx_queue(skb, tfile->queue_index);
                netif_receive_skb(skb);
                local_bh_enable();
                return;
@@ -1555,8 +1556,11 @@ static void tun_rx_batched(struct tun_struct *tun, struct tun_file *tfile,
                struct sk_buff *nskb;
 
                local_bh_disable();
-               while ((nskb = __skb_dequeue(&process_queue)))
+               while ((nskb = __skb_dequeue(&process_queue))) {
+                       skb_record_rx_queue(nskb, tfile->queue_index);
                        netif_receive_skb(nskb);
+               }
+               skb_record_rx_queue(skb, tfile->queue_index);
                netif_receive_skb(skb);
                local_bh_enable();
        }
@@ -2451,6 +2455,7 @@ build:
        if (!rcu_dereference(tun->steering_prog))
                rxhash = __skb_get_hash_symmetric(skb);
 
+       skb_record_rx_queue(skb, tfile->queue_index);
        netif_receive_skb(skb);
 
        stats = get_cpu_ptr(tun->pcpu_stats);
index 7275761a1177ca9cda569bfc734bb6de3e1558e1..3d8a70d3ea9bd67c91f85c6cab38d1afbf5f25f3 100644 (file)
@@ -140,7 +140,6 @@ struct ipheth_device {
        struct usb_device *udev;
        struct usb_interface *intf;
        struct net_device *net;
-       struct sk_buff *tx_skb;
        struct urb *tx_urb;
        struct urb *rx_urb;
        unsigned char *tx_buf;
@@ -230,6 +229,7 @@ static void ipheth_rcvbulk_callback(struct urb *urb)
        case -ENOENT:
        case -ECONNRESET:
        case -ESHUTDOWN:
+       case -EPROTO:
                return;
        case 0:
                break;
@@ -281,7 +281,6 @@ static void ipheth_sndbulk_callback(struct urb *urb)
                dev_err(&dev->intf->dev, "%s: urb status: %d\n",
                __func__, status);
 
-       dev_kfree_skb_irq(dev->tx_skb);
        if (status == 0)
                netif_wake_queue(dev->net);
        else
@@ -423,7 +422,7 @@ static int ipheth_tx(struct sk_buff *skb, struct net_device *net)
        if (skb->len > IPHETH_BUF_SIZE) {
                WARN(1, "%s: skb too large: %d bytes\n", __func__, skb->len);
                dev->net->stats.tx_dropped++;
-               dev_kfree_skb_irq(skb);
+               dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
 
@@ -443,12 +442,11 @@ static int ipheth_tx(struct sk_buff *skb, struct net_device *net)
                dev_err(&dev->intf->dev, "%s: usb_submit_urb: %d\n",
                        __func__, retval);
                dev->net->stats.tx_errors++;
-               dev_kfree_skb_irq(skb);
+               dev_kfree_skb_any(skb);
        } else {
-               dev->tx_skb = skb;
-
                dev->net->stats.tx_packets++;
                dev->net->stats.tx_bytes += skb->len;
+               dev_consume_skb_any(skb);
                netif_stop_queue(net);
        }
 
index 3e2c041d76ac1ac61fe5f6033c378feb4e3d6fd0..cecfd77c9f3ca6e4ef1b454a7c049d5f4ec11e56 100644 (file)
@@ -70,7 +70,8 @@ static const unsigned long guest_offloads[] = {
        VIRTIO_NET_F_GUEST_TSO4,
        VIRTIO_NET_F_GUEST_TSO6,
        VIRTIO_NET_F_GUEST_ECN,
-       VIRTIO_NET_F_GUEST_UFO
+       VIRTIO_NET_F_GUEST_UFO,
+       VIRTIO_NET_F_GUEST_CSUM
 };
 
 struct virtnet_stat_desc {
@@ -2334,9 +2335,6 @@ static int virtnet_clear_guest_offloads(struct virtnet_info *vi)
        if (!vi->guest_offloads)
                return 0;
 
-       if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))
-               offloads = 1ULL << VIRTIO_NET_F_GUEST_CSUM;
-
        return virtnet_set_guest_offloads(vi, offloads);
 }
 
@@ -2346,8 +2344,6 @@ static int virtnet_restore_guest_offloads(struct virtnet_info *vi)
 
        if (!vi->guest_offloads)
                return 0;
-       if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))
-               offloads |= 1ULL << VIRTIO_NET_F_GUEST_CSUM;
 
        return virtnet_set_guest_offloads(vi, offloads);
 }
@@ -2365,8 +2361,9 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
            && (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO4) ||
                virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO6) ||
                virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ECN) ||
-               virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_UFO))) {
-               NL_SET_ERR_MSG_MOD(extack, "Can't set XDP while host is implementing LRO, disable LRO first");
+               virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_UFO) ||
+               virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))) {
+               NL_SET_ERR_MSG_MOD(extack, "Can't set XDP while host is implementing LRO/CSUM, disable LRO/CSUM first");
                return -EOPNOTSUPP;
        }
 
index a1c2801ded10123ae46ff1d43e4fd60a04231d90..7e49342bae384d25729e48ae31396ee958e6e967 100644 (file)
@@ -6867,7 +6867,7 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        u32 bitmap;
 
        if (drop) {
-               if (vif->type == NL80211_IFTYPE_STATION) {
+               if (vif && vif->type == NL80211_IFTYPE_STATION) {
                        bitmap = ~(1 << WMI_MGMT_TID);
                        list_for_each_entry(arvif, &ar->arvifs, list) {
                                if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
index 1e3b5f4a4cf929682f1aea668b851e27ef1a2f9b..f23cb2f3d296a0205c07296b212d3805ce35a330 100644 (file)
@@ -1251,6 +1251,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
        struct ath_vif *avp = (void *)vif->drv_priv;
        struct ath_node *an = &avp->mcast_node;
 
+       mutex_lock(&sc->mutex);
        if (IS_ENABLED(CONFIG_ATH9K_TX99)) {
                if (sc->cur_chan->nvifs >= 1) {
                        mutex_unlock(&sc->mutex);
@@ -1259,8 +1260,6 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
                sc->tx99_vif = vif;
        }
 
-       mutex_lock(&sc->mutex);
-
        ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);
        sc->cur_chan->nvifs++;
 
index 230a378c26fcfdbd7e4ed14795a20420bf0ee596..7f0a5bade70a66acf26453bb59c386245c859d06 100644 (file)
@@ -6005,7 +6005,8 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
                         * for subsequent chanspecs.
                         */
                        channel->flags = IEEE80211_CHAN_NO_HT40 |
-                                        IEEE80211_CHAN_NO_80MHZ;
+                                        IEEE80211_CHAN_NO_80MHZ |
+                                        IEEE80211_CHAN_NO_160MHZ;
                        ch.bw = BRCMU_CHAN_BW_20;
                        cfg->d11inf.encchspec(&ch);
                        chaninfo = ch.chspec;
index e7584b842dce4b8cc8fcd08504714e64eefc7f3a..eb5db94f57453f2aed93e89a510fdd210bef7a34 100644 (file)
@@ -193,6 +193,9 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)
                }
                break;
        case BRCMU_CHSPEC_D11AC_BW_160:
+               ch->bw = BRCMU_CHAN_BW_160;
+               ch->sb = brcmu_maskget16(ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
+                                        BRCMU_CHSPEC_D11AC_SB_SHIFT);
                switch (ch->sb) {
                case BRCMU_CHAN_SB_LLL:
                        ch->control_ch_num -= CH_70MHZ_APART;
index 2439e98431eefe4f023ec9c0b38a72010b17e4d1..7492dfb6729b89d181592459e70a49d3a5d0b137 100644 (file)
@@ -6,6 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 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 version 2 of the GNU General Public License as
@@ -26,6 +27,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2017        Intel Deutschland GmbH
+ * Copyright(c) 2018        Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -81,7 +83,7 @@
 #define ACPI_WRDS_WIFI_DATA_SIZE       (ACPI_SAR_TABLE_SIZE + 2)
 #define ACPI_EWRD_WIFI_DATA_SIZE       ((ACPI_SAR_PROFILE_NUM - 1) * \
                                         ACPI_SAR_TABLE_SIZE + 3)
-#define ACPI_WGDS_WIFI_DATA_SIZE       18
+#define ACPI_WGDS_WIFI_DATA_SIZE       19
 #define ACPI_WRDD_WIFI_DATA_SIZE       2
 #define ACPI_SPLC_WIFI_DATA_SIZE       2
 
index 6b95d0e758897cbecf8cac036411cce590d408e8..2b8b50a77990cd453610feb194961929d7adce21 100644 (file)
@@ -154,7 +154,11 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
                        const struct iwl_fw_runtime_ops *ops, void *ops_ctx,
                        struct dentry *dbgfs_dir);
 
-void iwl_fw_runtime_exit(struct iwl_fw_runtime *fwrt);
+static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt)
+{
+       kfree(fwrt->dump.d3_debug_data);
+       fwrt->dump.d3_debug_data = NULL;
+}
 
 void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt);
 
index dade206d551151959ef400f157cf5d3d417529d8..2ba890445c356502502a5d948bb2fdb0a21042bf 100644 (file)
@@ -893,7 +893,7 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
        IWL_DEBUG_RADIO(mvm, "Sending GEO_TX_POWER_LIMIT\n");
 
        BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES * ACPI_WGDS_NUM_BANDS *
-                    ACPI_WGDS_TABLE_SIZE !=  ACPI_WGDS_WIFI_DATA_SIZE);
+                    ACPI_WGDS_TABLE_SIZE + 1 !=  ACPI_WGDS_WIFI_DATA_SIZE);
 
        BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES > IWL_NUM_GEO_PROFILES);
 
@@ -928,6 +928,11 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
        return -ENOENT;
 }
 
+static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
+{
+       return -ENOENT;
+}
+
 static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
 {
        return 0;
@@ -954,8 +959,11 @@ static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
                IWL_DEBUG_RADIO(mvm,
                                "WRDS SAR BIOS table invalid or unavailable. (%d)\n",
                                ret);
-               /* if not available, don't fail and don't bother with EWRD */
-               return 0;
+               /*
+                * If not available, don't fail and don't bother with EWRD.
+                * Return 1 to tell that we can't use WGDS either.
+                */
+               return 1;
        }
 
        ret = iwl_mvm_sar_get_ewrd_table(mvm);
@@ -968,9 +976,13 @@ static int iwl_mvm_sar_init(struct iwl_mvm *mvm)
        /* choose profile 1 (WRDS) as default for both chains */
        ret = iwl_mvm_sar_select_profile(mvm, 1, 1);
 
-       /* if we don't have profile 0 from BIOS, just skip it */
+       /*
+        * If we don't have profile 0 from BIOS, just skip it.  This
+        * means that SAR Geo will not be enabled either, even if we
+        * have other valid profiles.
+        */
        if (ret == -ENOENT)
-               return 0;
+               return 1;
 
        return ret;
 }
@@ -1168,11 +1180,19 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
                iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
 
        ret = iwl_mvm_sar_init(mvm);
-       if (ret)
-               goto error;
+       if (ret == 0) {
+               ret = iwl_mvm_sar_geo_init(mvm);
+       } else if (ret > 0 && !iwl_mvm_sar_get_wgds_table(mvm)) {
+               /*
+                * If basic SAR is not available, we check for WGDS,
+                * which should *not* be available either.  If it is
+                * available, issue an error, because we can't use SAR
+                * Geo without basic SAR.
+                */
+               IWL_ERR(mvm, "BIOS contains WGDS but no WRDS\n");
+       }
 
-       ret = iwl_mvm_sar_geo_init(mvm);
-       if (ret)
+       if (ret < 0)
                goto error;
 
        iwl_mvm_leds_sync(mvm);
index 505b0385d80003e546578fa2a1d8a4684ea1a9dd..00f831d88366d00103697eac358f54c753975448 100644 (file)
@@ -301,8 +301,12 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
                goto out;
        }
 
-       if (changed)
-               *changed = (resp->status == MCC_RESP_NEW_CHAN_PROFILE);
+       if (changed) {
+               u32 status = le32_to_cpu(resp->status);
+
+               *changed = (status == MCC_RESP_NEW_CHAN_PROFILE ||
+                           status == MCC_RESP_ILLEGAL);
+       }
 
        regd = iwl_parse_nvm_mcc_info(mvm->trans->dev, mvm->cfg,
                                      __le32_to_cpu(resp->n_channels),
@@ -4444,10 +4448,6 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
        }
 
-       if (!fw_has_capa(&mvm->fw->ucode_capa,
-                        IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS))
-               return;
-
        /* if beacon filtering isn't on mac80211 does it anyway */
        if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER))
                return;
index 3633f27d048ab7bd36ac99fc38cae1c1197bd0de..6fc5cc1f2b5b3e1cf7e46c9b46e01da266325d2e 100644 (file)
@@ -539,9 +539,8 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,
        }
 
        IWL_DEBUG_LAR(mvm,
-                     "MCC response status: 0x%x. new MCC: 0x%x ('%c%c') change: %d n_chans: %d\n",
-                     status, mcc, mcc >> 8, mcc & 0xff,
-                     !!(status == MCC_RESP_NEW_CHAN_PROFILE), n_channels);
+                     "MCC response status: 0x%x. new MCC: 0x%x ('%c%c') n_chans: %d\n",
+                     status, mcc, mcc >> 8, mcc & 0xff, n_channels);
 
 exit:
        iwl_free_resp(&cmd);
index 0e2092526fae1d81623c08005bbf2f08ee8d7077..af3fba10abc195847d781832ad597a9482613ab2 100644 (file)
@@ -858,6 +858,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        iwl_mvm_thermal_exit(mvm);
  out_free:
        iwl_fw_flush_dump(&mvm->fwrt);
+       iwl_fw_runtime_free(&mvm->fwrt);
 
        if (iwlmvm_mod_params.init_dbg)
                return op_mode;
@@ -910,6 +911,7 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
 
        iwl_mvm_tof_clean(mvm);
 
+       iwl_fw_runtime_free(&mvm->fwrt);
        mutex_destroy(&mvm->mutex);
        mutex_destroy(&mvm->d0i3_suspend_mutex);
 
index 0ccbcd7e887d67d1352886736411e13c0813ccfb..c30d8f5bbf2aa2a3db56818f61821a9698963d14 100644 (file)
@@ -1,6 +1,12 @@
 config MT76_CORE
        tristate
 
+config MT76_LEDS
+       bool
+       depends on MT76_CORE
+       depends on LEDS_CLASS=y || MT76_CORE=LEDS_CLASS
+       default y
+
 config MT76_USB
        tristate
        depends on MT76_CORE
index 2a699e8b79bfbdb2aadc798278c03439ed53811d..7d219ff2d48027e6b7532f0ebec2163fb3a9567d 100644 (file)
@@ -345,9 +345,11 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,
        mt76_check_sband(dev, NL80211_BAND_2GHZ);
        mt76_check_sband(dev, NL80211_BAND_5GHZ);
 
-       ret = mt76_led_init(dev);
-       if (ret)
-               return ret;
+       if (IS_ENABLED(CONFIG_MT76_LEDS)) {
+               ret = mt76_led_init(dev);
+               if (ret)
+                       return ret;
+       }
 
        return ieee80211_register_hw(hw);
 }
index 47c42c607964356f1c6ec634394278b2423a8a9e..7806963b1905293f5067ab5758c35a9f190b8c7d 100644 (file)
@@ -71,7 +71,6 @@ struct mt76x02_dev {
        struct mac_address macaddr_list[8];
 
        struct mutex phy_mutex;
-       struct mutex mutex;
 
        u8 txdone_seq;
        DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status);
index 3824290b219d5b7165a47611eb42cb6bcfe9e042..fd125722d1fb67a1fe2700d34c9f298bfb02a7fc 100644 (file)
@@ -507,8 +507,10 @@ int mt76x2_register_device(struct mt76x02_dev *dev)
        mt76x2_dfs_init_detector(dev);
 
        /* init led callbacks */
-       dev->mt76.led_cdev.brightness_set = mt76x2_led_set_brightness;
-       dev->mt76.led_cdev.blink_set = mt76x2_led_set_blink;
+       if (IS_ENABLED(CONFIG_MT76_LEDS)) {
+               dev->mt76.led_cdev.brightness_set = mt76x2_led_set_brightness;
+               dev->mt76.led_cdev.blink_set = mt76x2_led_set_blink;
+       }
 
        ret = mt76_register_device(&dev->mt76, true, mt76x02_rates,
                                   ARRAY_SIZE(mt76x02_rates));
index 034a062956681ec4f72d45501bab70c1cbe791ad..3f001bd6806ce62ad8fe1c143936549f9fdeac62 100644 (file)
@@ -272,9 +272,9 @@ mt76x2_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
        if (val != ~0 && val > 0xffff)
                return -EINVAL;
 
-       mutex_lock(&dev->mutex);
+       mutex_lock(&dev->mt76.mutex);
        mt76x2_mac_set_tx_protection(dev, val);
-       mutex_unlock(&dev->mutex);
+       mutex_unlock(&dev->mt76.mutex);
 
        return 0;
 }
index 4c2154b9e6a3e59bcb772b34031e6db860227ccb..bd10165d7eec5b4d28c22d06e7a3abad79ade277 100644 (file)
@@ -285,7 +285,7 @@ static int wl1271_probe(struct sdio_func *func,
        struct resource res[2];
        mmc_pm_flag_t mmcflags;
        int ret = -ENOMEM;
-       int irq, wakeirq;
+       int irq, wakeirq, num_irqs;
        const char *chip_family;
 
        /* We are only able to handle the wlan function */
@@ -353,12 +353,17 @@ static int wl1271_probe(struct sdio_func *func,
                       irqd_get_trigger_type(irq_get_irq_data(irq));
        res[0].name = "irq";
 
-       res[1].start = wakeirq;
-       res[1].flags = IORESOURCE_IRQ |
-                      irqd_get_trigger_type(irq_get_irq_data(wakeirq));
-       res[1].name = "wakeirq";
 
-       ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res));
+       if (wakeirq > 0) {
+               res[1].start = wakeirq;
+               res[1].flags = IORESOURCE_IRQ |
+                              irqd_get_trigger_type(irq_get_irq_data(wakeirq));
+               res[1].name = "wakeirq";
+               num_irqs = 2;
+       } else {
+               num_irqs = 1;
+       }
+       ret = platform_device_add_resources(glue->core, res, num_irqs);
        if (ret) {
                dev_err(glue->dev, "can't add resources\n");
                goto out_dev_put;
index 0b70c8bab045ac1a544cf3c72eb1a8766152fcd2..54032c4666361e3f3cb65f60900acb0772b99988 100644 (file)
@@ -152,6 +152,7 @@ struct nvme_fc_ctrl {
 
        bool                    ioq_live;
        bool                    assoc_active;
+       atomic_t                err_work_active;
        u64                     association_id;
 
        struct list_head        ctrl_list;      /* rport->ctrl_list */
@@ -160,6 +161,7 @@ struct nvme_fc_ctrl {
        struct blk_mq_tag_set   tag_set;
 
        struct delayed_work     connect_work;
+       struct work_struct      err_work;
 
        struct kref             ref;
        u32                     flags;
@@ -1531,6 +1533,10 @@ nvme_fc_abort_aen_ops(struct nvme_fc_ctrl *ctrl)
        struct nvme_fc_fcp_op *aen_op = ctrl->aen_ops;
        int i;
 
+       /* ensure we've initialized the ops once */
+       if (!(aen_op->flags & FCOP_FLAGS_AEN))
+               return;
+
        for (i = 0; i < NVME_NR_AEN_COMMANDS; i++, aen_op++)
                __nvme_fc_abort_op(ctrl, aen_op);
 }
@@ -2049,7 +2055,25 @@ nvme_fc_nvme_ctrl_freed(struct nvme_ctrl *nctrl)
 static void
 nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)
 {
-       /* only proceed if in LIVE state - e.g. on first error */
+       int active;
+
+       /*
+        * if an error (io timeout, etc) while (re)connecting,
+        * it's an error on creating the new association.
+        * Start the error recovery thread if it hasn't already
+        * been started. It is expected there could be multiple
+        * ios hitting this path before things are cleaned up.
+        */
+       if (ctrl->ctrl.state == NVME_CTRL_CONNECTING) {
+               active = atomic_xchg(&ctrl->err_work_active, 1);
+               if (!active && !schedule_work(&ctrl->err_work)) {
+                       atomic_set(&ctrl->err_work_active, 0);
+                       WARN_ON(1);
+               }
+               return;
+       }
+
+       /* Otherwise, only proceed if in LIVE state - e.g. on first error */
        if (ctrl->ctrl.state != NVME_CTRL_LIVE)
                return;
 
@@ -2814,6 +2838,7 @@ nvme_fc_delete_ctrl(struct nvme_ctrl *nctrl)
 {
        struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl);
 
+       cancel_work_sync(&ctrl->err_work);
        cancel_delayed_work_sync(&ctrl->connect_work);
        /*
         * kill the association on the link side.  this will block
@@ -2866,23 +2891,30 @@ nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status)
 }
 
 static void
-nvme_fc_reset_ctrl_work(struct work_struct *work)
+__nvme_fc_terminate_io(struct nvme_fc_ctrl *ctrl)
 {
-       struct nvme_fc_ctrl *ctrl =
-               container_of(work, struct nvme_fc_ctrl, ctrl.reset_work);
-       int ret;
-
-       nvme_stop_ctrl(&ctrl->ctrl);
+       nvme_stop_keep_alive(&ctrl->ctrl);
 
        /* will block will waiting for io to terminate */
        nvme_fc_delete_association(ctrl);
 
-       if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) {
+       if (ctrl->ctrl.state != NVME_CTRL_CONNECTING &&
+           !nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING))
                dev_err(ctrl->ctrl.device,
                        "NVME-FC{%d}: error_recovery: Couldn't change state "
                        "to CONNECTING\n", ctrl->cnum);
-               return;
-       }
+}
+
+static void
+nvme_fc_reset_ctrl_work(struct work_struct *work)
+{
+       struct nvme_fc_ctrl *ctrl =
+               container_of(work, struct nvme_fc_ctrl, ctrl.reset_work);
+       int ret;
+
+       __nvme_fc_terminate_io(ctrl);
+
+       nvme_stop_ctrl(&ctrl->ctrl);
 
        if (ctrl->rport->remoteport.port_state == FC_OBJSTATE_ONLINE)
                ret = nvme_fc_create_association(ctrl);
@@ -2897,6 +2929,24 @@ nvme_fc_reset_ctrl_work(struct work_struct *work)
                        ctrl->cnum);
 }
 
+static void
+nvme_fc_connect_err_work(struct work_struct *work)
+{
+       struct nvme_fc_ctrl *ctrl =
+                       container_of(work, struct nvme_fc_ctrl, err_work);
+
+       __nvme_fc_terminate_io(ctrl);
+
+       atomic_set(&ctrl->err_work_active, 0);
+
+       /*
+        * Rescheduling the connection after recovering
+        * from the io error is left to the reconnect work
+        * item, which is what should have stalled waiting on
+        * the io that had the error that scheduled this work.
+        */
+}
+
 static const struct nvme_ctrl_ops nvme_fc_ctrl_ops = {
        .name                   = "fc",
        .module                 = THIS_MODULE,
@@ -3007,6 +3057,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
        ctrl->cnum = idx;
        ctrl->ioq_live = false;
        ctrl->assoc_active = false;
+       atomic_set(&ctrl->err_work_active, 0);
        init_waitqueue_head(&ctrl->ioabort_wait);
 
        get_device(ctrl->dev);
@@ -3014,6 +3065,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
 
        INIT_WORK(&ctrl->ctrl.reset_work, nvme_fc_reset_ctrl_work);
        INIT_DELAYED_WORK(&ctrl->connect_work, nvme_fc_connect_ctrl_work);
+       INIT_WORK(&ctrl->err_work, nvme_fc_connect_err_work);
        spin_lock_init(&ctrl->lock);
 
        /* io queue count */
@@ -3103,6 +3155,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
 fail_ctrl:
        nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING);
        cancel_work_sync(&ctrl->ctrl.reset_work);
+       cancel_work_sync(&ctrl->err_work);
        cancel_delayed_work_sync(&ctrl->connect_work);
 
        ctrl->ctrl.opts = NULL;
index 9b18ce90f90733a0b4d6ceec64921488cd19aa80..27f67dfa649d08373de5d898cffb19f8e851ea93 100644 (file)
@@ -44,6 +44,7 @@ struct nvmem_cell {
        int                     bytes;
        int                     bit_offset;
        int                     nbits;
+       struct device_node      *np;
        struct nvmem_device     *nvmem;
        struct list_head        node;
 };
@@ -298,6 +299,7 @@ static void nvmem_cell_drop(struct nvmem_cell *cell)
        mutex_lock(&nvmem_mutex);
        list_del(&cell->node);
        mutex_unlock(&nvmem_mutex);
+       of_node_put(cell->np);
        kfree(cell->name);
        kfree(cell);
 }
@@ -530,6 +532,7 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)
                        return -ENOMEM;
 
                cell->nvmem = nvmem;
+               cell->np = of_node_get(child);
                cell->offset = be32_to_cpup(addr++);
                cell->bytes = be32_to_cpup(addr);
                cell->name = kasprintf(GFP_KERNEL, "%pOFn", child);
@@ -960,14 +963,13 @@ out:
 
 #if IS_ENABLED(CONFIG_OF)
 static struct nvmem_cell *
-nvmem_find_cell_by_index(struct nvmem_device *nvmem, int index)
+nvmem_find_cell_by_node(struct nvmem_device *nvmem, struct device_node *np)
 {
        struct nvmem_cell *cell = NULL;
-       int i = 0;
 
        mutex_lock(&nvmem_mutex);
        list_for_each_entry(cell, &nvmem->cells, node) {
-               if (index == i++)
+               if (np == cell->np)
                        break;
        }
        mutex_unlock(&nvmem_mutex);
@@ -1011,7 +1013,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
        if (IS_ERR(nvmem))
                return ERR_CAST(nvmem);
 
-       cell = nvmem_find_cell_by_index(nvmem, index);
+       cell = nvmem_find_cell_by_node(nvmem, cell_np);
        if (!cell) {
                __nvmem_device_put(nvmem);
                return ERR_PTR(-ENOENT);
index 9e5a9a3112c9cec57abcffab6c9b23640682756c..3f4fb4dbbe33b0ca755dc547707b815a337597e9 100644 (file)
@@ -288,7 +288,10 @@ static int ti_opp_supply_set_opp(struct dev_pm_set_opp_data *data)
        int ret;
 
        vdd_uv = _get_optimal_vdd_voltage(dev, &opp_data,
-                                         new_supply_vbb->u_volt);
+                                         new_supply_vdd->u_volt);
+
+       if (new_supply_vdd->u_volt_min < vdd_uv)
+               new_supply_vdd->u_volt_min = vdd_uv;
 
        /* Scaling up? Scale voltage before frequency */
        if (freq > old_freq) {
index 2a4aa64685794434f9ffdc5c38613035e63038f3..921db6f803403a27f7f4f8bb4394b9a94d95e0bd 100644 (file)
@@ -793,15 +793,10 @@ static void pci_acpi_setup(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
        struct acpi_device *adev = ACPI_COMPANION(dev);
-       int node;
 
        if (!adev)
                return;
 
-       node = acpi_get_node(adev->handle);
-       if (node != NUMA_NO_NODE)
-               set_dev_node(dev, node);
-
        pci_acpi_optimize_delay(pci_dev, adev->handle);
 
        pci_acpi_add_pm_notifier(adev, pci_dev);
index 4ceb06f8a33c965aa51cb317b56e8a672b55a090..4edeb4cae72aa28ba251558a499ce5a13436d237 100644 (file)
@@ -830,7 +830,7 @@ static struct meson_bank meson_gxbb_periphs_banks[] = {
 
 static struct meson_bank meson_gxbb_aobus_banks[] = {
        /*   name    first      last       irq    pullen  pull    dir     out     in  */
-       BANK("AO",   GPIOAO_0,  GPIOAO_13, 0, 13, 0,  0,  0, 16,  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_pinctrl_data meson_gxbb_periphs_pinctrl_data = {
index 7dae1d7bf6b0a50f75c9d104f43f93972abaf27d..158f618f169570d07dcbd2b9850c72f7334ca495 100644 (file)
@@ -807,7 +807,7 @@ static struct meson_bank meson_gxl_periphs_banks[] = {
 
 static struct meson_bank meson_gxl_aobus_banks[] = {
        /*   name    first      last      irq   pullen  pull    dir     out     in  */
-       BANK("AO",   GPIOAO_0,  GPIOAO_9, 0, 9, 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
+       BANK("AO",   GPIOAO_0,  GPIOAO_9, 0, 9, 0,  16, 0, 0,   0,  0,  0, 16,  1,  0),
 };
 
 static struct meson_pinctrl_data meson_gxl_periphs_pinctrl_data = {
index f8b778a7d47174b902d398fba74ba1845d88b126..53d449076dee32bb64cf3f0093b4a7e9016b9fa7 100644 (file)
@@ -192,7 +192,7 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,
                        dev_dbg(pc->dev, "pin %u: disable bias\n", pin);
 
                        meson_calc_reg_and_bit(bank, pin, REG_PULL, &reg, &bit);
-                       ret = regmap_update_bits(pc->reg_pull, reg,
+                       ret = regmap_update_bits(pc->reg_pullen, reg,
                                                 BIT(bit), 0);
                        if (ret)
                                return ret;
index c6d79315218fa69cadcdde9aa49d657d6916f5bb..86466173114da013ff7dff4e6a89195c9399a82d 100644 (file)
@@ -1053,7 +1053,7 @@ static struct meson_bank meson8_cbus_banks[] = {
 
 static struct meson_bank meson8_aobus_banks[] = {
        /*   name    first     last         irq    pullen  pull    dir     out     in  */
-       BANK("AO",   GPIOAO_0, GPIO_TEST_N, 0, 13, 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
+       BANK("AO",   GPIOAO_0, GPIO_TEST_N, 0, 13, 0, 16,  0,  0,  0,  0,  0, 16,  1,  0),
 };
 
 static struct meson_pinctrl_data meson8_cbus_pinctrl_data = {
index bb2a30964fc69a20bfe488a8904ebd6badaf8e71..647ad15d5c3c41ee538688ade979145efa459b9b 100644 (file)
@@ -906,7 +906,7 @@ static struct meson_bank meson8b_cbus_banks[] = {
 
 static struct meson_bank meson8b_aobus_banks[] = {
        /*   name    first     lastc        irq    pullen  pull    dir     out     in  */
-       BANK("AO",   GPIOAO_0, GPIO_TEST_N, 0, 13, 0,  0,  0, 16,  0,  0,  0, 16,  1,  0),
+       BANK("AO",   GPIOAO_0, GPIO_TEST_N, 0, 13, 0,  16, 0, 0,  0,  0,  0, 16,  1,  0),
 };
 
 static struct meson_pinctrl_data meson8b_cbus_pinctrl_data = {
index e79f2a181ad24217a3e3bc232593184b82d494fd..b9ec4a16db1f6b6fd113c5661a28aa0e9153eeaa 100644 (file)
@@ -50,8 +50,10 @@ static int __init rtc_hctosys(void)
        tv64.tv_sec = rtc_tm_to_time64(&tm);
 
 #if BITS_PER_LONG == 32
-       if (tv64.tv_sec > INT_MAX)
+       if (tv64.tv_sec > INT_MAX) {
+               err = -ERANGE;
                goto err_read;
+       }
 #endif
 
        err = do_settimeofday64(&tv64);
index df0c5776d49bb6f5553dbbf2bc97b3235beae902..a5a19ff10535463d91d39d69ced1f13110ff139d 100644 (file)
@@ -257,6 +257,7 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
        struct cmos_rtc *cmos = dev_get_drvdata(dev);
        unsigned char   rtc_control;
 
+       /* This not only a rtc_op, but also called directly */
        if (!is_valid_irq(cmos->irq))
                return -EIO;
 
@@ -452,6 +453,7 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        unsigned char mon, mday, hrs, min, sec, rtc_control;
        int ret;
 
+       /* This not only a rtc_op, but also called directly */
        if (!is_valid_irq(cmos->irq))
                return -EIO;
 
@@ -516,9 +518,6 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
        struct cmos_rtc *cmos = dev_get_drvdata(dev);
        unsigned long   flags;
 
-       if (!is_valid_irq(cmos->irq))
-               return -EINVAL;
-
        spin_lock_irqsave(&rtc_lock, flags);
 
        if (enabled)
@@ -579,6 +578,12 @@ static const struct rtc_class_ops cmos_rtc_ops = {
        .alarm_irq_enable       = cmos_alarm_irq_enable,
 };
 
+static const struct rtc_class_ops cmos_rtc_ops_no_alarm = {
+       .read_time              = cmos_read_time,
+       .set_time               = cmos_set_time,
+       .proc                   = cmos_procfs,
+};
+
 /*----------------------------------------------------------------*/
 
 /*
@@ -855,9 +860,12 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
                        dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq);
                        goto cleanup1;
                }
+
+               cmos_rtc.rtc->ops = &cmos_rtc_ops;
+       } else {
+               cmos_rtc.rtc->ops = &cmos_rtc_ops_no_alarm;
        }
 
-       cmos_rtc.rtc->ops = &cmos_rtc_ops;
        cmos_rtc.rtc->nvram_old_abi = true;
        retval = rtc_register_device(cmos_rtc.rtc);
        if (retval)
index 9f99a0966550b5e77672e83cc707eda26b22ede5..7cb786d76e3c1da81bf5055bf01375546a74e9ff 100644 (file)
@@ -303,6 +303,9 @@ static int pcf2127_i2c_gather_write(void *context,
        memcpy(buf + 1, val, val_size);
 
        ret = i2c_master_send(client, buf, val_size + 1);
+
+       kfree(buf);
+
        if (ret != val_size + 1)
                return ret < 0 ? ret : -EIO;
 
index f96ec68af2e58aabfa0bdb71dde1f05ff8ad4151..dcbf5c857743782871d9be3dfe51f9fee3d83d91 100644 (file)
@@ -415,9 +415,9 @@ static irqreturn_t ism_handle_irq(int irq, void *data)
                        break;
 
                clear_bit_inv(bit, bv);
+               ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET] = 0;
                barrier();
                smcd_handle_irq(ism->smcd, bit + ISM_DMB_BIT_OFFSET);
-               ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET] = 0;
        }
 
        if (ism->sba->e) {
index f07444d30b216dace2eb7b7adcc59e818c95192e..640cd1b31a18d2bfc164e50adaf819ce27d6d754 100644 (file)
@@ -578,6 +578,7 @@ config SCSI_MYRB
 config SCSI_MYRS
        tristate "Mylex DAC960/DAC1100 PCI RAID Controller (SCSI Interface)"
        depends on PCI
+       depends on !CPU_BIG_ENDIAN || COMPILE_TEST
        select RAID_ATTRS
        help
          This driver adds support for the Mylex DAC960, AcceleRAID, and
index 8429c855701fca200b56df1453a4fc5188a9a38e..01c23d27f290b114c3f9e0b20b713edd30e2d884 100644 (file)
@@ -1198,7 +1198,7 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
 
 out:
        if (!hostdata->selecting)
-               return NULL;
+               return false;
        hostdata->selecting = NULL;
        return ret;
 }
index f0e457e6884e5ca9c92d84c12c1db2cf6906104b..8df822a4a1bd6624abb8814a70e8bdc502274192 100644 (file)
@@ -904,11 +904,9 @@ static void start_delivery_v1_hw(struct hisi_sas_dq *dq)
 {
        struct hisi_hba *hisi_hba = dq->hisi_hba;
        struct hisi_sas_slot *s, *s1, *s2 = NULL;
-       struct list_head *dq_list;
        int dlvry_queue = dq->id;
        int wp;
 
-       dq_list = &dq->list;
        list_for_each_entry_safe(s, s1, &dq->list, delivery) {
                if (!s->ready)
                        break;
index cc36b6473e986b3191f88160ac41f24f730999d6..77a85ead483e098a8e1d837c8130bfb873dc3671 100644 (file)
@@ -1670,11 +1670,9 @@ static void start_delivery_v2_hw(struct hisi_sas_dq *dq)
 {
        struct hisi_hba *hisi_hba = dq->hisi_hba;
        struct hisi_sas_slot *s, *s1, *s2 = NULL;
-       struct list_head *dq_list;
        int dlvry_queue = dq->id;
        int wp;
 
-       dq_list = &dq->list;
        list_for_each_entry_safe(s, s1, &dq->list, delivery) {
                if (!s->ready)
                        break;
index bd4ce38b98d229ad56fb4a224621929b34d11640..a369450a1fa7bfd71160c06211969609cc056f15 100644 (file)
@@ -886,11 +886,9 @@ static void start_delivery_v3_hw(struct hisi_sas_dq *dq)
 {
        struct hisi_hba *hisi_hba = dq->hisi_hba;
        struct hisi_sas_slot *s, *s1, *s2 = NULL;
-       struct list_head *dq_list;
        int dlvry_queue = dq->id;
        int wp;
 
-       dq_list = &dq->list;
        list_for_each_entry_safe(s, s1, &dq->list, delivery) {
                if (!s->ready)
                        break;
index 0c8005bb0f53f271e958c4b1f51eadd7551474b8..34d311a7dbef1b5a0ad9e0cff3ef52d2f0e9103d 100644 (file)
@@ -698,6 +698,8 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
                rport = lpfc_ndlp_get_nrport(ndlp);
                if (rport)
                        nrport = rport->remoteport;
+               else
+                       nrport = NULL;
                spin_unlock(&phba->hbalock);
                if (!nrport)
                        continue;
index aeb282f617c5c43fd182065e1fd9dbab7e6f69d5..0642f2d0a3bb687a1c7ca3de09e24865afa637a7 100644 (file)
@@ -1049,7 +1049,8 @@ static int myrb_get_hba_config(struct myrb_hba *cb)
                enquiry2->fw.firmware_type = '0';
                enquiry2->fw.turn_id = 0;
        }
-       sprintf(cb->fw_version, "%d.%02d-%c-%02d",
+       snprintf(cb->fw_version, sizeof(cb->fw_version),
+               "%d.%02d-%c-%02d",
                enquiry2->fw.major_version,
                enquiry2->fw.minor_version,
                enquiry2->fw.firmware_type,
index 0264a2e2bc190e068832a89452215919b9b22c30..b8d54ef8cf6dfb84c6d4cb3ce2714071cc2de1d6 100644 (file)
@@ -163,9 +163,12 @@ static unsigned char myrs_get_ctlr_info(struct myrs_hba *cs)
        dma_addr_t ctlr_info_addr;
        union myrs_sgl *sgl;
        unsigned char status;
-       struct myrs_ctlr_info old;
+       unsigned short ldev_present, ldev_critical, ldev_offline;
+
+       ldev_present = cs->ctlr_info->ldev_present;
+       ldev_critical = cs->ctlr_info->ldev_critical;
+       ldev_offline = cs->ctlr_info->ldev_offline;
 
-       memcpy(&old, cs->ctlr_info, sizeof(struct myrs_ctlr_info));
        ctlr_info_addr = dma_map_single(&cs->pdev->dev, cs->ctlr_info,
                                        sizeof(struct myrs_ctlr_info),
                                        DMA_FROM_DEVICE);
@@ -198,9 +201,9 @@ static unsigned char myrs_get_ctlr_info(struct myrs_hba *cs)
                    cs->ctlr_info->rbld_active +
                    cs->ctlr_info->exp_active != 0)
                        cs->needs_update = true;
-               if (cs->ctlr_info->ldev_present != old.ldev_present ||
-                   cs->ctlr_info->ldev_critical != old.ldev_critical ||
-                   cs->ctlr_info->ldev_offline != old.ldev_offline)
+               if (cs->ctlr_info->ldev_present != ldev_present ||
+                   cs->ctlr_info->ldev_critical != ldev_critical ||
+                   cs->ctlr_info->ldev_offline != ldev_offline)
                        shost_printk(KERN_INFO, cs->host,
                                     "Logical drive count changes (%d/%d/%d)\n",
                                     cs->ctlr_info->ldev_critical,
index 6fe20c27acc16e54aaf02112735d2b657c61852d..eb59c796a795de06af7d2fa19a64a30e022a3b87 100644 (file)
@@ -4763,6 +4763,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
        fcport->loop_id = FC_NO_LOOP_ID;
        qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED);
        fcport->supported_classes = FC_COS_UNSPECIFIED;
+       fcport->fp_speed = PORT_SPEED_UNKNOWN;
 
        fcport->ct_desc.ct_sns = dma_alloc_coherent(&vha->hw->pdev->dev,
                sizeof(struct ct_sns_pkt), &fcport->ct_desc.ct_sns_dma,
index 518f15141170e733d8acee71cf288c31db6c9261..b658b9a5eb1e172b6549d05b1e8c3aece913f715 100644 (file)
@@ -67,7 +67,7 @@ module_param(ql2xplogiabsentdevice, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(ql2xplogiabsentdevice,
                "Option to enable PLOGI to devices that are not present after "
                "a Fabric scan.  This is needed for several broken switches. "
-               "Default is 0 - no PLOGI. 1 - perfom PLOGI.");
+               "Default is 0 - no PLOGI. 1 - perform PLOGI.");
 
 int ql2xloginretrycount = 0;
 module_param(ql2xloginretrycount, int, S_IRUGO);
@@ -1749,7 +1749,7 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)
 static void
 __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
 {
-       int cnt;
+       int cnt, status;
        unsigned long flags;
        srb_t *sp;
        scsi_qla_host_t *vha = qp->vha;
@@ -1799,10 +1799,16 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
                                        if (!sp_get(sp)) {
                                                spin_unlock_irqrestore
                                                        (qp->qp_lock_ptr, flags);
-                                               qla2xxx_eh_abort(
+                                               status = qla2xxx_eh_abort(
                                                        GET_CMD_SP(sp));
                                                spin_lock_irqsave
                                                        (qp->qp_lock_ptr, flags);
+                                               /*
+                                                * Get rid of extra reference caused
+                                                * by early exit from qla2xxx_eh_abort
+                                                */
+                                               if (status == FAST_IO_FAIL)
+                                                       atomic_dec(&sp->ref_count);
                                        }
                                }
                                sp->done(sp, res);
index c7fccbb8f5545e463537389bc34b607de3dc9cb3..fa6e0c3b3aa678cd1e62f91021dc89036211aa8a 100644 (file)
@@ -697,6 +697,12 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
                 */
                scsi_mq_uninit_cmd(cmd);
 
+               /*
+                * queue is still alive, so grab the ref for preventing it
+                * from being cleaned up during running queue.
+                */
+               percpu_ref_get(&q->q_usage_counter);
+
                __blk_mq_end_request(req, error);
 
                if (scsi_target(sdev)->single_lun ||
@@ -704,6 +710,8 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
                        kblockd_schedule_work(&sdev->requeue_work);
                else
                        blk_mq_run_hw_queues(q, true);
+
+               percpu_ref_put(&q->q_usage_counter);
        } else {
                unsigned long flags;
 
index 46df707e6f2c0404a3c1c4b5f92a76e03feee622..452e19f8fb47027ab4c264f60da67b69eafdbf49 100644 (file)
@@ -20,6 +20,7 @@
 #include "unipro.h"
 #include "ufs-hisi.h"
 #include "ufshci.h"
+#include "ufs_quirks.h"
 
 static int ufs_hisi_check_hibern8(struct ufs_hba *hba)
 {
@@ -390,6 +391,14 @@ static void ufs_hisi_set_dev_cap(struct ufs_hisi_dev_params *hisi_param)
 
 static void ufs_hisi_pwr_change_pre_change(struct ufs_hba *hba)
 {
+       if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME) {
+               pr_info("ufs flash device must set VS_DebugSaveConfigTime 0x10\n");
+               /* VS_DebugSaveConfigTime */
+               ufshcd_dme_set(hba, UIC_ARG_MIB(0xD0A0), 0x10);
+               /* sync length */
+               ufshcd_dme_set(hba, UIC_ARG_MIB(0x1556), 0x48);
+       }
+
        /* update */
        ufshcd_dme_set(hba, UIC_ARG_MIB(0x15A8), 0x1);
        /* PA_TxSkip */
index 71f73d1d1ad1fb9b7c357c65baf0f49ec9dfa780..5d2dfdb41a6ffcc6c20a88189c070a3917d8d4e3 100644 (file)
@@ -131,4 +131,10 @@ struct ufs_dev_fix {
  */
 #define UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME        (1 << 8)
 
+/*
+ * Some UFS devices require VS_DebugSaveConfigTime is 0x10,
+ * enabling this quirk ensure this.
+ */
+#define UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME   (1 << 9)
+
 #endif /* UFS_QUIRKS_H_ */
index 23d7cca36ff031b6463aae8a639b061bfd2c825c..f1c57cd33b5ba3bd78c7b66e0b9b4ba171f17f14 100644 (file)
@@ -231,6 +231,8 @@ static struct ufs_dev_fix ufs_fixups[] = {
        UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),
        UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL,
                UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME),
+       UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1" /*H28U62301AMR*/,
+               UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME),
 
        END_FIX
 };
@@ -8099,13 +8101,6 @@ int ufshcd_alloc_host(struct device *dev, struct ufs_hba **hba_handle)
                err = -ENOMEM;
                goto out_error;
        }
-
-       /*
-        * Do not use blk-mq at this time because blk-mq does not support
-        * runtime pm.
-        */
-       host->use_blk_mq = false;
-
        hba = shost_priv(host);
        hba->host = host;
        hba->dev = dev;
index 7218fb963d0a111d5ccc15cc6d96d1370f9fe3ff..1382a8df6c75f8439f98261811768ca3126883af 100644 (file)
@@ -777,9 +777,6 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,
        u8 la = txn->la;
        bool usr_msg = false;
 
-       if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
-               return -EPROTONOSUPPORT;
-
        if (txn->mt == SLIM_MSG_MT_CORE &&
                (txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&
                 txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW))
index 4399d1873e2d929b4897ad7fedfd8ca69d08ae72..9be41089edde7385abd89b87385376d730be7d29 100644 (file)
 #define SLIM_MSG_MC_NEXT_REMOVE_CHANNEL          0x58
 #define SLIM_MSG_MC_RECONFIGURE_NOW              0x5F
 
-/*
- * Clock pause flag to indicate that the reconfig message
- * corresponds to clock pause sequence
- */
-#define SLIM_MSG_CLK_PAUSE_SEQ_FLG             (1U << 8)
-
 /* Clock pause values per SLIMbus spec */
 #define SLIM_CLK_FAST                          0
 #define SLIM_CLK_CONST_PHASE                   1
index a53231b08d30ee390e9565cfc52c185023692778..e3425bf082ae986ab4c28893c11112654a9fbb2a 100644 (file)
@@ -310,6 +310,7 @@ static int ipipeif_hw_setup(struct v4l2_subdev *sd)
                        ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2);
                        break;
                }
+               /* fall through */
 
        case IPIPEIF_SDRAM_YUV:
                /* Set clock divider */
index 82558455384af6f1bbd576e0181261163c1bdce3..dd121f66fa2de82db949a0027cafad53b1d08225 100644 (file)
@@ -253,7 +253,7 @@ static const struct v4l2_m2m_ops cedrus_m2m_ops = {
 
 static const struct media_device_ops cedrus_m2m_media_ops = {
        .req_validate   = cedrus_request_validate,
-       .req_queue      = vb2_m2m_request_queue,
+       .req_queue      = v4l2_m2m_request_queue,
 };
 
 static int cedrus_probe(struct platform_device *pdev)
index e31e4fc31aa150767c3fc910e6348b6f4a34b7fe..2cfd61d62e9730503414817d52c053c4083ba9e7 100644 (file)
@@ -1778,7 +1778,7 @@ EXPORT_SYMBOL(target_submit_tmr);
 void transport_generic_request_failure(struct se_cmd *cmd,
                sense_reason_t sense_reason)
 {
-       int ret = 0;
+       int ret = 0, post_ret;
 
        pr_debug("-----[ Storage Engine Exception; sense_reason %d\n",
                 sense_reason);
@@ -1790,7 +1790,7 @@ void transport_generic_request_failure(struct se_cmd *cmd,
        transport_complete_task_attr(cmd);
 
        if (cmd->transport_complete_callback)
-               cmd->transport_complete_callback(cmd, false, NULL);
+               cmd->transport_complete_callback(cmd, false, &post_ret);
 
        if (transport_check_aborted_status(cmd, 1))
                return;
index 85644669fbe7b013b59b24adff5fd466230a102b..0a357db4b31b37ddd3ceedd25ecde5f7572d7690 100644 (file)
@@ -961,6 +961,8 @@ int __uio_register_device(struct module *owner,
        if (ret)
                goto err_uio_dev_add_attributes;
 
+       info->uio_dev = idev;
+
        if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) {
                /*
                 * Note that we deliberately don't use devm_request_irq
@@ -972,11 +974,12 @@ int __uio_register_device(struct module *owner,
                 */
                ret = request_irq(info->irq, uio_interrupt,
                                  info->irq_flags, info->name, idev);
-               if (ret)
+               if (ret) {
+                       info->uio_dev = NULL;
                        goto err_request_irq;
+               }
        }
 
-       info->uio_dev = idev;
        return 0;
 
 err_request_irq:
index 47d75c20c211c6f70cad75fcae4ae6b75c458c09..1b68fed464cb96456fcd566f409608bfda34b4f1 100644 (file)
@@ -1696,6 +1696,9 @@ static const struct usb_device_id acm_ids[] = {
        { USB_DEVICE(0x0572, 0x1328), /* Shiro / Aztech USB MODEM UM-3100 */
        .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
        },
+       { USB_DEVICE(0x0572, 0x1349), /* Hiro (Conexant) USB MODEM H50228 */
+       .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
+       },
        { USB_DEVICE(0x20df, 0x0001), /* Simtec Electronics Entropy Key */
        .driver_info = QUIRK_CONTROL_LINE_STATE, },
        { USB_DEVICE(0x2184, 0x001c) }, /* GW Instek AFG-2225 */
index c6077d582d2966a4fbeffd092092c1bf58429db1..0f9381b69a3b563bc63d8010a639bb270f0fc2c8 100644 (file)
@@ -2794,6 +2794,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
        int i, status;
        u16 portchange, portstatus;
        struct usb_port *port_dev = hub->ports[port1 - 1];
+       int reset_recovery_time;
 
        if (!hub_is_superspeed(hub->hdev)) {
                if (warm) {
@@ -2849,7 +2850,9 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
                                        USB_PORT_FEAT_C_BH_PORT_RESET);
                        usb_clear_port_feature(hub->hdev, port1,
                                        USB_PORT_FEAT_C_PORT_LINK_STATE);
-                       usb_clear_port_feature(hub->hdev, port1,
+
+                       if (udev)
+                               usb_clear_port_feature(hub->hdev, port1,
                                        USB_PORT_FEAT_C_CONNECTION);
 
                        /*
@@ -2885,11 +2888,18 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
 
 done:
        if (status == 0) {
-               /* TRSTRCY = 10 ms; plus some extra */
                if (port_dev->quirks & USB_PORT_QUIRK_FAST_ENUM)
                        usleep_range(10000, 12000);
-               else
-                       msleep(10 + 40);
+               else {
+                       /* TRSTRCY = 10 ms; plus some extra */
+                       reset_recovery_time = 10 + 40;
+
+                       /* Hub needs extra delay after resetting its port. */
+                       if (hub->hdev->quirks & USB_QUIRK_HUB_SLOW_RESET)
+                               reset_recovery_time += 100;
+
+                       msleep(reset_recovery_time);
+               }
 
                if (udev) {
                        struct usb_hcd *hcd = bus_to_hcd(udev->bus);
index 178d6c6063c0280a06c6dc3dc6611394d8233479..f9ff03e6af93e7e41acfbcdcb2154dc3a81bbe03 100644 (file)
@@ -128,6 +128,9 @@ static int quirks_param_set(const char *val, const struct kernel_param *kp)
                        case 'n':
                                flags |= USB_QUIRK_DELAY_CTRL_MSG;
                                break;
+                       case 'o':
+                               flags |= USB_QUIRK_HUB_SLOW_RESET;
+                               break;
                        /* Ignore unrecognized flag characters */
                        }
                }
@@ -380,6 +383,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x1a0a, 0x0200), .driver_info =
                        USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
 
+       /* Terminus Technology Inc. Hub */
+       { USB_DEVICE(0x1a40, 0x0101), .driver_info = USB_QUIRK_HUB_SLOW_RESET },
+
        /* Corsair K70 RGB */
        { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT },
 
@@ -391,6 +397,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT |
          USB_QUIRK_DELAY_CTRL_MSG },
 
+       /* Corsair K70 LUX RGB */
+       { USB_DEVICE(0x1b1c, 0x1b33), .driver_info = USB_QUIRK_DELAY_INIT },
+
        /* Corsair K70 LUX */
        { USB_DEVICE(0x1b1c, 0x1b36), .driver_info = USB_QUIRK_DELAY_INIT },
 
@@ -411,6 +420,11 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x2040, 0x7200), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
 
+       /* Raydium Touchscreen */
+       { USB_DEVICE(0x2386, 0x3114), .driver_info = USB_QUIRK_NO_LPM },
+
+       { USB_DEVICE(0x2386, 0x3119), .driver_info = USB_QUIRK_NO_LPM },
+
        /* DJI CineSSD */
        { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM },
 
index d257c541e51ba4e51530e5d8c3d1048794f5f013..7afc10872f1f031370727a277180f664fe8e4c56 100644 (file)
@@ -120,6 +120,7 @@ static int dwc2_pci_probe(struct pci_dev *pci,
        dwc2 = platform_device_alloc("dwc2", PLATFORM_DEVID_AUTO);
        if (!dwc2) {
                dev_err(dev, "couldn't allocate dwc2 device\n");
+               ret = -ENOMEM;
                goto err;
        }
 
index becfbb87f791dad714b5ab23049ede45f9dd63e6..2f2048aa5fde13dde439e52236620f9bab603118 100644 (file)
@@ -1499,6 +1499,7 @@ static int dwc3_probe(struct platform_device *pdev)
 
 err5:
        dwc3_event_buffers_cleanup(dwc);
+       dwc3_ulpi_exit(dwc);
 
 err4:
        dwc3_free_scratch_buffers(dwc);
index 1286076a8890308a66d6ef494b85169ae92d7798..842795856bf49e5093459777b252b33d67e89a96 100644 (file)
@@ -283,8 +283,10 @@ err:
 static void dwc3_pci_remove(struct pci_dev *pci)
 {
        struct dwc3_pci         *dwc = pci_get_drvdata(pci);
+       struct pci_dev          *pdev = dwc->pci;
 
-       gpiod_remove_lookup_table(&platform_bytcr_gpios);
+       if (pdev->device == PCI_DEVICE_ID_INTEL_BYT)
+               gpiod_remove_lookup_table(&platform_bytcr_gpios);
 #ifdef CONFIG_PM
        cancel_work_sync(&dwc->wakeup_work);
 #endif
index 679c12e145225899c1ac5ff3f4f8489d8552a928..9faad896b3a135e86a6d4aebae3678fbc20994d7 100644 (file)
@@ -1081,7 +1081,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
                        /* Now prepare one extra TRB to align transfer size */
                        trb = &dep->trb_pool[dep->trb_enqueue];
                        __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr,
-                                       maxp - rem, false, 0,
+                                       maxp - rem, false, 1,
                                        req->request.stream_id,
                                        req->request.short_not_ok,
                                        req->request.no_interrupt);
@@ -1125,7 +1125,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
                /* Now prepare one extra TRB to align transfer size */
                trb = &dep->trb_pool[dep->trb_enqueue];
                __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem,
-                               false, 0, req->request.stream_id,
+                               false, 1, req->request.stream_id,
                                req->request.short_not_ok,
                                req->request.no_interrupt);
        } else if (req->request.zero && req->request.length &&
@@ -1141,7 +1141,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
                /* Now prepare one extra TRB to handle ZLP */
                trb = &dep->trb_pool[dep->trb_enqueue];
                __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0,
-                               false, 0, req->request.stream_id,
+                               false, 1, req->request.stream_id,
                                req->request.short_not_ok,
                                req->request.no_interrupt);
        } else {
@@ -2259,7 +2259,7 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
         * with one TRB pending in the ring. We need to manually clear HWO bit
         * from that TRB.
         */
-       if ((req->zero || req->unaligned) && (trb->ctrl & DWC3_TRB_CTRL_HWO)) {
+       if ((req->zero || req->unaligned) && !(trb->ctrl & DWC3_TRB_CTRL_CHN)) {
                trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
                return 1;
        }
index 3ada83d81bda8d2810ab04d154b65658f57e0ba2..31e8bf3578c891303a9194c6c23df987cf59f38f 100644 (file)
@@ -215,7 +215,6 @@ struct ffs_io_data {
 
        struct mm_struct *mm;
        struct work_struct work;
-       struct work_struct cancellation_work;
 
        struct usb_ep *ep;
        struct usb_request *req;
@@ -1073,31 +1072,22 @@ ffs_epfile_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static void ffs_aio_cancel_worker(struct work_struct *work)
-{
-       struct ffs_io_data *io_data = container_of(work, struct ffs_io_data,
-                                                  cancellation_work);
-
-       ENTER();
-
-       usb_ep_dequeue(io_data->ep, io_data->req);
-}
-
 static int ffs_aio_cancel(struct kiocb *kiocb)
 {
        struct ffs_io_data *io_data = kiocb->private;
-       struct ffs_data *ffs = io_data->ffs;
+       struct ffs_epfile *epfile = kiocb->ki_filp->private_data;
        int value;
 
        ENTER();
 
-       if (likely(io_data && io_data->ep && io_data->req)) {
-               INIT_WORK(&io_data->cancellation_work, ffs_aio_cancel_worker);
-               queue_work(ffs->io_completion_wq, &io_data->cancellation_work);
-               value = -EINPROGRESS;
-       } else {
+       spin_lock_irq(&epfile->ffs->eps_lock);
+
+       if (likely(io_data && io_data->ep && io_data->req))
+               value = usb_ep_dequeue(io_data->ep, io_data->req);
+       else
                value = -EINVAL;
-       }
+
+       spin_unlock_irq(&epfile->ffs->eps_lock);
 
        return value;
 }
index 27f00160332e2186327da464d7be327d82bc3170..3c4abb5a1c3fc6bdb86e749ab62cf256381c1f75 100644 (file)
@@ -325,14 +325,16 @@ static int xhci_histb_remove(struct platform_device *dev)
        struct xhci_hcd_histb *histb = platform_get_drvdata(dev);
        struct usb_hcd *hcd = histb->hcd;
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+       struct usb_hcd *shared_hcd = xhci->shared_hcd;
 
        xhci->xhc_state |= XHCI_STATE_REMOVING;
 
-       usb_remove_hcd(xhci->shared_hcd);
+       usb_remove_hcd(shared_hcd);
+       xhci->shared_hcd = NULL;
        device_wakeup_disable(&dev->dev);
 
        usb_remove_hcd(hcd);
-       usb_put_hcd(xhci->shared_hcd);
+       usb_put_hcd(shared_hcd);
 
        xhci_histb_host_disable(histb);
        usb_put_hcd(hcd);
index 12eea73d9f20b00701e22da8debdcaa1d9283c92..94aca1b5ac8a228b6ecb690f84441f37c976fbdb 100644 (file)
@@ -876,7 +876,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                        status |= USB_PORT_STAT_SUSPEND;
        }
        if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME &&
-               !DEV_SUPERSPEED_ANY(raw_port_status)) {
+               !DEV_SUPERSPEED_ANY(raw_port_status) && hcd->speed < HCD_USB3) {
                if ((raw_port_status & PORT_RESET) ||
                                !(raw_port_status & PORT_PE))
                        return 0xffffffff;
@@ -921,7 +921,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                        time_left = wait_for_completion_timeout(
                                        &bus_state->rexit_done[wIndex],
                                        msecs_to_jiffies(
-                                               XHCI_MAX_REXIT_TIMEOUT));
+                                               XHCI_MAX_REXIT_TIMEOUT_MS));
                        spin_lock_irqsave(&xhci->lock, flags);
 
                        if (time_left) {
@@ -935,7 +935,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                        } else {
                                int port_status = readl(port->addr);
                                xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n",
-                                               XHCI_MAX_REXIT_TIMEOUT,
+                                               XHCI_MAX_REXIT_TIMEOUT_MS,
                                                port_status);
                                status |= USB_PORT_STAT_SUSPEND;
                                clear_bit(wIndex, &bus_state->rexit_ports);
@@ -1474,15 +1474,18 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
        unsigned long flags;
        struct xhci_hub *rhub;
        struct xhci_port **ports;
+       u32 portsc_buf[USB_MAXCHILDREN];
+       bool wake_enabled;
 
        rhub = xhci_get_rhub(hcd);
        ports = rhub->ports;
        max_ports = rhub->num_ports;
        bus_state = &xhci->bus_state[hcd_index(hcd)];
+       wake_enabled = hcd->self.root_hub->do_remote_wakeup;
 
        spin_lock_irqsave(&xhci->lock, flags);
 
-       if (hcd->self.root_hub->do_remote_wakeup) {
+       if (wake_enabled) {
                if (bus_state->resuming_ports ||        /* USB2 */
                    bus_state->port_remote_wakeup) {    /* USB3 */
                        spin_unlock_irqrestore(&xhci->lock, flags);
@@ -1490,26 +1493,36 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
                        return -EBUSY;
                }
        }
-
-       port_index = max_ports;
+       /*
+        * Prepare ports for suspend, but don't write anything before all ports
+        * are checked and we know bus suspend can proceed
+        */
        bus_state->bus_suspended = 0;
+       port_index = max_ports;
        while (port_index--) {
-               /* suspend the port if the port is not suspended */
                u32 t1, t2;
-               int slot_id;
 
                t1 = readl(ports[port_index]->addr);
                t2 = xhci_port_state_to_neutral(t1);
+               portsc_buf[port_index] = 0;
 
-               if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) {
-                       xhci_dbg(xhci, "port %d not suspended\n", port_index);
-                       slot_id = xhci_find_slot_id_by_port(hcd, xhci,
-                                       port_index + 1);
-                       if (slot_id) {
+               /* Bail out if a USB3 port has a new device in link training */
+               if ((t1 & PORT_PLS_MASK) == XDEV_POLLING) {
+                       bus_state->bus_suspended = 0;
+                       spin_unlock_irqrestore(&xhci->lock, flags);
+                       xhci_dbg(xhci, "Bus suspend bailout, port in polling\n");
+                       return -EBUSY;
+               }
+
+               /* suspend ports in U0, or bail out for new connect changes */
+               if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) {
+                       if ((t1 & PORT_CSC) && wake_enabled) {
+                               bus_state->bus_suspended = 0;
                                spin_unlock_irqrestore(&xhci->lock, flags);
-                               xhci_stop_device(xhci, slot_id, 1);
-                               spin_lock_irqsave(&xhci->lock, flags);
+                               xhci_dbg(xhci, "Bus suspend bailout, port connect change\n");
+                               return -EBUSY;
                        }
+                       xhci_dbg(xhci, "port %d not suspended\n", port_index);
                        t2 &= ~PORT_PLS_MASK;
                        t2 |= PORT_LINK_STROBE | XDEV_U3;
                        set_bit(port_index, &bus_state->bus_suspended);
@@ -1518,7 +1531,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
                 * including the USB 3.0 roothub, but only if CONFIG_PM
                 * is enabled, so also enable remote wake here.
                 */
-               if (hcd->self.root_hub->do_remote_wakeup) {
+               if (wake_enabled) {
                        if (t1 & PORT_CONNECT) {
                                t2 |= PORT_WKOC_E | PORT_WKDISC_E;
                                t2 &= ~PORT_WKCONN_E;
@@ -1538,7 +1551,26 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
 
                t1 = xhci_port_state_to_neutral(t1);
                if (t1 != t2)
-                       writel(t2, ports[port_index]->addr);
+                       portsc_buf[port_index] = t2;
+       }
+
+       /* write port settings, stopping and suspending ports if needed */
+       port_index = max_ports;
+       while (port_index--) {
+               if (!portsc_buf[port_index])
+                       continue;
+               if (test_bit(port_index, &bus_state->bus_suspended)) {
+                       int slot_id;
+
+                       slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+                                                           port_index + 1);
+                       if (slot_id) {
+                               spin_unlock_irqrestore(&xhci->lock, flags);
+                               xhci_stop_device(xhci, slot_id, 1);
+                               spin_lock_irqsave(&xhci->lock, flags);
+                       }
+               }
+               writel(portsc_buf[port_index], ports[port_index]->addr);
        }
        hcd->state = HC_STATE_SUSPENDED;
        bus_state->next_statechange = jiffies + msecs_to_jiffies(10);
index 71d0d33c3286254b0327646720161df6ba5cc1e9..60987c787e44f457d918659140a0671ed7a717e8 100644 (file)
@@ -590,12 +590,14 @@ static int xhci_mtk_remove(struct platform_device *dev)
        struct xhci_hcd_mtk *mtk = platform_get_drvdata(dev);
        struct usb_hcd  *hcd = mtk->hcd;
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+       struct usb_hcd  *shared_hcd = xhci->shared_hcd;
 
-       usb_remove_hcd(xhci->shared_hcd);
+       usb_remove_hcd(shared_hcd);
+       xhci->shared_hcd = NULL;
        device_init_wakeup(&dev->dev, false);
 
        usb_remove_hcd(hcd);
-       usb_put_hcd(xhci->shared_hcd);
+       usb_put_hcd(shared_hcd);
        usb_put_hcd(hcd);
        xhci_mtk_sch_exit(mtk);
        xhci_mtk_clks_disable(mtk);
index 01c57055c0c5bf6b85b8fd45ce2d09c1a0ad3d15..a9515265db4dba4392cc1a834876a5546d8490b2 100644 (file)
@@ -248,6 +248,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)
                xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7;
 
+       if ((pdev->vendor == PCI_VENDOR_ID_BROADCOM ||
+            pdev->vendor == PCI_VENDOR_ID_CAVIUM) &&
+            pdev->device == 0x9026)
+               xhci->quirks |= XHCI_RESET_PLL_ON_DISCONNECT;
+
        if (xhci->quirks & XHCI_RESET_ON_RESUME)
                xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
                                "QUIRK: Resetting on resume");
@@ -380,6 +385,7 @@ static void xhci_pci_remove(struct pci_dev *dev)
        if (xhci->shared_hcd) {
                usb_remove_hcd(xhci->shared_hcd);
                usb_put_hcd(xhci->shared_hcd);
+               xhci->shared_hcd = NULL;
        }
 
        /* Workaround for spurious wakeups at shutdown with HSW */
index 32b5574ad5c56403eb876a70b492f88182096903..ef09cb06212fd367da3593092a31dd5c32d95f58 100644 (file)
@@ -362,14 +362,16 @@ static int xhci_plat_remove(struct platform_device *dev)
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
        struct clk *clk = xhci->clk;
        struct clk *reg_clk = xhci->reg_clk;
+       struct usb_hcd *shared_hcd = xhci->shared_hcd;
 
        xhci->xhc_state |= XHCI_STATE_REMOVING;
 
-       usb_remove_hcd(xhci->shared_hcd);
+       usb_remove_hcd(shared_hcd);
+       xhci->shared_hcd = NULL;
        usb_phy_shutdown(hcd->usb_phy);
 
        usb_remove_hcd(hcd);
-       usb_put_hcd(xhci->shared_hcd);
+       usb_put_hcd(shared_hcd);
 
        clk_disable_unprepare(clk);
        clk_disable_unprepare(reg_clk);
index a8d92c90fb58755ad4359d94d4e52f50b949b2a0..65750582133f6a20eae8949e8a06c2c92c913881 100644 (file)
@@ -1521,6 +1521,35 @@ static void handle_device_notification(struct xhci_hcd *xhci,
                usb_wakeup_notification(udev->parent, udev->portnum);
 }
 
+/*
+ * Quirk hanlder for errata seen on Cavium ThunderX2 processor XHCI
+ * Controller.
+ * As per ThunderX2errata-129 USB 2 device may come up as USB 1
+ * If a connection to a USB 1 device is followed by another connection
+ * to a USB 2 device.
+ *
+ * Reset the PHY after the USB device is disconnected if device speed
+ * is less than HCD_USB3.
+ * Retry the reset sequence max of 4 times checking the PLL lock status.
+ *
+ */
+static void xhci_cavium_reset_phy_quirk(struct xhci_hcd *xhci)
+{
+       struct usb_hcd *hcd = xhci_to_hcd(xhci);
+       u32 pll_lock_check;
+       u32 retry_count = 4;
+
+       do {
+               /* Assert PHY reset */
+               writel(0x6F, hcd->regs + 0x1048);
+               udelay(10);
+               /* De-assert the PHY reset */
+               writel(0x7F, hcd->regs + 0x1048);
+               udelay(200);
+               pll_lock_check = readl(hcd->regs + 0x1070);
+       } while (!(pll_lock_check & 0x1) && --retry_count);
+}
+
 static void handle_port_status(struct xhci_hcd *xhci,
                union xhci_trb *event)
 {
@@ -1556,6 +1585,13 @@ static void handle_port_status(struct xhci_hcd *xhci,
                goto cleanup;
        }
 
+       /* We might get interrupts after shared_hcd is removed */
+       if (port->rhub == &xhci->usb3_rhub && xhci->shared_hcd == NULL) {
+               xhci_dbg(xhci, "ignore port event for removed USB3 hcd\n");
+               bogus_port_status = true;
+               goto cleanup;
+       }
+
        hcd = port->rhub->hcd;
        bus_state = &xhci->bus_state[hcd_index(hcd)];
        hcd_portnum = port->hcd_portnum;
@@ -1639,7 +1675,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
         * RExit to a disconnect state).  If so, let the the driver know it's
         * out of the RExit state.
         */
-       if (!DEV_SUPERSPEED_ANY(portsc) &&
+       if (!DEV_SUPERSPEED_ANY(portsc) && hcd->speed < HCD_USB3 &&
                        test_and_clear_bit(hcd_portnum,
                                &bus_state->rexit_ports)) {
                complete(&bus_state->rexit_done[hcd_portnum]);
@@ -1647,8 +1683,12 @@ static void handle_port_status(struct xhci_hcd *xhci,
                goto cleanup;
        }
 
-       if (hcd->speed < HCD_USB3)
+       if (hcd->speed < HCD_USB3) {
                xhci_test_and_clear_bit(xhci, port, PORT_PLC);
+               if ((xhci->quirks & XHCI_RESET_PLL_ON_DISCONNECT) &&
+                   (portsc & PORT_CSC) && !(portsc & PORT_CONNECT))
+                       xhci_cavium_reset_phy_quirk(xhci);
+       }
 
 cleanup:
        /* Update event ring dequeue pointer before dropping the lock */
@@ -2266,6 +2306,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                        goto cleanup;
                case COMP_RING_UNDERRUN:
                case COMP_RING_OVERRUN:
+               case COMP_STOPPED_LENGTH_INVALID:
                        goto cleanup;
                default:
                        xhci_err(xhci, "ERROR Transfer event for unknown stream ring slot %u ep %u\n",
index 6b5db344de3011df7154f698333e97c5f62f8f69..938ff06c034959f445dc8ad764d2e8a97887c15b 100644 (file)
@@ -1303,6 +1303,7 @@ static int tegra_xusb_remove(struct platform_device *pdev)
 
        usb_remove_hcd(xhci->shared_hcd);
        usb_put_hcd(xhci->shared_hcd);
+       xhci->shared_hcd = NULL;
        usb_remove_hcd(tegra->hcd);
        usb_put_hcd(tegra->hcd);
 
index 0420eefa647a15cb5321dfa5fd95556a5a5432e5..c928dbbff8811206fd3f668564b3ffe627cdd2aa 100644 (file)
@@ -719,8 +719,6 @@ static void xhci_stop(struct usb_hcd *hcd)
 
        /* Only halt host and free memory after both hcds are removed */
        if (!usb_hcd_is_primary_hcd(hcd)) {
-               /* usb core will free this hcd shortly, unset pointer */
-               xhci->shared_hcd = NULL;
                mutex_unlock(&xhci->mutex);
                return;
        }
index bf0b3692dc9a118d30664963e88d6757c7a5f31e..260b259b72bcb6abaf85db2b32c591a64b23dae5 100644 (file)
@@ -1680,7 +1680,7 @@ struct xhci_bus_state {
  * It can take up to 20 ms to transition from RExit to U0 on the
  * Intel Lynx Point LP xHCI host.
  */
-#define        XHCI_MAX_REXIT_TIMEOUT  (20 * 1000)
+#define        XHCI_MAX_REXIT_TIMEOUT_MS       20
 
 static inline unsigned int hcd_index(struct usb_hcd *hcd)
 {
@@ -1849,6 +1849,7 @@ struct xhci_hcd {
 #define XHCI_INTEL_USB_ROLE_SW BIT_ULL(31)
 #define XHCI_ZERO_64B_REGS     BIT_ULL(32)
 #define XHCI_DEFAULT_PM_RUNTIME_ALLOW  BIT_ULL(33)
+#define XHCI_RESET_PLL_ON_DISCONNECT   BIT_ULL(34)
 
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
index bd539f3058bcaa3d754e07bdb7034d4f2786e8a7..85b48c6ddc7e681e7aadb8ddb86d53dbffba85a9 100644 (file)
@@ -50,6 +50,7 @@ static const struct usb_device_id appledisplay_table[] = {
        { APPLEDISPLAY_DEVICE(0x9219) },
        { APPLEDISPLAY_DEVICE(0x921c) },
        { APPLEDISPLAY_DEVICE(0x921d) },
+       { APPLEDISPLAY_DEVICE(0x9222) },
        { APPLEDISPLAY_DEVICE(0x9236) },
 
        /* Terminating entry */
index 59970886690f1b6a3767b72ec33c3c2fe81fd61f..a7b44863d502e95cbb28a1f7ed2f2a17d7ba1043 100644 (file)
@@ -576,6 +576,7 @@ static long afs_wait_for_call_to_complete(struct afs_call *call,
 {
        signed long rtt2, timeout;
        long ret;
+       bool stalled = false;
        u64 rtt;
        u32 life, last_life;
 
@@ -609,12 +610,20 @@ static long afs_wait_for_call_to_complete(struct afs_call *call,
 
                life = rxrpc_kernel_check_life(call->net->socket, call->rxcall);
                if (timeout == 0 &&
-                   life == last_life && signal_pending(current))
+                   life == last_life && signal_pending(current)) {
+                       if (stalled)
                                break;
+                       __set_current_state(TASK_RUNNING);
+                       rxrpc_kernel_probe_life(call->net->socket, call->rxcall);
+                       timeout = rtt2;
+                       stalled = true;
+                       continue;
+               }
 
                if (life != last_life) {
                        timeout = rtt2;
                        last_life = life;
+                       stalled = false;
                }
 
                timeout = schedule_timeout(timeout);
index fc281b738a9822a652f7d19bb60ae15acd7a7ebf..acc3a5536384cf65c6742d918cc2bd9d42305da3 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -62,6 +62,7 @@
 #include <linux/oom.h>
 #include <linux/compat.h>
 #include <linux/vmalloc.h>
+#include <linux/freezer.h>
 
 #include <linux/uaccess.h>
 #include <asm/mmu_context.h>
@@ -1083,7 +1084,7 @@ static int de_thread(struct task_struct *tsk)
        while (sig->notify_count) {
                __set_current_state(TASK_KILLABLE);
                spin_unlock_irq(lock);
-               schedule();
+               freezable_schedule();
                if (unlikely(__fatal_signal_pending(tsk)))
                        goto killed;
                spin_lock_irq(lock);
@@ -1111,7 +1112,7 @@ static int de_thread(struct task_struct *tsk)
                        __set_current_state(TASK_KILLABLE);
                        write_unlock_irq(&tasklist_lock);
                        cgroup_threadgroup_change_end(tsk);
-                       schedule();
+                       freezable_schedule();
                        if (unlikely(__fatal_signal_pending(tsk)))
                                goto killed;
                }
index ae813e609932168ec2e74056fb598aca0ad65907..a5e516a40e7a359cdae8b2bf289175e971b6e6c9 100644 (file)
@@ -165,9 +165,13 @@ static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background)
 
 static void fuse_drop_waiting(struct fuse_conn *fc)
 {
-       if (fc->connected) {
-               atomic_dec(&fc->num_waiting);
-       } else if (atomic_dec_and_test(&fc->num_waiting)) {
+       /*
+        * lockess check of fc->connected is okay, because atomic_dec_and_test()
+        * provides a memory barrier mached with the one in fuse_wait_aborted()
+        * to ensure no wake-up is missed.
+        */
+       if (atomic_dec_and_test(&fc->num_waiting) &&
+           !READ_ONCE(fc->connected)) {
                /* wake up aborters */
                wake_up_all(&fc->blocked_waitq);
        }
@@ -1768,8 +1772,10 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
        req->in.args[1].size = total_len;
 
        err = fuse_request_send_notify_reply(fc, req, outarg->notify_unique);
-       if (err)
+       if (err) {
                fuse_retrieve_end(fc, req);
+               fuse_put_request(fc, req);
+       }
 
        return err;
 }
@@ -2219,6 +2225,8 @@ EXPORT_SYMBOL_GPL(fuse_abort_conn);
 
 void fuse_wait_aborted(struct fuse_conn *fc)
 {
+       /* matches implicit memory barrier in fuse_drop_waiting() */
+       smp_mb();
        wait_event(fc->blocked_waitq, atomic_read(&fc->num_waiting) == 0);
 }
 
index cc2121b37bf5f7d3bb0a57398a2abfc6948ad321..b52f9baaa3e7b9c98478a8c115748ae71fb7b0e1 100644 (file)
@@ -2924,10 +2924,12 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
        }
 
        if (io->async) {
+               bool blocking = io->blocking;
+
                fuse_aio_complete(io, ret < 0 ? ret : 0, -1);
 
                /* we have a non-extending, async request, so return */
-               if (!io->blocking)
+               if (!blocking)
                        return -EIOCBQUEUED;
 
                wait_for_completion(&wait);
index a683d9b27d76033a191b72f81528a7b255de4f08..9a4a15d646ebb2f556828c410cb38c0bd1f30dd5 100644 (file)
@@ -826,7 +826,7 @@ static int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
        ret = gfs2_meta_inode_buffer(ip, &dibh);
        if (ret)
                goto unlock;
-       iomap->private = dibh;
+       mp->mp_bh[0] = dibh;
 
        if (gfs2_is_stuffed(ip)) {
                if (flags & IOMAP_WRITE) {
@@ -863,9 +863,6 @@ unstuff:
        len = lblock_stop - lblock + 1;
        iomap->length = len << inode->i_blkbits;
 
-       get_bh(dibh);
-       mp->mp_bh[0] = dibh;
-
        height = ip->i_height;
        while ((lblock + 1) * sdp->sd_sb.sb_bsize > sdp->sd_heightsize[height])
                height++;
@@ -898,8 +895,6 @@ out:
        iomap->bdev = inode->i_sb->s_bdev;
 unlock:
        up_read(&ip->i_rw_mutex);
-       if (ret && dibh)
-               brelse(dibh);
        return ret;
 
 do_alloc:
@@ -980,9 +975,9 @@ static void gfs2_iomap_journaled_page_done(struct inode *inode, loff_t pos,
 
 static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
                                  loff_t length, unsigned flags,
-                                 struct iomap *iomap)
+                                 struct iomap *iomap,
+                                 struct metapath *mp)
 {
-       struct metapath mp = { .mp_aheight = 1, };
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_sbd *sdp = GFS2_SB(inode);
        unsigned int data_blocks = 0, ind_blocks = 0, rblocks;
@@ -996,9 +991,9 @@ static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
        unstuff = gfs2_is_stuffed(ip) &&
                  pos + length > gfs2_max_stuffed_size(ip);
 
-       ret = gfs2_iomap_get(inode, pos, length, flags, iomap, &mp);
+       ret = gfs2_iomap_get(inode, pos, length, flags, iomap, mp);
        if (ret)
-               goto out_release;
+               goto out_unlock;
 
        alloc_required = unstuff || iomap->type == IOMAP_HOLE;
 
@@ -1013,7 +1008,7 @@ static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
 
                ret = gfs2_quota_lock_check(ip, &ap);
                if (ret)
-                       goto out_release;
+                       goto out_unlock;
 
                ret = gfs2_inplace_reserve(ip, &ap);
                if (ret)
@@ -1038,17 +1033,15 @@ static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
                ret = gfs2_unstuff_dinode(ip, NULL);
                if (ret)
                        goto out_trans_end;
-               release_metapath(&mp);
-               brelse(iomap->private);
-               iomap->private = NULL;
+               release_metapath(mp);
                ret = gfs2_iomap_get(inode, iomap->offset, iomap->length,
-                                    flags, iomap, &mp);
+                                    flags, iomap, mp);
                if (ret)
                        goto out_trans_end;
        }
 
        if (iomap->type == IOMAP_HOLE) {
-               ret = gfs2_iomap_alloc(inode, iomap, flags, &mp);
+               ret = gfs2_iomap_alloc(inode, iomap, flags, mp);
                if (ret) {
                        gfs2_trans_end(sdp);
                        gfs2_inplace_release(ip);
@@ -1056,7 +1049,6 @@ static int gfs2_iomap_begin_write(struct inode *inode, loff_t pos,
                        goto out_qunlock;
                }
        }
-       release_metapath(&mp);
        if (!gfs2_is_stuffed(ip) && gfs2_is_jdata(ip))
                iomap->page_done = gfs2_iomap_journaled_page_done;
        return 0;
@@ -1069,10 +1061,7 @@ out_trans_fail:
 out_qunlock:
        if (alloc_required)
                gfs2_quota_unlock(ip);
-out_release:
-       if (iomap->private)
-               brelse(iomap->private);
-       release_metapath(&mp);
+out_unlock:
        gfs2_write_unlock(inode);
        return ret;
 }
@@ -1088,10 +1077,10 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
 
        trace_gfs2_iomap_start(ip, pos, length, flags);
        if ((flags & IOMAP_WRITE) && !(flags & IOMAP_DIRECT)) {
-               ret = gfs2_iomap_begin_write(inode, pos, length, flags, iomap);
+               ret = gfs2_iomap_begin_write(inode, pos, length, flags, iomap, &mp);
        } else {
                ret = gfs2_iomap_get(inode, pos, length, flags, iomap, &mp);
-               release_metapath(&mp);
+
                /*
                 * Silently fall back to buffered I/O for stuffed files or if
                 * we've hot a hole (see gfs2_file_direct_write).
@@ -1100,6 +1089,11 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
                    iomap->type != IOMAP_MAPPED)
                        ret = -ENOTBLK;
        }
+       if (!ret) {
+               get_bh(mp.mp_bh[0]);
+               iomap->private = mp.mp_bh[0];
+       }
+       release_metapath(&mp);
        trace_gfs2_iomap_end(ip, iomap, ret);
        return ret;
 }
@@ -1908,10 +1902,16 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
                        if (ret < 0)
                                goto out;
 
-                       /* issue read-ahead on metadata */
-                       if (mp.mp_aheight > 1) {
-                               for (; ret > 1; ret--) {
-                                       metapointer_range(&mp, mp.mp_aheight - ret,
+                       /* On the first pass, issue read-ahead on metadata. */
+                       if (mp.mp_aheight > 1 && strip_h == ip->i_height - 1) {
+                               unsigned int height = mp.mp_aheight - 1;
+
+                               /* No read-ahead for data blocks. */
+                               if (mp.mp_aheight - 1 == strip_h)
+                                       height--;
+
+                               for (; height >= mp.mp_aheight - ret; height--) {
+                                       metapointer_range(&mp, height,
                                                          start_list, start_aligned,
                                                          end_list, end_aligned,
                                                          &start, &end);
index ffe3032b1043deafc6730158f3d262d7a66279af..b08a530433adfb56560fedbf4d741205afdfbd41 100644 (file)
@@ -733,6 +733,7 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp)
 
                if (gl) {
                        glock_clear_object(gl, rgd);
+                       gfs2_rgrp_brelse(rgd);
                        gfs2_glock_put(gl);
                }
 
@@ -1174,7 +1175,7 @@ static u32 count_unlinked(struct gfs2_rgrpd *rgd)
  * @rgd: the struct gfs2_rgrpd describing the RG to read in
  *
  * Read in all of a Resource Group's header and bitmap blocks.
- * Caller must eventually call gfs2_rgrp_relse() to free the bitmaps.
+ * Caller must eventually call gfs2_rgrp_brelse() to free the bitmaps.
  *
  * Returns: errno
  */
index 9e198f00b64c6f59e7e4a50b1bc8ddf4ec73cdbf..35d2108d567c25d0de1376a84e8a2a4333859ddf 100644 (file)
@@ -730,8 +730,11 @@ static enum lru_status inode_lru_isolate(struct list_head *item,
                return LRU_REMOVED;
        }
 
-       /* recently referenced inodes get one more pass */
-       if (inode->i_state & I_REFERENCED) {
+       /*
+        * Recently referenced inodes and inodes with many attached pages
+        * get one more pass.
+        */
+       if (inode->i_state & I_REFERENCED || inode->i_data.nrpages > 1) {
                inode->i_state &= ~I_REFERENCED;
                spin_unlock(&inode->i_lock);
                return LRU_ROTATE;
index 64ce240217a18985dd0510fd968b257dce214cd4..3ffb776fbebe33492be0c05c5dee41f5f166b753 100644 (file)
@@ -142,13 +142,14 @@ static void
 iomap_adjust_read_range(struct inode *inode, struct iomap_page *iop,
                loff_t *pos, loff_t length, unsigned *offp, unsigned *lenp)
 {
+       loff_t orig_pos = *pos;
+       loff_t isize = i_size_read(inode);
        unsigned block_bits = inode->i_blkbits;
        unsigned block_size = (1 << block_bits);
        unsigned poff = offset_in_page(*pos);
        unsigned plen = min_t(loff_t, PAGE_SIZE - poff, length);
        unsigned first = poff >> block_bits;
        unsigned last = (poff + plen - 1) >> block_bits;
-       unsigned end = offset_in_page(i_size_read(inode)) >> block_bits;
 
        /*
         * If the block size is smaller than the page size we need to check the
@@ -183,8 +184,12 @@ iomap_adjust_read_range(struct inode *inode, struct iomap_page *iop,
         * handle both halves separately so that we properly zero data in the
         * page cache for blocks that are entirely outside of i_size.
         */
-       if (first <= end && last > end)
-               plen -= (last - end) * block_size;
+       if (orig_pos <= isize && orig_pos + length > isize) {
+               unsigned end = offset_in_page(isize - 1) >> block_bits;
+
+               if (first <= end && last > end)
+                       plen -= (last - end) * block_size;
+       }
 
        *offp = poff;
        *lenp = plen;
@@ -1580,7 +1585,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
        struct bio *bio;
        bool need_zeroout = false;
        bool use_fua = false;
-       int nr_pages, ret;
+       int nr_pages, ret = 0;
        size_t copied = 0;
 
        if ((pos | length | align) & ((1 << blkbits) - 1))
@@ -1596,12 +1601,13 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
 
        if (iomap->flags & IOMAP_F_NEW) {
                need_zeroout = true;
-       } else {
+       } else if (iomap->type == IOMAP_MAPPED) {
                /*
-                * Use a FUA write if we need datasync semantics, this
-                * is a pure data IO that doesn't require any metadata
-                * updates and the underlying device supports FUA. This
-                * allows us to avoid cache flushes on IO completion.
+                * Use a FUA write if we need datasync semantics, this is a pure
+                * data IO that doesn't require any metadata updates (including
+                * after IO completion such as unwritten extent conversion) and
+                * the underlying device supports FUA. This allows us to avoid
+                * cache flushes on IO completion.
                 */
                if (!(iomap->flags & (IOMAP_F_SHARED|IOMAP_F_DIRTY)) &&
                    (dio->flags & IOMAP_DIO_WRITE_FUA) &&
@@ -1644,8 +1650,14 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
 
                ret = bio_iov_iter_get_pages(bio, &iter);
                if (unlikely(ret)) {
+                       /*
+                        * We have to stop part way through an IO. We must fall
+                        * through to the sub-block tail zeroing here, otherwise
+                        * this short IO may expose stale data in the tail of
+                        * the block we haven't written data to.
+                        */
                        bio_put(bio);
-                       return copied ? copied : ret;
+                       goto zero_tail;
                }
 
                n = bio->bi_iter.bi_size;
@@ -1676,13 +1688,21 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
                dio->submit.cookie = submit_bio(bio);
        } while (nr_pages);
 
-       if (need_zeroout) {
+       /*
+        * We need to zeroout the tail of a sub-block write if the extent type
+        * requires zeroing or the write extends beyond EOF. If we don't zero
+        * the block tail in the latter case, we can expose stale data via mmap
+        * reads of the EOF block.
+        */
+zero_tail:
+       if (need_zeroout ||
+           ((dio->flags & IOMAP_DIO_WRITE) && pos >= i_size_read(inode))) {
                /* zero out from the end of the write to the end of the block */
                pad = pos & (fs_block_size - 1);
                if (pad)
                        iomap_dio_zero(dio, iomap, pos, fs_block_size - pad);
        }
-       return copied;
+       return copied ? copied : ret;
 }
 
 static loff_t
@@ -1857,6 +1877,15 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                                dio->wait_for_completion = true;
                                ret = 0;
                        }
+
+                       /*
+                        * Splicing to pipes can fail on a full pipe. We have to
+                        * swallow this to make it look like a short IO
+                        * otherwise the higher splice layers will completely
+                        * mishandle the error and stop moving data.
+                        */
+                       if (ret == -EFAULT)
+                               ret = 0;
                        break;
                }
                pos += ret;
index 74f64294a410838e45fa5f4cf83757fa8b46e844..a7f91265ea671d0f6ebe59d2b9fb0f91bd6155cf 100644 (file)
@@ -695,9 +695,6 @@ static struct mountpoint *lookup_mountpoint(struct dentry *dentry)
 
        hlist_for_each_entry(mp, chain, m_hash) {
                if (mp->m_dentry == dentry) {
-                       /* might be worth a WARN_ON() */
-                       if (d_unlinked(dentry))
-                               return ERR_PTR(-ENOENT);
                        mp->m_count++;
                        return mp;
                }
@@ -711,6 +708,9 @@ static struct mountpoint *get_mountpoint(struct dentry *dentry)
        int ret;
 
        if (d_mountpoint(dentry)) {
+               /* might be worth a WARN_ON() */
+               if (d_unlinked(dentry))
+                       return ERR_PTR(-ENOENT);
 mountpoint:
                read_seqlock_excl(&mount_lock);
                mp = lookup_mountpoint(dentry);
index fa515d5ea5ba12e0e47fb0c6e3c67ea898bc0003..7b861bbc0b43f38285866dd0d0b2eb6afd45a9b8 100644 (file)
@@ -66,7 +66,7 @@ __be32 nfs4_callback_getattr(void *argp, void *resp,
 out_iput:
        rcu_read_unlock();
        trace_nfs4_cb_getattr(cps->clp, &args->fh, inode, -ntohl(res->status));
-       iput(inode);
+       nfs_iput_and_deactive(inode);
 out:
        dprintk("%s: exit with status = %d\n", __func__, ntohl(res->status));
        return res->status;
@@ -108,7 +108,7 @@ __be32 nfs4_callback_recall(void *argp, void *resp,
        }
        trace_nfs4_cb_recall(cps->clp, &args->fh, inode,
                        &args->stateid, -ntohl(res));
-       iput(inode);
+       nfs_iput_and_deactive(inode);
 out:
        dprintk("%s: exit with status = %d\n", __func__, ntohl(res));
        return res;
index 07b83956057627913ac64b44307d19a5765e03e4..6ec2f78c1e191ef3b7b3666fe458856d1fc547bc 100644 (file)
@@ -850,16 +850,23 @@ nfs_delegation_find_inode_server(struct nfs_server *server,
                                 const struct nfs_fh *fhandle)
 {
        struct nfs_delegation *delegation;
-       struct inode *res = NULL;
+       struct inode *freeme, *res = NULL;
 
        list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
                spin_lock(&delegation->lock);
                if (delegation->inode != NULL &&
                    nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
-                       res = igrab(delegation->inode);
+                       freeme = igrab(delegation->inode);
+                       if (freeme && nfs_sb_active(freeme->i_sb))
+                               res = freeme;
                        spin_unlock(&delegation->lock);
                        if (res != NULL)
                                return res;
+                       if (freeme) {
+                               rcu_read_unlock();
+                               iput(freeme);
+                               rcu_read_lock();
+                       }
                        return ERR_PTR(-EAGAIN);
                }
                spin_unlock(&delegation->lock);
index 62ae0fd345ad6751d5dbbf1ab8aefca85eff9e68..ffea5788539490467fcf83a4950a42ccce2e0ed3 100644 (file)
@@ -2601,11 +2601,12 @@ static void nfs4_state_manager(struct nfs_client *clp)
                nfs4_clear_state_manager_bit(clp);
                /* Did we race with an attempt to give us more work? */
                if (clp->cl_state == 0)
-                       break;
+                       return;
                if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
-                       break;
-       } while (refcount_read(&clp->cl_count) > 1);
-       return;
+                       return;
+       } while (refcount_read(&clp->cl_count) > 1 && !signalled());
+       goto out_drain;
+
 out_error:
        if (strlen(section))
                section_sep = ": ";
@@ -2613,6 +2614,7 @@ out_error:
                        " with error %d\n", section_sep, section,
                        clp->cl_hostname, -status);
        ssleep(1);
+out_drain:
        nfs4_end_drain_session(clp);
        nfs4_clear_state_manager_bit(clp);
 }
index edff074d38c75c19a06a6ae5c634ba1fd1688d98..d505990dac7c9137b33120762b4606af655a0fc2 100644 (file)
@@ -1038,6 +1038,9 @@ nfsd4_verify_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 {
        __be32 status;
 
+       if (!cstate->save_fh.fh_dentry)
+               return nfserr_nofilehandle;
+
        status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->save_fh,
                                            src_stateid, RD_STATE, src, NULL);
        if (status) {
index 5769cf3ff035a4b500154eb4e1a4027d3245cbe3..e08a6647267b17d927641c2ef8f34de01c9bbcb3 100644 (file)
@@ -115,12 +115,12 @@ static bool fanotify_should_send_event(struct fsnotify_iter_info *iter_info,
                        continue;
                mark = iter_info->marks[type];
                /*
-                * if the event is for a child and this inode doesn't care about
-                * events on the child, don't send it!
+                * If the event is for a child and this mark doesn't care about
+                * events on a child, don't send it!
                 */
-               if (type == FSNOTIFY_OBJ_TYPE_INODE &&
-                   (event_mask & FS_EVENT_ON_CHILD) &&
-                   !(mark->mask & FS_EVENT_ON_CHILD))
+               if (event_mask & FS_EVENT_ON_CHILD &&
+                   (type != FSNOTIFY_OBJ_TYPE_INODE ||
+                    !(mark->mask & FS_EVENT_ON_CHILD)))
                        continue;
 
                marks_mask |= mark->mask;
index 2172ba516c61d536f5f05045e0a47d7dae30cfc1..d2c34900ae05da81e941b2a2d7503714ec09d8d0 100644 (file)
@@ -167,9 +167,9 @@ int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask
        parent = dget_parent(dentry);
        p_inode = parent->d_inode;
 
-       if (unlikely(!fsnotify_inode_watches_children(p_inode)))
+       if (unlikely(!fsnotify_inode_watches_children(p_inode))) {
                __fsnotify_update_child_dentry_flags(p_inode);
-       else if (p_inode->i_fsnotify_mask & mask) {
+       } else if (p_inode->i_fsnotify_mask & mask & ALL_FSNOTIFY_EVENTS) {
                struct name_snapshot name;
 
                /* we are notifying a parent so come up with the new mask which
@@ -339,6 +339,9 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
                sb = mnt->mnt.mnt_sb;
                mnt_or_sb_mask = mnt->mnt_fsnotify_mask | sb->s_fsnotify_mask;
        }
+       /* An event "on child" is not intended for a mount/sb mark */
+       if (mask & FS_EVENT_ON_CHILD)
+               mnt_or_sb_mask = 0;
 
        /*
         * Optimization: srcu_read_lock() has a memory barrier which can
index da578ad4c08f4b5f5f66d3e7f3e5b5af77cff812..eb1ce30412dc3e09d1fbd4c8e890d86c2d0a4c9f 100644 (file)
@@ -2411,8 +2411,16 @@ static int ocfs2_dio_end_io(struct kiocb *iocb,
        /* this io's submitter should not have unlocked this before we could */
        BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
 
-       if (bytes > 0 && private)
-               ret = ocfs2_dio_end_io_write(inode, private, offset, bytes);
+       if (bytes <= 0)
+               mlog_ratelimited(ML_ERROR, "Direct IO failed, bytes = %lld",
+                                (long long)bytes);
+       if (private) {
+               if (bytes > 0)
+                       ret = ocfs2_dio_end_io_write(inode, private, offset,
+                                                    bytes);
+               else
+                       ocfs2_dio_free_write_ctx(inode, private);
+       }
 
        ocfs2_iocb_clear_rw_locked(iocb);
 
index 308ea0eb35fd112f29a5546c23dba6f80e60c787..a396096a5099f93e95f43b2db71d4f64ce996448 100644 (file)
@@ -178,6 +178,15 @@ do {                                                                       \
                              ##__VA_ARGS__);                           \
 } while (0)
 
+#define mlog_ratelimited(mask, fmt, ...)                               \
+do {                                                                   \
+       static DEFINE_RATELIMIT_STATE(_rs,                              \
+                                     DEFAULT_RATELIMIT_INTERVAL,       \
+                                     DEFAULT_RATELIMIT_BURST);         \
+       if (__ratelimit(&_rs))                                          \
+               mlog(mask, fmt, ##__VA_ARGS__);                         \
+} while (0)
+
 #define mlog_errno(st) ({                                              \
        int _st = (st);                                                 \
        if (_st != -ERESTARTSYS && _st != -EINTR &&                     \
index bfcb4ced5664c00f2fab706ba483094a4bc1ca5a..4dae0399c75a7227f8c53a5d2a06d985fa31b3a0 100644 (file)
@@ -2094,17 +2094,18 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
        off = same->src_offset;
        len = same->src_length;
 
-       ret = -EISDIR;
        if (S_ISDIR(src->i_mode))
-               goto out;
+               return -EISDIR;
 
-       ret = -EINVAL;
        if (!S_ISREG(src->i_mode))
-               goto out;
+               return -EINVAL;
+
+       if (!file->f_op->remap_file_range)
+               return -EOPNOTSUPP;
 
        ret = remap_verify_area(file, off, len, false);
        if (ret < 0)
-               goto out;
+               return ret;
        ret = 0;
 
        if (off + len > i_size_read(src))
@@ -2147,10 +2148,8 @@ next_fdput:
                fdput(dst_fd);
 next_loop:
                if (fatal_signal_pending(current))
-                       goto out;
+                       break;
        }
-
-out:
        return ret;
 }
 EXPORT_SYMBOL(vfs_dedupe_file_range);
index 74d7228e755b3ade097457c0ae68e07e252e67a4..19e921d1586f273f7f234d0c32a8982683821f69 100644 (file)
@@ -1694,10 +1694,13 @@ xfs_bmap_add_extent_delay_real(
        case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
                /*
                 * Filling in all of a previously delayed allocation extent.
-                * The right neighbor is contiguous, the left is not.
+                * The right neighbor is contiguous, the left is not. Take care
+                * with delay -> unwritten extent allocation here because the
+                * delalloc record we are overwriting is always written.
                 */
                PREV.br_startblock = new->br_startblock;
                PREV.br_blockcount += RIGHT.br_blockcount;
+               PREV.br_state = new->br_state;
 
                xfs_iext_next(ifp, &bma->icur);
                xfs_iext_remove(bma->ip, &bma->icur, state);
index 86c50208a14374e2a1588b5686df8d30dc677c57..7fbf8af0b15949fb1e329e270cf66ef9f519eb3f 100644 (file)
@@ -538,15 +538,18 @@ xfs_inobt_rec_check_count(
 
 static xfs_extlen_t
 xfs_inobt_max_size(
-       struct xfs_mount        *mp)
+       struct xfs_mount        *mp,
+       xfs_agnumber_t          agno)
 {
+       xfs_agblock_t           agblocks = xfs_ag_block_count(mp, agno);
+
        /* Bail out if we're uninitialized, which can happen in mkfs. */
        if (mp->m_inobt_mxr[0] == 0)
                return 0;
 
        return xfs_btree_calc_size(mp->m_inobt_mnr,
-               (uint64_t)mp->m_sb.sb_agblocks * mp->m_sb.sb_inopblock /
-                               XFS_INODES_PER_CHUNK);
+                               (uint64_t)agblocks * mp->m_sb.sb_inopblock /
+                                       XFS_INODES_PER_CHUNK);
 }
 
 static int
@@ -594,7 +597,7 @@ xfs_finobt_calc_reserves(
        if (error)
                return error;
 
-       *ask += xfs_inobt_max_size(mp);
+       *ask += xfs_inobt_max_size(mp, agno);
        *used += tree_len;
        return 0;
 }
index 5d263dfdb3bcc60ca30708622397e42de9fbaeac..404e581f1ea1e879e4a32099d303e53a89fbb91a 100644 (file)
@@ -1042,7 +1042,7 @@ out_trans_cancel:
        goto out_unlock;
 }
 
-static int
+int
 xfs_flush_unmap_range(
        struct xfs_inode        *ip,
        xfs_off_t               offset,
@@ -1195,13 +1195,7 @@ xfs_prepare_shift(
         * Writeback and invalidate cache for the remainder of the file as we're
         * about to shift down every extent from offset to EOF.
         */
-       error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, offset, -1);
-       if (error)
-               return error;
-       error = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping,
-                                       offset >> PAGE_SHIFT, -1);
-       if (error)
-               return error;
+       error = xfs_flush_unmap_range(ip, offset, XFS_ISIZE(ip));
 
        /*
         * Clean out anything hanging around in the cow fork now that
index 87363d136bb618145c396223da5b4755bdd572c8..7a78229cf1a79807c7794e5f468eff6e4bf8ff7f 100644 (file)
@@ -80,4 +80,7 @@ int xfs_bmap_count_blocks(struct xfs_trans *tp, struct xfs_inode *ip,
                          int whichfork, xfs_extnum_t *nextents,
                          xfs_filblks_t *count);
 
+int    xfs_flush_unmap_range(struct xfs_inode *ip, xfs_off_t offset,
+                             xfs_off_t len);
+
 #endif /* __XFS_BMAP_UTIL_H__ */
index 12d8455bfbb29114887744046d52cb75428bc911..010db5f8fb00f81deb3524c6356b35f71a2fd7d3 100644 (file)
@@ -1233,9 +1233,23 @@ xfs_buf_iodone(
 }
 
 /*
- * Requeue a failed buffer for writeback
+ * Requeue a failed buffer for writeback.
  *
- * Return true if the buffer has been re-queued properly, false otherwise
+ * We clear the log item failed state here as well, but we have to be careful
+ * about reference counts because the only active reference counts on the buffer
+ * may be the failed log items. Hence if we clear the log item failed state
+ * before queuing the buffer for IO we can release all active references to
+ * the buffer and free it, leading to use after free problems in
+ * xfs_buf_delwri_queue. It makes no difference to the buffer or log items which
+ * order we process them in - the buffer is locked, and we own the buffer list
+ * so nothing on them is going to change while we are performing this action.
+ *
+ * Hence we can safely queue the buffer for IO before we clear the failed log
+ * item state, therefore  always having an active reference to the buffer and
+ * avoiding the transient zero-reference state that leads to use-after-free.
+ *
+ * Return true if the buffer was added to the buffer list, false if it was
+ * already on the buffer list.
  */
 bool
 xfs_buf_resubmit_failed_buffers(
@@ -1243,16 +1257,16 @@ xfs_buf_resubmit_failed_buffers(
        struct list_head        *buffer_list)
 {
        struct xfs_log_item     *lip;
+       bool                    ret;
+
+       ret = xfs_buf_delwri_queue(bp, buffer_list);
 
        /*
-        * Clear XFS_LI_FAILED flag from all items before resubmit
-        *
-        * XFS_LI_FAILED set/clear is protected by ail_lock, caller  this
+        * XFS_LI_FAILED set/clear is protected by ail_lock, caller of this
         * function already have it acquired
         */
        list_for_each_entry(lip, &bp->b_li_list, li_bio_list)
                xfs_clear_li_failed(lip);
 
-       /* Add this buffer back to the delayed write list */
-       return xfs_buf_delwri_queue(bp, buffer_list);
+       return ret;
 }
index 53c9ab8fb777f4d78803da906b151624cfc7053f..e47425071e654473f4b34e7899015cecce19ef5e 100644 (file)
@@ -920,7 +920,7 @@ out_unlock:
 }
 
 
-loff_t
+STATIC loff_t
 xfs_file_remap_range(
        struct file             *file_in,
        loff_t                  pos_in,
index ecdb086bc23e559f6fcfc45ca70590533d04b3c7..322a852ce284a017382ceb9e75bb74762dfbad78 100644 (file)
@@ -296,6 +296,7 @@ xfs_reflink_reserve_cow(
        if (error)
                return error;
 
+       xfs_trim_extent(imap, got.br_startoff, got.br_blockcount);
        trace_xfs_reflink_cow_alloc(ip, &got);
        return 0;
 }
@@ -1351,10 +1352,19 @@ xfs_reflink_remap_prep(
        if (ret)
                goto out_unlock;
 
-       /* Zap any page cache for the destination file's range. */
-       truncate_inode_pages_range(&inode_out->i_data,
-                       round_down(pos_out, PAGE_SIZE),
-                       round_up(pos_out + *len, PAGE_SIZE) - 1);
+       /*
+        * If pos_out > EOF, we may have dirtied blocks between EOF and
+        * pos_out. In that case, we need to extend the flush and unmap to cover
+        * from EOF to the end of the copy length.
+        */
+       if (pos_out > XFS_ISIZE(dest)) {
+               loff_t  flen = *len + (pos_out - XFS_ISIZE(dest));
+               ret = xfs_flush_unmap_range(dest, XFS_ISIZE(dest), flen);
+       } else {
+               ret = xfs_flush_unmap_range(dest, pos_out, *len);
+       }
+       if (ret)
+               goto out_unlock;
 
        return 1;
 out_unlock:
index 3043e5ed6495580de11de6932117addca0e85aec..8a6532aae779b49299e8c99b55b6d770d1866be1 100644 (file)
@@ -280,7 +280,10 @@ DECLARE_EVENT_CLASS(xfs_buf_class,
        ),
        TP_fast_assign(
                __entry->dev = bp->b_target->bt_dev;
-               __entry->bno = bp->b_bn;
+               if (bp->b_bn == XFS_BUF_DADDR_NULL)
+                       __entry->bno = bp->b_maps[0].bm_bn;
+               else
+                       __entry->bno = bp->b_bn;
                __entry->nblks = bp->b_length;
                __entry->hold = atomic_read(&bp->b_hold);
                __entry->pincount = atomic_read(&bp->b_pin_count);
index a83e1f632eb70eeda82581403f2916e7c7346f79..f01623aef2f77945514d4b2ef0045f0735e11851 100644 (file)
@@ -169,6 +169,7 @@ void can_change_state(struct net_device *dev, struct can_frame *cf,
 
 void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
                      unsigned int idx);
+struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr);
 unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx);
 void can_free_echo_skb(struct net_device *dev, unsigned int idx);
 
index cb31683bbe154ab1f5b58319369aa7fe32da1c44..8268811a697e25398b6785b6d8904fc9dca46adf 100644 (file)
@@ -41,7 +41,12 @@ int can_rx_offload_add_timestamp(struct net_device *dev, struct can_rx_offload *
 int can_rx_offload_add_fifo(struct net_device *dev, struct can_rx_offload *offload, unsigned int weight);
 int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload, u64 reg);
 int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload);
-int can_rx_offload_irq_queue_err_skb(struct can_rx_offload *offload, struct sk_buff *skb);
+int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
+                               struct sk_buff *skb, u32 timestamp);
+unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
+                                        unsigned int idx, u32 timestamp);
+int can_rx_offload_queue_tail(struct can_rx_offload *offload,
+                             struct sk_buff *skb);
 void can_rx_offload_reset(struct can_rx_offload *offload);
 void can_rx_offload_del(struct can_rx_offload *offload);
 void can_rx_offload_enable(struct can_rx_offload *offload);
index 845174e113ce9b360e899553b7e97f837a5abff7..100ce4a4aff6ce1808a0993a7bc24ebeb3612468 100644 (file)
@@ -1167,6 +1167,8 @@ static inline bool efi_enabled(int feature)
 extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused);
 
 extern bool efi_is_table_address(unsigned long phys_addr);
+
+extern int efi_apply_persistent_mem_reservations(void);
 #else
 static inline bool efi_enabled(int feature)
 {
@@ -1185,6 +1187,11 @@ static inline bool efi_is_table_address(unsigned long phys_addr)
 {
        return false;
 }
+
+static inline int efi_apply_persistent_mem_reservations(void)
+{
+       return 0;
+}
 #endif
 
 extern int efi_status_to_err(efi_status_t status);
index de629b706d1d7dda246819ed37109f098c05785e..448dcc448f1fe59cb14de60969f71f8ba6c35278 100644 (file)
@@ -866,6 +866,10 @@ void bpf_jit_binary_free(struct bpf_binary_header *hdr);
 
 void bpf_jit_free(struct bpf_prog *fp);
 
+int bpf_jit_get_func_addr(const struct bpf_prog *prog,
+                         const struct bpf_insn *insn, bool extra_pass,
+                         u64 *func_addr, bool *func_addr_fixed);
+
 struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *fp);
 void bpf_jit_prog_release_other(struct bpf_prog *fp, struct bpf_prog *fp_other);
 
index c79e859408e62d7cd7306407bbaf4c6489103905..fd458389f7d19291ed6a13c22ff60eff5e34b7b3 100644 (file)
@@ -406,6 +406,8 @@ static inline void net_dim(struct net_dim *dim,
                }
                /* fall through */
        case NET_DIM_START_MEASURE:
+               net_dim_sample(end_sample.event_ctr, end_sample.pkt_ctr, end_sample.byte_ctr,
+                              &dim->start_sample);
                dim->state = NET_DIM_MEASURE_IN_PROGRESS;
                break;
        case NET_DIM_APPLY_NEW_PROFILE:
index 0ba687454267fdac6f69d8fea69ffaa94c1bb205..0d1b2c3f127b3a4f316dca1ed6ffb7d65aac0cc1 100644 (file)
@@ -1326,6 +1326,22 @@ static inline void skb_zcopy_set(struct sk_buff *skb, struct ubuf_info *uarg)
        }
 }
 
+static inline void skb_zcopy_set_nouarg(struct sk_buff *skb, void *val)
+{
+       skb_shinfo(skb)->destructor_arg = (void *)((uintptr_t) val | 0x1UL);
+       skb_shinfo(skb)->tx_flags |= SKBTX_ZEROCOPY_FRAG;
+}
+
+static inline bool skb_zcopy_is_nouarg(struct sk_buff *skb)
+{
+       return (uintptr_t) skb_shinfo(skb)->destructor_arg & 0x1UL;
+}
+
+static inline void *skb_zcopy_get_nouarg(struct sk_buff *skb)
+{
+       return (void *)((uintptr_t) skb_shinfo(skb)->destructor_arg & ~0x1UL);
+}
+
 /* Release a reference on a zerocopy structure */
 static inline void skb_zcopy_clear(struct sk_buff *skb, bool zerocopy)
 {
@@ -1335,7 +1351,7 @@ static inline void skb_zcopy_clear(struct sk_buff *skb, bool zerocopy)
                if (uarg->callback == sock_zerocopy_callback) {
                        uarg->zerocopy = uarg->zerocopy && zerocopy;
                        sock_zerocopy_put(uarg);
-               } else {
+               } else if (!skb_zcopy_is_nouarg(skb)) {
                        uarg->callback(uarg, zerocopy);
                }
 
index 8ed77bb4ed8636e9294389a011529fd9a667dce4..a9b0280687d52797972506a8bac13ed0747e2182 100644 (file)
@@ -196,6 +196,7 @@ struct tcp_sock {
        u32     rcv_tstamp;     /* timestamp of last received ACK (for keepalives) */
        u32     lsndtime;       /* timestamp of last sent data packet (for restart window) */
        u32     last_oow_ack_time;  /* timestamp of last out-of-window ACK */
+       u32     compressed_ack_rcv_nxt;
 
        u32     tsoffset;       /* timestamp offset */
 
index b7a99ce56bc9ad6cd4c8ff2c5681d6fbb781b875..a1be64c9940fb4ad4e2365f226419f050d6addba 100644 (file)
@@ -66,4 +66,7 @@
 /* Device needs a pause after every control message. */
 #define USB_QUIRK_DELAY_CTRL_MSG               BIT(13)
 
+/* Hub needs extra delay after resetting its port. */
+#define USB_QUIRK_HUB_SLOW_RESET               BIT(14)
+
 #endif /* __LINUX_USB_QUIRKS_H */
index 58c1ecf3d6489cda2cfd77a5f7de47abc7d90d3a..5467264771ec136f1b2f9b4ee538f847221f90d9 100644 (file)
@@ -624,7 +624,7 @@ v4l2_m2m_dst_buf_remove_by_idx(struct v4l2_m2m_ctx *m2m_ctx, unsigned int idx)
 
 /* v4l2 request helper */
 
-void vb2_m2m_request_queue(struct media_request *req);
+void v4l2_m2m_request_queue(struct media_request *req);
 
 /* v4l2 ioctl helpers */
 
index de587948042a4ab6ce9e00dac021ce492a026621..1adefe42c0a689b839492d500327ef891c4c395c 100644 (file)
@@ -77,7 +77,8 @@ int rxrpc_kernel_retry_call(struct socket *, struct rxrpc_call *,
                            struct sockaddr_rxrpc *, struct key *);
 int rxrpc_kernel_check_call(struct socket *, struct rxrpc_call *,
                            enum rxrpc_call_completion *, u32 *);
-u32 rxrpc_kernel_check_life(struct socket *, struct rxrpc_call *);
+u32 rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *);
+void rxrpc_kernel_probe_life(struct socket *, struct rxrpc_call *);
 u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *);
 bool rxrpc_kernel_get_reply_time(struct socket *, struct rxrpc_call *,
                                 ktime_t *);
index 8c2caa370e0f683ea764bc0d72da6dfa93699673..ab9242e51d9e04ac6f4a18d50710c03dbc82ff24 100644 (file)
@@ -608,4 +608,16 @@ static inline __u32 sctp_dst_mtu(const struct dst_entry *dst)
                                 SCTP_DEFAULT_MINSEGMENT));
 }
 
+static inline bool sctp_transport_pmtu_check(struct sctp_transport *t)
+{
+       __u32 pmtu = sctp_dst_mtu(t->dst);
+
+       if (t->pathmtu == pmtu)
+               return true;
+
+       t->pathmtu = pmtu;
+
+       return false;
+}
+
 #endif /* __net_sctp_h__ */
index a9834c37ac40061d0e18209756c1d3be2c0497d7..c0e7d24ca25682acf384d56d7b0c87e71e6c456b 100644 (file)
@@ -31,8 +31,8 @@ TRACE_EVENT(kyber_latency,
 
        TP_fast_assign(
                __entry->dev            = disk_devt(dev_to_disk(kobj_to_dev(q->kobj.parent)));
-               strlcpy(__entry->domain, domain, DOMAIN_LEN);
-               strlcpy(__entry->type, type, DOMAIN_LEN);
+               strlcpy(__entry->domain, domain, sizeof(__entry->domain));
+               strlcpy(__entry->type, type, sizeof(__entry->type));
                __entry->percentile     = percentile;
                __entry->numerator      = numerator;
                __entry->denominator    = denominator;
@@ -60,7 +60,7 @@ TRACE_EVENT(kyber_adjust,
 
        TP_fast_assign(
                __entry->dev            = disk_devt(dev_to_disk(kobj_to_dev(q->kobj.parent)));
-               strlcpy(__entry->domain, domain, DOMAIN_LEN);
+               strlcpy(__entry->domain, domain, sizeof(__entry->domain));
                __entry->depth          = depth;
        ),
 
@@ -82,7 +82,7 @@ TRACE_EVENT(kyber_throttled,
 
        TP_fast_assign(
                __entry->dev            = disk_devt(dev_to_disk(kobj_to_dev(q->kobj.parent)));
-               strlcpy(__entry->domain, domain, DOMAIN_LEN);
+               strlcpy(__entry->domain, domain, sizeof(__entry->domain));
        ),
 
        TP_printk("%d,%d %s", MAJOR(__entry->dev), MINOR(__entry->dev),
index 573d5b901fb11886590a2672cf396af64476efeb..5b50fe4906d2ef95d5121a80109fdb1f130ead2b 100644 (file)
@@ -181,6 +181,7 @@ enum rxrpc_timer_trace {
 enum rxrpc_propose_ack_trace {
        rxrpc_propose_ack_client_tx_end,
        rxrpc_propose_ack_input_data,
+       rxrpc_propose_ack_ping_for_check_life,
        rxrpc_propose_ack_ping_for_keepalive,
        rxrpc_propose_ack_ping_for_lost_ack,
        rxrpc_propose_ack_ping_for_lost_reply,
@@ -380,6 +381,7 @@ enum rxrpc_tx_point {
 #define rxrpc_propose_ack_traces \
        EM(rxrpc_propose_ack_client_tx_end,     "ClTxEnd") \
        EM(rxrpc_propose_ack_input_data,        "DataIn ") \
+       EM(rxrpc_propose_ack_ping_for_check_life, "ChkLife") \
        EM(rxrpc_propose_ack_ping_for_keepalive, "KeepAlv") \
        EM(rxrpc_propose_ack_ping_for_lost_ack, "LostAck") \
        EM(rxrpc_propose_ack_ping_for_lost_reply, "LostRpl") \
index 51b095898f4b5952178205b5c517c7e383066164..998983a6e6b712f76b503fc8b2950554d582659f 100644 (file)
@@ -50,6 +50,8 @@
 #ifndef __LINUX_V4L2_CONTROLS_H
 #define __LINUX_V4L2_CONTROLS_H
 
+#include <linux/types.h>
+
 /* Control classes */
 #define V4L2_CTRL_CLASS_USER           0x00980000      /* Old-style 'user' controls */
 #define V4L2_CTRL_CLASS_MPEG           0x00990000      /* MPEG-compression controls */
@@ -1110,6 +1112,7 @@ struct v4l2_mpeg2_sequence {
        __u8    profile_and_level_indication;
        __u8    progressive_sequence;
        __u8    chroma_format;
+       __u8    pad;
 };
 
 struct v4l2_mpeg2_picture {
@@ -1128,6 +1131,7 @@ struct v4l2_mpeg2_picture {
        __u8    alternate_scan;
        __u8    repeat_first_field;
        __u8    progressive_frame;
+       __u8    pad;
 };
 
 struct v4l2_ctrl_mpeg2_slice_params {
@@ -1142,6 +1146,7 @@ struct v4l2_ctrl_mpeg2_slice_params {
 
        __u8    backward_ref_index;
        __u8    forward_ref_index;
+       __u8    pad;
 };
 
 struct v4l2_ctrl_mpeg2_quantization {
index 1a796e0799ec4a524aee5c325734f0ab22a410ac..b1a3545d0ec89f747d1cd51b7140fd64ad2fe6fd 100644 (file)
@@ -672,6 +672,40 @@ void __weak bpf_jit_free(struct bpf_prog *fp)
        bpf_prog_unlock_free(fp);
 }
 
+int bpf_jit_get_func_addr(const struct bpf_prog *prog,
+                         const struct bpf_insn *insn, bool extra_pass,
+                         u64 *func_addr, bool *func_addr_fixed)
+{
+       s16 off = insn->off;
+       s32 imm = insn->imm;
+       u8 *addr;
+
+       *func_addr_fixed = insn->src_reg != BPF_PSEUDO_CALL;
+       if (!*func_addr_fixed) {
+               /* Place-holder address till the last pass has collected
+                * all addresses for JITed subprograms in which case we
+                * can pick them up from prog->aux.
+                */
+               if (!extra_pass)
+                       addr = NULL;
+               else if (prog->aux->func &&
+                        off >= 0 && off < prog->aux->func_cnt)
+                       addr = (u8 *)prog->aux->func[off]->bpf_func;
+               else
+                       return -EINVAL;
+       } else {
+               /* Address of a BPF helper call. Since part of the core
+                * kernel, it's always at a fixed location. __bpf_call_base
+                * and the helper with imm relative to it are both in core
+                * kernel.
+                */
+               addr = (u8 *)__bpf_call_base + imm;
+       }
+
+       *func_addr = (unsigned long)addr;
+       return 0;
+}
+
 static int bpf_jit_blind_insn(const struct bpf_insn *from,
                              const struct bpf_insn *aux,
                              struct bpf_insn *to_buff)
index c97a8f968638c6da0c2ec32c591753f69af59e15..bed9d48a7ae9582928c0ab4c59dd931fea61f1bd 100644 (file)
@@ -139,7 +139,8 @@ static int cgroup_storage_update_elem(struct bpf_map *map, void *_key,
                return -ENOENT;
 
        new = kmalloc_node(sizeof(struct bpf_storage_buffer) +
-                          map->value_size, __GFP_ZERO | GFP_USER,
+                          map->value_size,
+                          __GFP_ZERO | GFP_ATOMIC | __GFP_NOWARN,
                           map->numa_node);
        if (!new)
                return -ENOMEM;
index 8bbd72d3a121f4e1cb75effd9c5fe5b96728a6b5..b384ea9f3254987f1caa16dff0780900720d93ca 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/bpf.h>
 #include <linux/list.h>
 #include <linux/slab.h>
+#include <linux/capability.h>
 #include "percpu_freelist.h"
 
 #define QUEUE_STACK_CREATE_FLAG_MASK \
@@ -45,8 +46,12 @@ static bool queue_stack_map_is_full(struct bpf_queue_stack *qs)
 /* Called from syscall */
 static int queue_stack_map_alloc_check(union bpf_attr *attr)
 {
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
        /* check sanity of attributes */
        if (attr->max_entries == 0 || attr->key_size != 0 ||
+           attr->value_size == 0 ||
            attr->map_flags & ~QUEUE_STACK_CREATE_FLAG_MASK)
                return -EINVAL;
 
@@ -63,15 +68,10 @@ static struct bpf_map *queue_stack_map_alloc(union bpf_attr *attr)
 {
        int ret, numa_node = bpf_map_attr_numa_node(attr);
        struct bpf_queue_stack *qs;
-       u32 size, value_size;
-       u64 queue_size, cost;
-
-       size = attr->max_entries + 1;
-       value_size = attr->value_size;
-
-       queue_size = sizeof(*qs) + (u64) value_size * size;
+       u64 size, queue_size, cost;
 
-       cost = queue_size;
+       size = (u64) attr->max_entries + 1;
+       cost = queue_size = sizeof(*qs) + size * attr->value_size;
        if (cost >= U32_MAX - PAGE_SIZE)
                return ERR_PTR(-E2BIG);
 
index 1971ca325fb4e765be7156299e7f02983687019f..6dd419550aba4b98a45ee1e5b1cf6fde4bd7c354 100644 (file)
@@ -5650,7 +5650,7 @@ static void adjust_subprog_starts(struct bpf_verifier_env *env, u32 off, u32 len
                return;
        /* NOTE: fake 'exit' subprog should be updated as well. */
        for (i = 0; i <= env->subprog_cnt; i++) {
-               if (env->subprog_info[i].start < off)
+               if (env->subprog_info[i].start <= off)
                        continue;
                env->subprog_info[i].start += len - 1;
        }
index 6ad4a9fcbd6f7012ca577070455bec9a1cd03e57..7921ae4fca8de92513fb5b71cbc36fd96ed0e04f 100644 (file)
@@ -179,14 +179,14 @@ kdb_bt(int argc, const char **argv)
                                kdb_printf("no process for cpu %ld\n", cpu);
                                return 0;
                        }
-                       sprintf(buf, "btt 0x%p\n", KDB_TSK(cpu));
+                       sprintf(buf, "btt 0x%px\n", KDB_TSK(cpu));
                        kdb_parse(buf);
                        return 0;
                }
                kdb_printf("btc: cpu status: ");
                kdb_parse("cpu\n");
                for_each_online_cpu(cpu) {
-                       sprintf(buf, "btt 0x%p\n", KDB_TSK(cpu));
+                       sprintf(buf, "btt 0x%px\n", KDB_TSK(cpu));
                        kdb_parse(buf);
                        touch_nmi_watchdog();
                }
index ed5d34925ad0617a40aeed3774b0e393aec03e99..6a4b41484afe654572f3b4f37186046c4541c8e5 100644 (file)
@@ -216,7 +216,7 @@ static char *kdb_read(char *buffer, size_t bufsize)
        int count;
        int i;
        int diag, dtab_count;
-       int key;
+       int key, buf_size, ret;
 
 
        diag = kdbgetintenv("DTABCOUNT", &dtab_count);
@@ -336,9 +336,8 @@ poll_again:
                else
                        p_tmp = tmpbuffer;
                len = strlen(p_tmp);
-               count = kallsyms_symbol_complete(p_tmp,
-                                                sizeof(tmpbuffer) -
-                                                (p_tmp - tmpbuffer));
+               buf_size = sizeof(tmpbuffer) - (p_tmp - tmpbuffer);
+               count = kallsyms_symbol_complete(p_tmp, buf_size);
                if (tab == 2 && count > 0) {
                        kdb_printf("\n%d symbols are found.", count);
                        if (count > dtab_count) {
@@ -350,9 +349,13 @@ poll_again:
                        }
                        kdb_printf("\n");
                        for (i = 0; i < count; i++) {
-                               if (WARN_ON(!kallsyms_symbol_next(p_tmp, i)))
+                               ret = kallsyms_symbol_next(p_tmp, i, buf_size);
+                               if (WARN_ON(!ret))
                                        break;
-                               kdb_printf("%s ", p_tmp);
+                               if (ret != -E2BIG)
+                                       kdb_printf("%s ", p_tmp);
+                               else
+                                       kdb_printf("%s... ", p_tmp);
                                *(p_tmp + len) = '\0';
                        }
                        if (i >= dtab_count)
index 118527aa60eae183f6d3b882ff2102a0c9a6012a..750497b0003a6decd80a97051aec97347079fd93 100644 (file)
@@ -173,11 +173,11 @@ int kdb_get_kbd_char(void)
        case KT_LATIN:
                if (isprint(keychar))
                        break;          /* printable characters */
-               /* drop through */
+               /* fall through */
        case KT_SPEC:
                if (keychar == K_ENTER)
                        break;
-               /* drop through */
+               /* fall through */
        default:
                return -1;      /* ignore unprintables */
        }
index bb4fe4e1a601b5252197f20babd6da394aaa0bc9..d72b32c66f7dd3ba3f5cf254b4d8a66da21d259d 100644 (file)
@@ -1192,7 +1192,7 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
        if (reason == KDB_REASON_DEBUG) {
                /* special case below */
        } else {
-               kdb_printf("\nEntering kdb (current=0x%p, pid %d) ",
+               kdb_printf("\nEntering kdb (current=0x%px, pid %d) ",
                           kdb_current, kdb_current ? kdb_current->pid : 0);
 #if defined(CONFIG_SMP)
                kdb_printf("on processor %d ", raw_smp_processor_id());
@@ -1208,7 +1208,7 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs,
                 */
                switch (db_result) {
                case KDB_DB_BPT:
-                       kdb_printf("\nEntering kdb (0x%p, pid %d) ",
+                       kdb_printf("\nEntering kdb (0x%px, pid %d) ",
                                   kdb_current, kdb_current->pid);
 #if defined(CONFIG_SMP)
                        kdb_printf("on processor %d ", raw_smp_processor_id());
@@ -1493,6 +1493,7 @@ static void kdb_md_line(const char *fmtstr, unsigned long addr,
        char cbuf[32];
        char *c = cbuf;
        int i;
+       int j;
        unsigned long word;
 
        memset(cbuf, '\0', sizeof(cbuf));
@@ -1538,25 +1539,9 @@ static void kdb_md_line(const char *fmtstr, unsigned long addr,
                        wc.word = word;
 #define printable_char(c) \
        ({unsigned char __c = c; isascii(__c) && isprint(__c) ? __c : '.'; })
-                       switch (bytesperword) {
-                       case 8:
+                       for (j = 0; j < bytesperword; j++)
                                *c++ = printable_char(*cp++);
-                               *c++ = printable_char(*cp++);
-                               *c++ = printable_char(*cp++);
-                               *c++ = printable_char(*cp++);
-                               addr += 4;
-                       case 4:
-                               *c++ = printable_char(*cp++);
-                               *c++ = printable_char(*cp++);
-                               addr += 2;
-                       case 2:
-                               *c++ = printable_char(*cp++);
-                               addr++;
-                       case 1:
-                               *c++ = printable_char(*cp++);
-                               addr++;
-                               break;
-                       }
+                       addr += bytesperword;
 #undef printable_char
                }
        }
@@ -2048,7 +2033,7 @@ static int kdb_lsmod(int argc, const char **argv)
                if (mod->state == MODULE_STATE_UNFORMED)
                        continue;
 
-               kdb_printf("%-20s%8u  0x%p ", mod->name,
+               kdb_printf("%-20s%8u  0x%px ", mod->name,
                           mod->core_layout.size, (void *)mod);
 #ifdef CONFIG_MODULE_UNLOAD
                kdb_printf("%4d ", module_refcount(mod));
@@ -2059,7 +2044,7 @@ static int kdb_lsmod(int argc, const char **argv)
                        kdb_printf(" (Loading)");
                else
                        kdb_printf(" (Live)");
-               kdb_printf(" 0x%p", mod->core_layout.base);
+               kdb_printf(" 0x%px", mod->core_layout.base);
 
 #ifdef CONFIG_MODULE_UNLOAD
                {
@@ -2341,7 +2326,7 @@ void kdb_ps1(const struct task_struct *p)
                return;
 
        cpu = kdb_process_cpu(p);
-       kdb_printf("0x%p %8d %8d  %d %4d   %c  0x%p %c%s\n",
+       kdb_printf("0x%px %8d %8d  %d %4d   %c  0x%px %c%s\n",
                   (void *)p, p->pid, p->parent->pid,
                   kdb_task_has_cpu(p), kdb_process_cpu(p),
                   kdb_task_state_char(p),
@@ -2354,7 +2339,7 @@ void kdb_ps1(const struct task_struct *p)
                } else {
                        if (KDB_TSK(cpu) != p)
                                kdb_printf("  Error: does not match running "
-                                  "process table (0x%p)\n", KDB_TSK(cpu));
+                                  "process table (0x%px)\n", KDB_TSK(cpu));
                }
        }
 }
@@ -2687,7 +2672,7 @@ int kdb_register_flags(char *cmd,
        for_each_kdbcmd(kp, i) {
                if (kp->cmd_name && (strcmp(kp->cmd_name, cmd) == 0)) {
                        kdb_printf("Duplicate kdb command registered: "
-                               "%s, func %p help %s\n", cmd, func, help);
+                               "%s, func %px help %s\n", cmd, func, help);
                        return 1;
                }
        }
index 1e5a502ba4a7b44787a097540cc21787cce41f5d..2118d8258b7c9a3d66b917f10575f7b109b5d665 100644 (file)
@@ -83,7 +83,7 @@ typedef struct __ksymtab {
                unsigned long sym_start;
                unsigned long sym_end;
                } kdb_symtab_t;
-extern int kallsyms_symbol_next(char *prefix_name, int flag);
+extern int kallsyms_symbol_next(char *prefix_name, int flag, int buf_size);
 extern int kallsyms_symbol_complete(char *prefix_name, int max_len);
 
 /* Exported Symbols for kernel loadable modules to use. */
index 990b3cc526c80d2162d79f0524dbd83932418cdf..50bf9b119bad04952c767451a4e29315b0234ab0 100644 (file)
@@ -40,7 +40,7 @@
 int kdbgetsymval(const char *symname, kdb_symtab_t *symtab)
 {
        if (KDB_DEBUG(AR))
-               kdb_printf("kdbgetsymval: symname=%s, symtab=%p\n", symname,
+               kdb_printf("kdbgetsymval: symname=%s, symtab=%px\n", symname,
                           symtab);
        memset(symtab, 0, sizeof(*symtab));
        symtab->sym_start = kallsyms_lookup_name(symname);
@@ -88,7 +88,7 @@ int kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
        char *knt1 = NULL;
 
        if (KDB_DEBUG(AR))
-               kdb_printf("kdbnearsym: addr=0x%lx, symtab=%p\n", addr, symtab);
+               kdb_printf("kdbnearsym: addr=0x%lx, symtab=%px\n", addr, symtab);
        memset(symtab, 0, sizeof(*symtab));
 
        if (addr < 4096)
@@ -149,7 +149,7 @@ int kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
                symtab->mod_name = "kernel";
        if (KDB_DEBUG(AR))
                kdb_printf("kdbnearsym: returns %d symtab->sym_start=0x%lx, "
-                  "symtab->mod_name=%p, symtab->sym_name=%p (%s)\n", ret,
+                  "symtab->mod_name=%px, symtab->sym_name=%px (%s)\n", ret,
                   symtab->sym_start, symtab->mod_name, symtab->sym_name,
                   symtab->sym_name);
 
@@ -221,11 +221,13 @@ int kallsyms_symbol_complete(char *prefix_name, int max_len)
  * Parameters:
  *     prefix_name     prefix of a symbol name to lookup
  *     flag    0 means search from the head, 1 means continue search.
+ *     buf_size        maximum length that can be written to prefix_name
+ *                     buffer
  * Returns:
  *     1 if a symbol matches the given prefix.
  *     0 if no string found
  */
-int kallsyms_symbol_next(char *prefix_name, int flag)
+int kallsyms_symbol_next(char *prefix_name, int flag, int buf_size)
 {
        int prefix_len = strlen(prefix_name);
        static loff_t pos;
@@ -235,10 +237,8 @@ int kallsyms_symbol_next(char *prefix_name, int flag)
                pos = 0;
 
        while ((name = kdb_walk_kallsyms(&pos))) {
-               if (strncmp(name, prefix_name, prefix_len) == 0) {
-                       strncpy(prefix_name, name, strlen(name)+1);
-                       return 1;
-               }
+               if (!strncmp(name, prefix_name, prefix_len))
+                       return strscpy(prefix_name, name, buf_size);
        }
        return 0;
 }
@@ -432,7 +432,7 @@ int kdb_getphysword(unsigned long *word, unsigned long addr, size_t size)
                                *word = w8;
                        break;
                }
-               /* drop through */
+               /* fall through */
        default:
                diag = KDB_BADWIDTH;
                kdb_printf("kdb_getphysword: bad width %ld\n", (long) size);
@@ -481,7 +481,7 @@ int kdb_getword(unsigned long *word, unsigned long addr, size_t size)
                                *word = w8;
                        break;
                }
-               /* drop through */
+               /* fall through */
        default:
                diag = KDB_BADWIDTH;
                kdb_printf("kdb_getword: bad width %ld\n", (long) size);
@@ -525,7 +525,7 @@ int kdb_putword(unsigned long addr, unsigned long word, size_t size)
                        diag = kdb_putarea(addr, w8);
                        break;
                }
-               /* drop through */
+               /* fall through */
        default:
                diag = KDB_BADWIDTH;
                kdb_printf("kdb_putword: bad width %ld\n", (long) size);
@@ -887,13 +887,13 @@ void debug_kusage(void)
                   __func__, dah_first);
        if (dah_first) {
                h_used = (struct debug_alloc_header *)debug_alloc_pool;
-               kdb_printf("%s: h_used %p size %d\n", __func__, h_used,
+               kdb_printf("%s: h_used %px size %d\n", __func__, h_used,
                           h_used->size);
        }
        do {
                h_used = (struct debug_alloc_header *)
                          ((char *)h_free + dah_overhead + h_free->size);
-               kdb_printf("%s: h_used %p size %d caller %p\n",
+               kdb_printf("%s: h_used %px size %d caller %px\n",
                           __func__, h_used, h_used->size, h_used->caller);
                h_free = (struct debug_alloc_header *)
                          (debug_alloc_pool + h_free->next);
@@ -902,7 +902,7 @@ void debug_kusage(void)
                  ((char *)h_free + dah_overhead + h_free->size);
        if ((char *)h_used - debug_alloc_pool !=
            sizeof(debug_alloc_pool_aligned))
-               kdb_printf("%s: h_used %p size %d caller %p\n",
+               kdb_printf("%s: h_used %px size %d caller %px\n",
                           __func__, h_used, h_used->size, h_used->caller);
 out:
        spin_unlock(&dap_lock);
index 3648d0300fdf98b45702a42d0d672d38c97c3be7..ac855b2f47746efa80ed91081442626d15169568 100644 (file)
@@ -5674,11 +5674,11 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p,
        return target;
 }
 
-static unsigned long cpu_util_wake(int cpu, struct task_struct *p);
+static unsigned long cpu_util_without(int cpu, struct task_struct *p);
 
-static unsigned long capacity_spare_wake(int cpu, struct task_struct *p)
+static unsigned long capacity_spare_without(int cpu, struct task_struct *p)
 {
-       return max_t(long, capacity_of(cpu) - cpu_util_wake(cpu, p), 0);
+       return max_t(long, capacity_of(cpu) - cpu_util_without(cpu, p), 0);
 }
 
 /*
@@ -5738,7 +5738,7 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
 
                        avg_load += cfs_rq_load_avg(&cpu_rq(i)->cfs);
 
-                       spare_cap = capacity_spare_wake(i, p);
+                       spare_cap = capacity_spare_without(i, p);
 
                        if (spare_cap > max_spare_cap)
                                max_spare_cap = spare_cap;
@@ -5889,8 +5889,8 @@ static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p
                return prev_cpu;
 
        /*
-        * We need task's util for capacity_spare_wake, sync it up to prev_cpu's
-        * last_update_time.
+        * We need task's util for capacity_spare_without, sync it up to
+        * prev_cpu's last_update_time.
         */
        if (!(sd_flag & SD_BALANCE_FORK))
                sync_entity_load_avg(&p->se);
@@ -6216,10 +6216,19 @@ static inline unsigned long cpu_util(int cpu)
 }
 
 /*
- * cpu_util_wake: Compute CPU utilization with any contributions from
- * the waking task p removed.
+ * cpu_util_without: compute cpu utilization without any contributions from *p
+ * @cpu: the CPU which utilization is requested
+ * @p: the task which utilization should be discounted
+ *
+ * The utilization of a CPU is defined by the utilization of tasks currently
+ * enqueued on that CPU as well as tasks which are currently sleeping after an
+ * execution on that CPU.
+ *
+ * This method returns the utilization of the specified CPU by discounting the
+ * utilization of the specified task, whenever the task is currently
+ * contributing to the CPU utilization.
  */
-static unsigned long cpu_util_wake(int cpu, struct task_struct *p)
+static unsigned long cpu_util_without(int cpu, struct task_struct *p)
 {
        struct cfs_rq *cfs_rq;
        unsigned int util;
@@ -6231,7 +6240,7 @@ static unsigned long cpu_util_wake(int cpu, struct task_struct *p)
        cfs_rq = &cpu_rq(cpu)->cfs;
        util = READ_ONCE(cfs_rq->avg.util_avg);
 
-       /* Discount task's blocked util from CPU's util */
+       /* Discount task's util from CPU's util */
        util -= min_t(unsigned int, util, task_util(p));
 
        /*
@@ -6240,14 +6249,14 @@ static unsigned long cpu_util_wake(int cpu, struct task_struct *p)
         * a) if *p is the only task sleeping on this CPU, then:
         *      cpu_util (== task_util) > util_est (== 0)
         *    and thus we return:
-        *      cpu_util_wake = (cpu_util - task_util) = 0
+        *      cpu_util_without = (cpu_util - task_util) = 0
         *
         * b) if other tasks are SLEEPING on this CPU, which is now exiting
         *    IDLE, then:
         *      cpu_util >= task_util
         *      cpu_util > util_est (== 0)
         *    and thus we discount *p's blocked utilization to return:
-        *      cpu_util_wake = (cpu_util - task_util) >= 0
+        *      cpu_util_without = (cpu_util - task_util) >= 0
         *
         * c) if other tasks are RUNNABLE on that CPU and
         *      util_est > cpu_util
@@ -6260,8 +6269,33 @@ static unsigned long cpu_util_wake(int cpu, struct task_struct *p)
         * covered by the following code when estimated utilization is
         * enabled.
         */
-       if (sched_feat(UTIL_EST))
-               util = max(util, READ_ONCE(cfs_rq->avg.util_est.enqueued));
+       if (sched_feat(UTIL_EST)) {
+               unsigned int estimated =
+                       READ_ONCE(cfs_rq->avg.util_est.enqueued);
+
+               /*
+                * Despite the following checks we still have a small window
+                * for a possible race, when an execl's select_task_rq_fair()
+                * races with LB's detach_task():
+                *
+                *   detach_task()
+                *     p->on_rq = TASK_ON_RQ_MIGRATING;
+                *     ---------------------------------- A
+                *     deactivate_task()                   \
+                *       dequeue_task()                     + RaceTime
+                *         util_est_dequeue()              /
+                *     ---------------------------------- B
+                *
+                * The additional check on "current == p" it's required to
+                * properly fix the execl regression and it helps in further
+                * reducing the chances for the above race.
+                */
+               if (unlikely(task_on_rq_queued(p) || current == p)) {
+                       estimated -= min_t(unsigned int, estimated,
+                                          (_task_util_est(p) | UTIL_AVG_UNCHANGED));
+               }
+               util = max(util, estimated);
+       }
 
        /*
         * Utilization (estimated) can exceed the CPU capacity, thus let's
index 7cdecfc010af83f1f5d8679536433f288aa847d7..3d7355d7c3e3852a085a2d68de6e7bbc705c5071 100644 (file)
@@ -633,38 +633,39 @@ void psi_cgroup_free(struct cgroup *cgroup)
  */
 void cgroup_move_task(struct task_struct *task, struct css_set *to)
 {
-       bool move_psi = !psi_disabled;
        unsigned int task_flags = 0;
        struct rq_flags rf;
        struct rq *rq;
 
-       if (move_psi) {
-               rq = task_rq_lock(task, &rf);
+       if (psi_disabled) {
+               /*
+                * Lame to do this here, but the scheduler cannot be locked
+                * from the outside, so we move cgroups from inside sched/.
+                */
+               rcu_assign_pointer(task->cgroups, to);
+               return;
+       }
 
-               if (task_on_rq_queued(task))
-                       task_flags = TSK_RUNNING;
-               else if (task->in_iowait)
-                       task_flags = TSK_IOWAIT;
+       rq = task_rq_lock(task, &rf);
 
-               if (task->flags & PF_MEMSTALL)
-                       task_flags |= TSK_MEMSTALL;
+       if (task_on_rq_queued(task))
+               task_flags = TSK_RUNNING;
+       else if (task->in_iowait)
+               task_flags = TSK_IOWAIT;
 
-               if (task_flags)
-                       psi_task_change(task, task_flags, 0);
-       }
+       if (task->flags & PF_MEMSTALL)
+               task_flags |= TSK_MEMSTALL;
 
-       /*
-        * Lame to do this here, but the scheduler cannot be locked
-        * from the outside, so we move cgroups from inside sched/.
-        */
+       if (task_flags)
+               psi_task_change(task, task_flags, 0);
+
+       /* See comment above */
        rcu_assign_pointer(task->cgroups, to);
 
-       if (move_psi) {
-               if (task_flags)
-                       psi_task_change(task, 0, task_flags);
+       if (task_flags)
+               psi_task_change(task, 0, task_flags);
 
-               task_rq_unlock(rq, task, &rf);
-       }
+       task_rq_unlock(rq, task, &rf);
 }
 #endif /* CONFIG_CGROUPS */
 
index 08fcfe440c6374e336b02c1dde33a478fc58615a..9864a35c8bb576e30655bccf62e5174cb1591072 100644 (file)
@@ -196,11 +196,13 @@ BPF_CALL_5(bpf_trace_printk, char *, fmt, u32, fmt_size, u64, arg1,
                        i++;
                } else if (fmt[i] == 'p' || fmt[i] == 's') {
                        mod[fmt_cnt]++;
-                       i++;
-                       if (!isspace(fmt[i]) && !ispunct(fmt[i]) && fmt[i] != 0)
+                       /* disallow any further format extensions */
+                       if (fmt[i + 1] != 0 &&
+                           !isspace(fmt[i + 1]) &&
+                           !ispunct(fmt[i + 1]))
                                return -EINVAL;
                        fmt_cnt++;
-                       if (fmt[i - 1] == 's') {
+                       if (fmt[i] == 's') {
                                if (str_seen)
                                        /* allow only one '%s' per fmt string */
                                        return -EINVAL;
index b984806d7d7bb1f4665ffe6cecfa5849aecc8c22..7cab9a9869ace92900ec58aabffa175d2249296d 100644 (file)
@@ -837,6 +837,7 @@ static ssize_t read_firmware_show(struct device *dev,
        if (req->fw->size > PAGE_SIZE) {
                pr_err("Testing interface must use PAGE_SIZE firmware for now\n");
                rc = -EINVAL;
+               goto out;
        }
        memcpy(buf, req->fw->data, req->fw->size);
 
index 59fee96c29a0f1fb83fe67282482bc5d941bd6f3..e4162f59a81ccacda275cd218193fb2ad34d71d3 100644 (file)
@@ -427,8 +427,7 @@ void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data,
 EXPORT_SYMBOL(__ubsan_handle_shift_out_of_bounds);
 
 
-void __noreturn
-__ubsan_handle_builtin_unreachable(struct unreachable_data *data)
+void __ubsan_handle_builtin_unreachable(struct unreachable_data *data)
 {
        unsigned long flags;
 
index f76e77a2d34b79afec5f3032366a6bd954d1aead..aa43620a3270ec08040f75e587d4cbe7617754ff 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -385,11 +385,17 @@ static struct page *follow_p4d_mask(struct vm_area_struct *vma,
  * @vma: vm_area_struct mapping @address
  * @address: virtual address to look up
  * @flags: flags modifying lookup behaviour
- * @page_mask: on output, *page_mask is set according to the size of the page
+ * @ctx: contains dev_pagemap for %ZONE_DEVICE memory pinning and a
+ *       pointer to output page_mask
  *
  * @flags can have FOLL_ flags set, defined in <linux/mm.h>
  *
- * Returns the mapped (struct page *), %NULL if no mapping exists, or
+ * When getting pages from ZONE_DEVICE memory, the @ctx->pgmap caches
+ * the device's dev_pagemap metadata to avoid repeating expensive lookups.
+ *
+ * On output, the @ctx->page_mask is set according to the size of the page.
+ *
+ * Return: the mapped (struct page *), %NULL if no mapping exists, or
  * an error pointer if there is a mapping to something not represented
  * by a page descriptor (see also vm_normal_page()).
  */
index c007fb5fb8d5f6547dc916e5ab468753028a862b..7f2a28ab46d537ff4ed5034cce0ea46b95991477 100644 (file)
@@ -3233,7 +3233,7 @@ static int is_hugetlb_entry_hwpoisoned(pte_t pte)
 int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
                            struct vm_area_struct *vma)
 {
-       pte_t *src_pte, *dst_pte, entry;
+       pte_t *src_pte, *dst_pte, entry, dst_entry;
        struct page *ptepage;
        unsigned long addr;
        int cow;
@@ -3261,15 +3261,30 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
                        break;
                }
 
-               /* If the pagetables are shared don't copy or take references */
-               if (dst_pte == src_pte)
+               /*
+                * If the pagetables are shared don't copy or take references.
+                * dst_pte == src_pte is the common case of src/dest sharing.
+                *
+                * However, src could have 'unshared' and dst shares with
+                * another vma.  If dst_pte !none, this implies sharing.
+                * Check here before taking page table lock, and once again
+                * after taking the lock below.
+                */
+               dst_entry = huge_ptep_get(dst_pte);
+               if ((dst_pte == src_pte) || !huge_pte_none(dst_entry))
                        continue;
 
                dst_ptl = huge_pte_lock(h, dst, dst_pte);
                src_ptl = huge_pte_lockptr(h, src, src_pte);
                spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
                entry = huge_ptep_get(src_pte);
-               if (huge_pte_none(entry)) { /* skip none entry */
+               dst_entry = huge_ptep_get(dst_pte);
+               if (huge_pte_none(entry) || !huge_pte_none(dst_entry)) {
+                       /*
+                        * Skip if src entry none.  Also, skip in the
+                        * unlikely case dst entry !none as this implies
+                        * sharing with another vma.
+                        */
                        ;
                } else if (unlikely(is_hugetlb_entry_migration(entry) ||
                                    is_hugetlb_entry_hwpoisoned(entry))) {
index 7df468c8ebc8c0ada5b560ed70c9c821e5127c05..9a2d5ae81ae1cf4217ed3174d72667be276769da 100644 (file)
@@ -1179,7 +1179,7 @@ void __init_memblock __next_mem_range_rev(u64 *idx, int nid,
 
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 /*
- * Common iterator interface used to define for_each_mem_range().
+ * Common iterator interface used to define for_each_mem_pfn_range().
  */
 void __init_memblock __next_mem_pfn_range(int *idx, int nid,
                                unsigned long *out_start_pfn,
index a919ba5cb3c845e03e4a070eff354acf19ec7c4a..6847177dc4a1a89ce098c6ab6f4b19e46dab2428 100644 (file)
@@ -4060,17 +4060,6 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
        unsigned int cpuset_mems_cookie;
        int reserve_flags;
 
-       /*
-        * In the slowpath, we sanity check order to avoid ever trying to
-        * reclaim >= MAX_ORDER areas which will never succeed. Callers may
-        * be using allocators in order of preference for an area that is
-        * too large.
-        */
-       if (order >= MAX_ORDER) {
-               WARN_ON_ONCE(!(gfp_mask & __GFP_NOWARN));
-               return NULL;
-       }
-
        /*
         * We also sanity check to catch abuse of atomic reserves being used by
         * callers that are not in atomic context.
@@ -4364,6 +4353,15 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, int preferred_nid,
        gfp_t alloc_mask; /* The gfp_t that was actually used for allocation */
        struct alloc_context ac = { };
 
+       /*
+        * There are several places where we assume that the order value is sane
+        * so bail out early if the request is out of bound.
+        */
+       if (unlikely(order >= MAX_ORDER)) {
+               WARN_ON_ONCE(!(gfp_mask & __GFP_NOWARN));
+               return NULL;
+       }
+
        gfp_mask &= gfp_allowed_mask;
        alloc_mask = gfp_mask;
        if (!prepare_alloc_pages(gfp_mask, order, preferred_nid, nodemask, &ac, &alloc_mask, &alloc_flags))
@@ -7788,6 +7786,14 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
                if (PageReserved(page))
                        goto unmovable;
 
+               /*
+                * If the zone is movable and we have ruled out all reserved
+                * pages then it should be reasonably safe to assume the rest
+                * is movable.
+                */
+               if (zone_idx(zone) == ZONE_MOVABLE)
+                       continue;
+
                /*
                 * Hugepages are not in LRU lists, but they're movable.
                 * We need not scan over tail pages bacause we don't
index ea26d7a0342d77ac67f47e813a73f125c873a1e5..d44991ea5ed4b7612482525ebaa502457cbf1ead 100644 (file)
@@ -2563,9 +2563,7 @@ static loff_t shmem_file_llseek(struct file *file, loff_t offset, int whence)
        inode_lock(inode);
        /* We're holding i_mutex so we can access i_size directly */
 
-       if (offset < 0)
-               offset = -EINVAL;
-       else if (offset >= inode->i_size)
+       if (offset < 0 || offset >= inode->i_size)
                offset = -ENXIO;
        else {
                start = offset >> PAGE_SHIFT;
index 644f746e167acd65e8244088f483e50c71afbf20..8688ae65ef58ac639b0b2202039fa22577309350 100644 (file)
@@ -2813,7 +2813,7 @@ static struct swap_info_struct *alloc_swap_info(void)
        unsigned int type;
        int i;
 
-       p = kzalloc(sizeof(*p), GFP_KERNEL);
+       p = kvzalloc(sizeof(*p), GFP_KERNEL);
        if (!p)
                return ERR_PTR(-ENOMEM);
 
@@ -2824,7 +2824,7 @@ static struct swap_info_struct *alloc_swap_info(void)
        }
        if (type >= MAX_SWAPFILES) {
                spin_unlock(&swap_lock);
-               kfree(p);
+               kvfree(p);
                return ERR_PTR(-EPERM);
        }
        if (type >= nr_swapfiles) {
@@ -2838,7 +2838,7 @@ static struct swap_info_struct *alloc_swap_info(void)
                smp_wmb();
                nr_swapfiles++;
        } else {
-               kfree(p);
+               kvfree(p);
                p = swap_info[type];
                /*
                 * Do not memset this entry: a racing procfs swap_next()
index 6038ce593ce3e1ca4cce34a02bc0bbd4c1d3a296..9c624595e90416bc9114fc11721e14d56183a1b6 100644 (file)
@@ -1827,12 +1827,13 @@ static bool need_update(int cpu)
 
                /*
                 * The fast way of checking if there are any vmstat diffs.
-                * This works because the diffs are byte sized items.
                 */
-               if (memchr_inv(p->vm_stat_diff, 0, NR_VM_ZONE_STAT_ITEMS))
+               if (memchr_inv(p->vm_stat_diff, 0, NR_VM_ZONE_STAT_ITEMS *
+                              sizeof(p->vm_stat_diff[0])))
                        return true;
 #ifdef CONFIG_NUMA
-               if (memchr_inv(p->vm_numa_stat_diff, 0, NR_VM_NUMA_STAT_ITEMS))
+               if (memchr_inv(p->vm_numa_stat_diff, 0, NR_VM_NUMA_STAT_ITEMS *
+                              sizeof(p->vm_numa_stat_diff[0])))
                        return true;
 #endif
        }
index 4b366d181f35d12f9a1e600bb7083bbf4dfe7fff..aee9b0b8d9078a0bbf59a06509c6f7f7aa1360f3 100644 (file)
@@ -99,6 +99,7 @@ struct z3fold_header {
 #define NCHUNKS                ((PAGE_SIZE - ZHDR_SIZE_ALIGNED) >> CHUNK_SHIFT)
 
 #define BUDDY_MASK     (0x3)
+#define BUDDY_SHIFT    2
 
 /**
  * struct z3fold_pool - stores metadata for each z3fold pool
@@ -145,7 +146,7 @@ enum z3fold_page_flags {
        MIDDLE_CHUNK_MAPPED,
        NEEDS_COMPACTING,
        PAGE_STALE,
-       UNDER_RECLAIM
+       PAGE_CLAIMED, /* by either reclaim or free */
 };
 
 /*****************
@@ -174,7 +175,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);
+       clear_bit(PAGE_CLAIMED, &page->private);
 
        spin_lock_init(&zhdr->page_lock);
        kref_init(&zhdr->refcount);
@@ -223,8 +224,11 @@ static unsigned long encode_handle(struct z3fold_header *zhdr, enum buddy bud)
        unsigned long handle;
 
        handle = (unsigned long)zhdr;
-       if (bud != HEADLESS)
-               handle += (bud + zhdr->first_num) & BUDDY_MASK;
+       if (bud != HEADLESS) {
+               handle |= (bud + zhdr->first_num) & BUDDY_MASK;
+               if (bud == LAST)
+                       handle |= (zhdr->last_chunks << BUDDY_SHIFT);
+       }
        return handle;
 }
 
@@ -234,6 +238,12 @@ static struct z3fold_header *handle_to_z3fold_header(unsigned long handle)
        return (struct z3fold_header *)(handle & PAGE_MASK);
 }
 
+/* only for LAST bud, returns zero otherwise */
+static unsigned short handle_to_chunks(unsigned long handle)
+{
+       return (handle & ~PAGE_MASK) >> BUDDY_SHIFT;
+}
+
 /*
  * (handle & BUDDY_MASK) < zhdr->first_num is possible in encode_handle
  *  but that doesn't matter. because the masking will result in the
@@ -720,37 +730,39 @@ static void z3fold_free(struct z3fold_pool *pool, unsigned long handle)
        page = virt_to_page(zhdr);
 
        if (test_bit(PAGE_HEADLESS, &page->private)) {
-               /* HEADLESS page stored */
-               bud = HEADLESS;
-       } else {
-               z3fold_page_lock(zhdr);
-               bud = handle_to_buddy(handle);
-
-               switch (bud) {
-               case FIRST:
-                       zhdr->first_chunks = 0;
-                       break;
-               case MIDDLE:
-                       zhdr->middle_chunks = 0;
-                       zhdr->start_middle = 0;
-                       break;
-               case LAST:
-                       zhdr->last_chunks = 0;
-                       break;
-               default:
-                       pr_err("%s: unknown bud %d\n", __func__, bud);
-                       WARN_ON(1);
-                       z3fold_page_unlock(zhdr);
-                       return;
+               /* if a headless page is under reclaim, just leave.
+                * NB: we use test_and_set_bit for a reason: if the bit
+                * has not been set before, we release this page
+                * immediately so we don't care about its value any more.
+                */
+               if (!test_and_set_bit(PAGE_CLAIMED, &page->private)) {
+                       spin_lock(&pool->lock);
+                       list_del(&page->lru);
+                       spin_unlock(&pool->lock);
+                       free_z3fold_page(page);
+                       atomic64_dec(&pool->pages_nr);
                }
+               return;
        }
 
-       if (bud == HEADLESS) {
-               spin_lock(&pool->lock);
-               list_del(&page->lru);
-               spin_unlock(&pool->lock);
-               free_z3fold_page(page);
-               atomic64_dec(&pool->pages_nr);
+       /* Non-headless case */
+       z3fold_page_lock(zhdr);
+       bud = handle_to_buddy(handle);
+
+       switch (bud) {
+       case FIRST:
+               zhdr->first_chunks = 0;
+               break;
+       case MIDDLE:
+               zhdr->middle_chunks = 0;
+               break;
+       case LAST:
+               zhdr->last_chunks = 0;
+               break;
+       default:
+               pr_err("%s: unknown bud %d\n", __func__, bud);
+               WARN_ON(1);
+               z3fold_page_unlock(zhdr);
                return;
        }
 
@@ -758,7 +770,7 @@ static void z3fold_free(struct z3fold_pool *pool, unsigned long handle)
                atomic64_dec(&pool->pages_nr);
                return;
        }
-       if (test_bit(UNDER_RECLAIM, &page->private)) {
+       if (test_bit(PAGE_CLAIMED, &page->private)) {
                z3fold_page_unlock(zhdr);
                return;
        }
@@ -836,20 +848,30 @@ static int z3fold_reclaim_page(struct z3fold_pool *pool, unsigned int retries)
                }
                list_for_each_prev(pos, &pool->lru) {
                        page = list_entry(pos, struct page, lru);
+
+                       /* this bit could have been set by free, in which case
+                        * we pass over to the next page in the pool.
+                        */
+                       if (test_and_set_bit(PAGE_CLAIMED, &page->private))
+                               continue;
+
+                       zhdr = page_address(page);
                        if (test_bit(PAGE_HEADLESS, &page->private))
-                               /* candidate found */
                                break;
 
-                       zhdr = page_address(page);
-                       if (!z3fold_page_trylock(zhdr))
+                       if (!z3fold_page_trylock(zhdr)) {
+                               zhdr = NULL;
                                continue; /* can't evict at this point */
+                       }
                        kref_get(&zhdr->refcount);
                        list_del_init(&zhdr->buddy);
                        zhdr->cpu = -1;
-                       set_bit(UNDER_RECLAIM, &page->private);
                        break;
                }
 
+               if (!zhdr)
+                       break;
+
                list_del_init(&page->lru);
                spin_unlock(&pool->lock);
 
@@ -898,6 +920,7 @@ next:
                if (test_bit(PAGE_HEADLESS, &page->private)) {
                        if (ret == 0) {
                                free_z3fold_page(page);
+                               atomic64_dec(&pool->pages_nr);
                                return 0;
                        }
                        spin_lock(&pool->lock);
@@ -905,7 +928,7 @@ next:
                        spin_unlock(&pool->lock);
                } else {
                        z3fold_page_lock(zhdr);
-                       clear_bit(UNDER_RECLAIM, &page->private);
+                       clear_bit(PAGE_CLAIMED, &page->private);
                        if (kref_put(&zhdr->refcount,
                                        release_z3fold_page_locked)) {
                                atomic64_dec(&pool->pages_nr);
@@ -964,7 +987,7 @@ static void *z3fold_map(struct z3fold_pool *pool, unsigned long handle)
                set_bit(MIDDLE_CHUNK_MAPPED, &page->private);
                break;
        case LAST:
-               addr += PAGE_SIZE - (zhdr->last_chunks << CHUNK_SHIFT);
+               addr += PAGE_SIZE - (handle_to_chunks(handle) << CHUNK_SHIFT);
                break;
        default:
                pr_err("unknown buddy id %d\n", buddy);
index 9f481cfdf77dace2fa594585fde5079d46474c66..e8090f099eb805626ffaa1445d3d0f8254f6c9a7 100644 (file)
@@ -352,19 +352,21 @@ out:
  */
 int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface)
 {
+       static const size_t tvlv_padding = sizeof(__be32);
        struct batadv_elp_packet *elp_packet;
        unsigned char *elp_buff;
        u32 random_seqno;
        size_t size;
        int res = -ENOMEM;
 
-       size = ETH_HLEN + NET_IP_ALIGN + BATADV_ELP_HLEN;
+       size = ETH_HLEN + NET_IP_ALIGN + BATADV_ELP_HLEN + tvlv_padding;
        hard_iface->bat_v.elp_skb = dev_alloc_skb(size);
        if (!hard_iface->bat_v.elp_skb)
                goto out;
 
        skb_reserve(hard_iface->bat_v.elp_skb, ETH_HLEN + NET_IP_ALIGN);
-       elp_buff = skb_put_zero(hard_iface->bat_v.elp_skb, BATADV_ELP_HLEN);
+       elp_buff = skb_put_zero(hard_iface->bat_v.elp_skb,
+                               BATADV_ELP_HLEN + tvlv_padding);
        elp_packet = (struct batadv_elp_packet *)elp_buff;
 
        elp_packet->packet_type = BATADV_ELP;
index 0fddc17106bd8a0e3f064fee9adba7c226f34682..5b71a289d04fc80de6c20e7a24d621727c77825a 100644 (file)
@@ -275,7 +275,7 @@ batadv_frag_merge_packets(struct hlist_head *chain)
        kfree(entry);
 
        packet = (struct batadv_frag_packet *)skb_out->data;
-       size = ntohs(packet->total_size);
+       size = ntohs(packet->total_size) + hdr_size;
 
        /* Make room for the rest of the fragments. */
        if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) {
index 2920e06a540329ffb8f1286c65bc5acc6f53afad..04c19a37e500e872d564497c9410509c0df61fce 100644 (file)
@@ -102,12 +102,18 @@ struct br_tunnel_info {
        struct metadata_dst     *tunnel_dst;
 };
 
+/* private vlan flags */
+enum {
+       BR_VLFLAG_PER_PORT_STATS = BIT(0),
+};
+
 /**
  * struct net_bridge_vlan - per-vlan entry
  *
  * @vnode: rhashtable member
  * @vid: VLAN id
  * @flags: bridge vlan flags
+ * @priv_flags: private (in-kernel) bridge vlan flags
  * @stats: per-cpu VLAN statistics
  * @br: if MASTER flag set, this points to a bridge struct
  * @port: if MASTER flag unset, this points to a port struct
@@ -127,6 +133,7 @@ struct net_bridge_vlan {
        struct rhash_head               tnode;
        u16                             vid;
        u16                             flags;
+       u16                             priv_flags;
        struct br_vlan_stats __percpu   *stats;
        union {
                struct net_bridge       *br;
index 8c9297a019475fe68ee110a85cda1647deaf9075..e84be08b82854916d91bc0195ad2a9ab7dae8564 100644 (file)
@@ -197,7 +197,7 @@ static void nbp_vlan_rcu_free(struct rcu_head *rcu)
        v = container_of(rcu, struct net_bridge_vlan, rcu);
        WARN_ON(br_vlan_is_master(v));
        /* if we had per-port stats configured then free them here */
-       if (v->brvlan->stats != v->stats)
+       if (v->priv_flags & BR_VLFLAG_PER_PORT_STATS)
                free_percpu(v->stats);
        v->stats = NULL;
        kfree(v);
@@ -264,6 +264,7 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags)
                                err = -ENOMEM;
                                goto out_filt;
                        }
+                       v->priv_flags |= BR_VLFLAG_PER_PORT_STATS;
                } else {
                        v->stats = masterv->stats;
                }
index 1051eee8258184f33d15a6142ee8b387839c9adc..3aab7664933fdc67770cdbc8b80a231b41dc2555 100644 (file)
@@ -745,18 +745,19 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
        } else
                ifindex = ro->ifindex;
 
-       if (ro->fd_frames) {
+       dev = dev_get_by_index(sock_net(sk), ifindex);
+       if (!dev)
+               return -ENXIO;
+
+       err = -EINVAL;
+       if (ro->fd_frames && dev->mtu == CANFD_MTU) {
                if (unlikely(size != CANFD_MTU && size != CAN_MTU))
-                       return -EINVAL;
+                       goto put_dev;
        } else {
                if (unlikely(size != CAN_MTU))
-                       return -EINVAL;
+                       goto put_dev;
        }
 
-       dev = dev_get_by_index(sock_net(sk), ifindex);
-       if (!dev)
-               return -ENXIO;
-
        skb = sock_alloc_send_skb(sk, size + sizeof(struct can_skb_priv),
                                  msg->msg_flags & MSG_DONTWAIT, &err);
        if (!skb)
index 57fcc6b4bf6e1d6c33796868e5b816afcd3d235f..2f126eff275d58417d2397b15e7fcef2351cdde5 100644 (file)
@@ -580,9 +580,15 @@ static int ceph_tcp_sendpage(struct socket *sock, struct page *page,
        struct bio_vec bvec;
        int ret;
 
-       /* sendpage cannot properly handle pages with page_count == 0,
-        * we need to fallback to sendmsg if that's the case */
-       if (page_count(page) >= 1)
+       /*
+        * sendpage cannot properly handle pages with page_count == 0,
+        * we need to fall back to sendmsg if that's the case.
+        *
+        * Same goes for slab pages: skb_can_coalesce() allows
+        * coalescing neighboring slab objects into a single frag which
+        * triggers one of hardened usercopy checks.
+        */
+       if (page_count(page) >= 1 && !PageSlab(page))
                return __ceph_tcp_sendpage(sock, page, offset, size, more);
 
        bvec.bv_page = page;
index 0ffcbdd55fa9ee545c807f2ed3fc178830e3075a..ddc551f24ba2afc4cfd9f11826602f92945ff871 100644 (file)
@@ -5655,6 +5655,10 @@ static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb)
        skb->vlan_tci = 0;
        skb->dev = napi->dev;
        skb->skb_iif = 0;
+
+       /* eth_type_trans() assumes pkt_type is PACKET_HOST */
+       skb->pkt_type = PACKET_HOST;
+
        skb->encapsulation = 0;
        skb_shinfo(skb)->gso_type = 0;
        skb->truesize = SKB_TRUESIZE(skb_end_offset(skb));
@@ -5966,11 +5970,14 @@ bool napi_complete_done(struct napi_struct *n, int work_done)
                if (work_done)
                        timeout = n->dev->gro_flush_timeout;
 
+               /* When the NAPI instance uses a timeout and keeps postponing
+                * it, we need to bound somehow the time packets are kept in
+                * the GRO layer
+                */
+               napi_gro_flush(n, !!timeout);
                if (timeout)
                        hrtimer_start(&n->timer, ns_to_ktime(timeout),
                                      HRTIMER_MODE_REL_PINNED);
-               else
-                       napi_gro_flush(n, false);
        }
        if (unlikely(!list_empty(&n->poll_list))) {
                /* If n->poll_list is not empty, we need to mask irqs */
index e521c5ebc7d11cdfdcc10307ad973bcac2d1602a..9a1327eb25faf2c73a37d253f88b19c6b92414d6 100644 (file)
@@ -4852,18 +4852,17 @@ static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple,
        } else {
                struct in6_addr *src6 = (struct in6_addr *)&tuple->ipv6.saddr;
                struct in6_addr *dst6 = (struct in6_addr *)&tuple->ipv6.daddr;
-               u16 hnum = ntohs(tuple->ipv6.dport);
                int sdif = inet6_sdif(skb);
 
                if (proto == IPPROTO_TCP)
                        sk = __inet6_lookup(net, &tcp_hashinfo, skb, 0,
                                            src6, tuple->ipv6.sport,
-                                           dst6, hnum,
+                                           dst6, ntohs(tuple->ipv6.dport),
                                            dif, sdif, &refcounted);
                else if (likely(ipv6_bpf_stub))
                        sk = ipv6_bpf_stub->udp6_lib_lookup(net,
                                                            src6, tuple->ipv6.sport,
-                                                           dst6, hnum,
+                                                           dst6, tuple->ipv6.dport,
                                                            dif, sdif,
                                                            &udp_table, skb);
 #endif
index b4ee5c8b928f07879b3c7ed08ed5e9b67b08fcb4..a8217e221e1954871f15d6ba160538939d9b53ff 100644 (file)
@@ -4854,6 +4854,11 @@ void skb_scrub_packet(struct sk_buff *skb, bool xnet)
        nf_reset(skb);
        nf_reset_trace(skb);
 
+#ifdef CONFIG_NET_SWITCHDEV
+       skb->offload_fwd_mark = 0;
+       skb->offload_mr_fwd_mark = 0;
+#endif
+
        if (!xnet)
                return;
 
index c09219e7f23048636836d52daf748bf7e81369e1..5dbec21856f4ce458af136bfe5ef1c0c84a4f8a5 100644 (file)
@@ -939,7 +939,7 @@ static int __ip_append_data(struct sock *sk,
                        unsigned int fraglen;
                        unsigned int fraggap;
                        unsigned int alloclen;
-                       unsigned int pagedlen = 0;
+                       unsigned int pagedlen;
                        struct sk_buff *skb_prev;
 alloc_new_skb:
                        skb_prev = skb;
@@ -956,6 +956,7 @@ alloc_new_skb:
                        if (datalen > mtu - fragheaderlen)
                                datalen = maxfraglen - fragheaderlen;
                        fraglen = datalen + fragheaderlen;
+                       pagedlen = 0;
 
                        if ((flags & MSG_MORE) &&
                            !(rt->dst.dev->features&NETIF_F_SG))
index dde671e978298b5b0239f975fe134b232db9049b..c248e0dccbe17afa397910b0d68260daf2a9eb3f 100644 (file)
@@ -80,7 +80,7 @@ void iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb,
 
        iph->version    =       4;
        iph->ihl        =       sizeof(struct iphdr) >> 2;
-       iph->frag_off   =       df;
+       iph->frag_off   =       ip_mtu_locked(&rt->dst) ? 0 : df;
        iph->protocol   =       proto;
        iph->tos        =       tos;
        iph->daddr      =       dst;
index 2868ef28ce52179b3c5874e749b680ffbdc0521a..a9d9555a973fed4e3562a57d1a2cdadfef40dae4 100644 (file)
@@ -579,10 +579,12 @@ static inline void tcp_rcv_rtt_measure_ts(struct sock *sk,
                u32 delta = tcp_time_stamp(tp) - tp->rx_opt.rcv_tsecr;
                u32 delta_us;
 
-               if (!delta)
-                       delta = 1;
-               delta_us = delta * (USEC_PER_SEC / TCP_TS_HZ);
-               tcp_rcv_rtt_update(tp, delta_us, 0);
+               if (likely(delta < INT_MAX / (USEC_PER_SEC / TCP_TS_HZ))) {
+                       if (!delta)
+                               delta = 1;
+                       delta_us = delta * (USEC_PER_SEC / TCP_TS_HZ);
+                       tcp_rcv_rtt_update(tp, delta_us, 0);
+               }
        }
 }
 
@@ -2910,9 +2912,11 @@ static bool tcp_ack_update_rtt(struct sock *sk, const int flag,
        if (seq_rtt_us < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
            flag & FLAG_ACKED) {
                u32 delta = tcp_time_stamp(tp) - tp->rx_opt.rcv_tsecr;
-               u32 delta_us = delta * (USEC_PER_SEC / TCP_TS_HZ);
 
-               seq_rtt_us = ca_rtt_us = delta_us;
+               if (likely(delta < INT_MAX / (USEC_PER_SEC / TCP_TS_HZ))) {
+                       seq_rtt_us = delta * (USEC_PER_SEC / TCP_TS_HZ);
+                       ca_rtt_us = seq_rtt_us;
+               }
        }
        rs->rtt_us = ca_rtt_us; /* RTT of last (S)ACKed packet (or -1) */
        if (seq_rtt_us < 0)
@@ -4268,7 +4272,7 @@ static void tcp_sack_new_ofo_skb(struct sock *sk, u32 seq, u32 end_seq)
         * If the sack array is full, forget about the last one.
         */
        if (this_sack >= TCP_NUM_SACKS) {
-               if (tp->compressed_ack)
+               if (tp->compressed_ack > TCP_FASTRETRANS_THRESH)
                        tcp_send_ack(sk);
                this_sack--;
                tp->rx_opt.num_sacks--;
@@ -4363,6 +4367,7 @@ static bool tcp_try_coalesce(struct sock *sk,
        if (TCP_SKB_CB(from)->has_rxtstamp) {
                TCP_SKB_CB(to)->has_rxtstamp = true;
                to->tstamp = from->tstamp;
+               skb_hwtstamps(to)->hwtstamp = skb_hwtstamps(from)->hwtstamp;
        }
 
        return true;
@@ -5188,7 +5193,17 @@ send_now:
        if (!tcp_is_sack(tp) ||
            tp->compressed_ack >= sock_net(sk)->ipv4.sysctl_tcp_comp_sack_nr)
                goto send_now;
-       tp->compressed_ack++;
+
+       if (tp->compressed_ack_rcv_nxt != tp->rcv_nxt) {
+               tp->compressed_ack_rcv_nxt = tp->rcv_nxt;
+               if (tp->compressed_ack > TCP_FASTRETRANS_THRESH)
+                       NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPACKCOMPRESSED,
+                                     tp->compressed_ack - TCP_FASTRETRANS_THRESH);
+               tp->compressed_ack = 0;
+       }
+
+       if (++tp->compressed_ack <= TCP_FASTRETRANS_THRESH)
+               goto send_now;
 
        if (hrtimer_is_queued(&tp->compressed_ack_timer))
                return;
index 9c34b97d365d719ff76250bc9fe7fa20495a3ed2..3f510cad0b3ec884aeb23f58aaa597ec98c82c88 100644 (file)
@@ -180,10 +180,10 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts,
 {
        struct tcp_sock *tp = tcp_sk(sk);
 
-       if (unlikely(tp->compressed_ack)) {
+       if (unlikely(tp->compressed_ack > TCP_FASTRETRANS_THRESH)) {
                NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPACKCOMPRESSED,
-                             tp->compressed_ack);
-               tp->compressed_ack = 0;
+                             tp->compressed_ack - TCP_FASTRETRANS_THRESH);
+               tp->compressed_ack = TCP_FASTRETRANS_THRESH;
                if (hrtimer_try_to_cancel(&tp->compressed_ack_timer) == 1)
                        __sock_put(sk);
        }
index 676020663ce80a79341ad1a05352742cc8dd5850..091c53925e4da6b2b154d166682a0ac0aefd7ecb 100644 (file)
@@ -40,15 +40,17 @@ static u32 tcp_clamp_rto_to_user_timeout(const struct sock *sk)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
        u32 elapsed, start_ts;
+       s32 remaining;
 
        start_ts = tcp_retransmit_stamp(sk);
        if (!icsk->icsk_user_timeout || !start_ts)
                return icsk->icsk_rto;
        elapsed = tcp_time_stamp(tcp_sk(sk)) - start_ts;
-       if (elapsed >= icsk->icsk_user_timeout)
+       remaining = icsk->icsk_user_timeout - elapsed;
+       if (remaining <= 0)
                return 1; /* user timeout has passed; fire ASAP */
-       else
-               return min_t(u32, icsk->icsk_rto, msecs_to_jiffies(icsk->icsk_user_timeout - elapsed));
+
+       return min_t(u32, icsk->icsk_rto, msecs_to_jiffies(remaining));
 }
 
 /**
@@ -209,7 +211,7 @@ static bool retransmits_timed_out(struct sock *sk,
                                (boundary - linear_backoff_thresh) * TCP_RTO_MAX;
                timeout = jiffies_to_msecs(timeout);
        }
-       return (tcp_time_stamp(tcp_sk(sk)) - start_ts) >= timeout;
+       return (s32)(tcp_time_stamp(tcp_sk(sk)) - start_ts - timeout) >= 0;
 }
 
 /* A write timeout has occurred. Process the after effects. */
@@ -740,7 +742,7 @@ static enum hrtimer_restart tcp_compressed_ack_kick(struct hrtimer *timer)
 
        bh_lock_sock(sk);
        if (!sock_owned_by_user(sk)) {
-               if (tp->compressed_ack)
+               if (tp->compressed_ack > TCP_FASTRETRANS_THRESH)
                        tcp_send_ack(sk);
        } else {
                if (!test_and_set_bit(TCP_DELACK_TIMER_DEFERRED,
index 63a808d5af1575255ae9ef16aeb9a2a9549571d5..045597b9a7c05bd5fdb796358af64f4da6bb22dc 100644 (file)
@@ -179,7 +179,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp);
 static void addrconf_dad_work(struct work_struct *w);
 static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id,
                                   bool send_na);
-static void addrconf_dad_run(struct inet6_dev *idev);
+static void addrconf_dad_run(struct inet6_dev *idev, bool restart);
 static void addrconf_rs_timer(struct timer_list *t);
 static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
 static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
@@ -3439,6 +3439,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
                           void *ptr)
 {
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+       struct netdev_notifier_change_info *change_info;
        struct netdev_notifier_changeupper_info *info;
        struct inet6_dev *idev = __in6_dev_get(dev);
        struct net *net = dev_net(dev);
@@ -3513,7 +3514,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
                                break;
                        }
 
-                       if (idev) {
+                       if (!IS_ERR_OR_NULL(idev)) {
                                if (idev->if_flags & IF_READY) {
                                        /* device is already configured -
                                         * but resend MLD reports, we might
@@ -3521,6 +3522,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
                                         * multicast snooping switches
                                         */
                                        ipv6_mc_up(idev);
+                                       change_info = ptr;
+                                       if (change_info->flags_changed & IFF_NOARP)
+                                               addrconf_dad_run(idev, true);
                                        rt6_sync_up(dev, RTNH_F_LINKDOWN);
                                        break;
                                }
@@ -3555,7 +3559,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 
                if (!IS_ERR_OR_NULL(idev)) {
                        if (run_pending)
-                               addrconf_dad_run(idev);
+                               addrconf_dad_run(idev, false);
 
                        /* Device has an address by now */
                        rt6_sync_up(dev, RTNH_F_DEAD);
@@ -4173,16 +4177,19 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp, bool bump_id,
                addrconf_verify_rtnl();
 }
 
-static void addrconf_dad_run(struct inet6_dev *idev)
+static void addrconf_dad_run(struct inet6_dev *idev, bool restart)
 {
        struct inet6_ifaddr *ifp;
 
        read_lock_bh(&idev->lock);
        list_for_each_entry(ifp, &idev->addr_list, if_list) {
                spin_lock(&ifp->lock);
-               if (ifp->flags & IFA_F_TENTATIVE &&
-                   ifp->state == INET6_IFADDR_STATE_DAD)
+               if ((ifp->flags & IFA_F_TENTATIVE &&
+                    ifp->state == INET6_IFADDR_STATE_DAD) || restart) {
+                       if (restart)
+                               ifp->state = INET6_IFADDR_STATE_PREDAD;
                        addrconf_dad_kick(ifp);
+               }
                spin_unlock(&ifp->lock);
        }
        read_unlock_bh(&idev->lock);
index 89e0d5118afe69a94c93e1f584047240fc0d1a51..827a3f5ff3bbdff2e66e09bb90b5b2195b9ef297 100644 (file)
@@ -1354,7 +1354,7 @@ emsgsize:
                        unsigned int fraglen;
                        unsigned int fraggap;
                        unsigned int alloclen;
-                       unsigned int pagedlen = 0;
+                       unsigned int pagedlen;
 alloc_new_skb:
                        /* There's no room in the current skb */
                        if (skb)
@@ -1378,6 +1378,7 @@ alloc_new_skb:
                        if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
                                datalen = maxfraglen - fragheaderlen - rt->dst.trailer_len;
                        fraglen = datalen + fragheaderlen;
+                       pagedlen = 0;
 
                        if ((flags & MSG_MORE) &&
                            !(rt->dst.dev->features&NETIF_F_SG))
index 2a7423c394560c0bc70d6f0398781a0b35fa9fa0..059f0531f7c1c86133afcab0f8e7388c60eeaf58 100644 (file)
@@ -2232,8 +2232,7 @@ static void ip6_link_failure(struct sk_buff *skb)
        if (rt) {
                rcu_read_lock();
                if (rt->rt6i_flags & RTF_CACHE) {
-                       if (dst_hold_safe(&rt->dst))
-                               rt6_remove_exception_rt(rt);
+                       rt6_remove_exception_rt(rt);
                } else {
                        struct fib6_info *from;
                        struct fib6_node *fn;
@@ -2360,10 +2359,13 @@ EXPORT_SYMBOL_GPL(ip6_update_pmtu);
 
 void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
 {
+       int oif = sk->sk_bound_dev_if;
        struct dst_entry *dst;
 
-       ip6_update_pmtu(skb, sock_net(sk), mtu,
-                       sk->sk_bound_dev_if, sk->sk_mark, sk->sk_uid);
+       if (!oif && skb->dev)
+               oif = l3mdev_master_ifindex(skb->dev);
+
+       ip6_update_pmtu(skb, sock_net(sk), mtu, oif, sk->sk_mark, sk->sk_uid);
 
        dst = __sk_dst_get(sk);
        if (!dst || !dst->obsolete ||
@@ -3214,8 +3216,8 @@ static int ip6_del_cached_rt(struct rt6_info *rt, struct fib6_config *cfg)
        if (cfg->fc_flags & RTF_GATEWAY &&
            !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway))
                goto out;
-       if (dst_hold_safe(&rt->dst))
-               rc = rt6_remove_exception_rt(rt);
+
+       rc = rt6_remove_exception_rt(rt);
 out:
        return rc;
 }
index 82cdf9020b53921c1ed86cd6122ebe6007ea263c..26f1d435696a628aca844edb2a88f8b793839d91 100644 (file)
@@ -1490,12 +1490,7 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
                        goto err_sock;
        }
 
-       sk = sock->sk;
-
-       sock_hold(sk);
-       tunnel->sock = sk;
        tunnel->l2tp_net = net;
-
        pn = l2tp_pernet(net);
 
        spin_lock_bh(&pn->l2tp_tunnel_list_lock);
@@ -1510,6 +1505,10 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
        list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list);
        spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
 
+       sk = sock->sk;
+       sock_hold(sk);
+       tunnel->sock = sk;
+
        if (tunnel->encap == L2TP_ENCAPTYPE_UDP) {
                struct udp_tunnel_sock_cfg udp_cfg = {
                        .sk_user_data = tunnel,
index ec3095f13aaee114476a8f06706bfeb7f7739002..a74650e98f423d752e3c49df1388e9c86cb5ee44 100644 (file)
@@ -2394,7 +2394,7 @@ static void tpacket_destruct_skb(struct sk_buff *skb)
                void *ph;
                __u32 ts;
 
-               ph = skb_shinfo(skb)->destructor_arg;
+               ph = skb_zcopy_get_nouarg(skb);
                packet_dec_pending(&po->tx_ring);
 
                ts = __packet_set_timestamp(po, ph, skb);
@@ -2461,7 +2461,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
        skb->mark = po->sk.sk_mark;
        skb->tstamp = sockc->transmit_time;
        sock_tx_timestamp(&po->sk, sockc->tsflags, &skb_shinfo(skb)->tx_flags);
-       skb_shinfo(skb)->destructor_arg = ph.raw;
+       skb_zcopy_set_nouarg(skb, ph.raw);
 
        skb_reserve(skb, hlen);
        skb_reset_network_header(skb);
index 64362d078da846daead402d0f0a5b88bae04b223..a2522f9d71e266d338f1c0d223ce5bcb670fd00f 100644 (file)
@@ -375,16 +375,35 @@ EXPORT_SYMBOL(rxrpc_kernel_end_call);
  * getting ACKs from the server.  Returns a number representing the life state
  * which can be compared to that returned by a previous call.
  *
- * If this is a client call, ping ACKs will be sent to the server to find out
- * whether it's still responsive and whether the call is still alive on the
- * server.
+ * If the life state stalls, rxrpc_kernel_probe_life() should be called and
+ * then 2RTT waited.
  */
-u32 rxrpc_kernel_check_life(struct socket *sock, struct rxrpc_call *call)
+u32 rxrpc_kernel_check_life(const struct socket *sock,
+                           const struct rxrpc_call *call)
 {
        return call->acks_latest;
 }
 EXPORT_SYMBOL(rxrpc_kernel_check_life);
 
+/**
+ * rxrpc_kernel_probe_life - Poke the peer to see if it's still alive
+ * @sock: The socket the call is on
+ * @call: The call to check
+ *
+ * In conjunction with rxrpc_kernel_check_life(), allow a kernel service to
+ * find out whether a call is still alive by pinging it.  This should cause the
+ * life state to be bumped in about 2*RTT.
+ *
+ * The must be called in TASK_RUNNING state on pain of might_sleep() objecting.
+ */
+void rxrpc_kernel_probe_life(struct socket *sock, struct rxrpc_call *call)
+{
+       rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
+                         rxrpc_propose_ack_ping_for_check_life);
+       rxrpc_send_ack_packet(call, true, NULL);
+}
+EXPORT_SYMBOL(rxrpc_kernel_probe_life);
+
 /**
  * rxrpc_kernel_get_epoch - Retrieve the epoch value from a call.
  * @sock: The socket the call is on
index da3dd0f68cc24d2c2b1828b43afc323a5786a3f8..2b372a06b432aec5b48209a3ac0e9424c9ae0b10 100644 (file)
@@ -201,7 +201,8 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
                        goto out_release;
                }
        } else {
-               return err;
+               ret = err;
+               goto out_free;
        }
 
        p = to_pedit(*a);
index 052855d47354232f1c5d4762763367d638d96574..37c9b8f0e10f07c65b48087cbc5ef1335eecb850 100644 (file)
@@ -27,10 +27,7 @@ struct tcf_police_params {
        u32                     tcfp_ewma_rate;
        s64                     tcfp_burst;
        u32                     tcfp_mtu;
-       s64                     tcfp_toks;
-       s64                     tcfp_ptoks;
        s64                     tcfp_mtu_ptoks;
-       s64                     tcfp_t_c;
        struct psched_ratecfg   rate;
        bool                    rate_present;
        struct psched_ratecfg   peak;
@@ -41,6 +38,11 @@ struct tcf_police_params {
 struct tcf_police {
        struct tc_action        common;
        struct tcf_police_params __rcu *params;
+
+       spinlock_t              tcfp_lock ____cacheline_aligned_in_smp;
+       s64                     tcfp_toks;
+       s64                     tcfp_ptoks;
+       s64                     tcfp_t_c;
 };
 
 #define to_police(pc) ((struct tcf_police *)pc)
@@ -122,6 +124,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
                        return ret;
                }
                ret = ACT_P_CREATED;
+               spin_lock_init(&(to_police(*a)->tcfp_lock));
        } else if (!ovr) {
                tcf_idr_release(*a, bind);
                return -EEXIST;
@@ -186,12 +189,9 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
        }
 
        new->tcfp_burst = PSCHED_TICKS2NS(parm->burst);
-       new->tcfp_toks = new->tcfp_burst;
-       if (new->peak_present) {
+       if (new->peak_present)
                new->tcfp_mtu_ptoks = (s64)psched_l2t_ns(&new->peak,
                                                         new->tcfp_mtu);
-               new->tcfp_ptoks = new->tcfp_mtu_ptoks;
-       }
 
        if (tb[TCA_POLICE_AVRATE])
                new->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]);
@@ -207,7 +207,12 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
        }
 
        spin_lock_bh(&police->tcf_lock);
-       new->tcfp_t_c = ktime_get_ns();
+       spin_lock_bh(&police->tcfp_lock);
+       police->tcfp_t_c = ktime_get_ns();
+       police->tcfp_toks = new->tcfp_burst;
+       if (new->peak_present)
+               police->tcfp_ptoks = new->tcfp_mtu_ptoks;
+       spin_unlock_bh(&police->tcfp_lock);
        police->tcf_action = parm->action;
        rcu_swap_protected(police->params,
                           new,
@@ -257,25 +262,28 @@ static int tcf_police_act(struct sk_buff *skb, const struct tc_action *a,
                }
 
                now = ktime_get_ns();
-               toks = min_t(s64, now - p->tcfp_t_c, p->tcfp_burst);
+               spin_lock_bh(&police->tcfp_lock);
+               toks = min_t(s64, now - police->tcfp_t_c, p->tcfp_burst);
                if (p->peak_present) {
-                       ptoks = toks + p->tcfp_ptoks;
+                       ptoks = toks + police->tcfp_ptoks;
                        if (ptoks > p->tcfp_mtu_ptoks)
                                ptoks = p->tcfp_mtu_ptoks;
                        ptoks -= (s64)psched_l2t_ns(&p->peak,
                                                    qdisc_pkt_len(skb));
                }
-               toks += p->tcfp_toks;
+               toks += police->tcfp_toks;
                if (toks > p->tcfp_burst)
                        toks = p->tcfp_burst;
                toks -= (s64)psched_l2t_ns(&p->rate, qdisc_pkt_len(skb));
                if ((toks|ptoks) >= 0) {
-                       p->tcfp_t_c = now;
-                       p->tcfp_toks = toks;
-                       p->tcfp_ptoks = ptoks;
+                       police->tcfp_t_c = now;
+                       police->tcfp_toks = toks;
+                       police->tcfp_ptoks = ptoks;
+                       spin_unlock_bh(&police->tcfp_lock);
                        ret = p->tcfp_result;
                        goto inc_drops;
                }
+               spin_unlock_bh(&police->tcfp_lock);
        }
 
 inc_overlimits:
index 4b1af706896c07e5a0fe6d542dfcd530acdcf8f5..25a7cf6d380fd1ef5610a43a06dea488121b8206 100644 (file)
@@ -469,22 +469,29 @@ begin:
                goto begin;
        }
        prefetch(&skb->end);
-       f->credit -= qdisc_pkt_len(skb);
+       plen = qdisc_pkt_len(skb);
+       f->credit -= plen;
 
-       if (ktime_to_ns(skb->tstamp) || !q->rate_enable)
+       if (!q->rate_enable)
                goto out;
 
        rate = q->flow_max_rate;
-       if (skb->sk)
-               rate = min(skb->sk->sk_pacing_rate, rate);
-
-       if (rate <= q->low_rate_threshold) {
-               f->credit = 0;
-               plen = qdisc_pkt_len(skb);
-       } else {
-               plen = max(qdisc_pkt_len(skb), q->quantum);
-               if (f->credit > 0)
-                       goto out;
+
+       /* If EDT time was provided for this skb, we need to
+        * update f->time_next_packet only if this qdisc enforces
+        * a flow max rate.
+        */
+       if (!skb->tstamp) {
+               if (skb->sk)
+                       rate = min(skb->sk->sk_pacing_rate, rate);
+
+               if (rate <= q->low_rate_threshold) {
+                       f->credit = 0;
+               } else {
+                       plen = max(plen, q->quantum);
+                       if (f->credit > 0)
+                               goto out;
+               }
        }
        if (rate != ~0UL) {
                u64 len = (u64)plen * NSEC_PER_SEC;
index 67939ad99c01335267c3cb21ade4b7dc3259f86f..025f48e14a91f19facf557acb27ee45c0dee46c8 100644 (file)
@@ -118,6 +118,9 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
                sctp_transport_route(tp, NULL, sp);
                if (asoc->param_flags & SPP_PMTUD_ENABLE)
                        sctp_assoc_sync_pmtu(asoc);
+       } else if (!sctp_transport_pmtu_check(tp)) {
+               if (asoc->param_flags & SPP_PMTUD_ENABLE)
+                       sctp_assoc_sync_pmtu(asoc);
        }
 
        if (asoc->pmtu_pending) {
@@ -396,25 +399,6 @@ finish:
        return retval;
 }
 
-static void sctp_packet_release_owner(struct sk_buff *skb)
-{
-       sk_free(skb->sk);
-}
-
-static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk)
-{
-       skb_orphan(skb);
-       skb->sk = sk;
-       skb->destructor = sctp_packet_release_owner;
-
-       /*
-        * The data chunks have already been accounted for in sctp_sendmsg(),
-        * therefore only reserve a single byte to keep socket around until
-        * the packet has been transmitted.
-        */
-       refcount_inc(&sk->sk_wmem_alloc);
-}
-
 static void sctp_packet_gso_append(struct sk_buff *head, struct sk_buff *skb)
 {
        if (SCTP_OUTPUT_CB(head)->last == head)
@@ -426,6 +410,7 @@ static void sctp_packet_gso_append(struct sk_buff *head, struct sk_buff *skb)
        head->truesize += skb->truesize;
        head->data_len += skb->len;
        head->len += skb->len;
+       refcount_add(skb->truesize, &head->sk->sk_wmem_alloc);
 
        __skb_header_release(skb);
 }
@@ -601,7 +586,7 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
        if (!head)
                goto out;
        skb_reserve(head, packet->overhead + MAX_HEADER);
-       sctp_packet_set_owner_w(head, sk);
+       skb_set_owner_w(head, sk);
 
        /* set sctp header */
        sh = skb_push(head, sizeof(struct sctphdr));
index 739f3e50120ddf61c508cc677b46e0239054131c..bf618d1b41fd20d0799726a4f3bc9081f4e48599 100644 (file)
@@ -3940,32 +3940,16 @@ static int sctp_setsockopt_pr_supported(struct sock *sk,
                                        unsigned int optlen)
 {
        struct sctp_assoc_value params;
-       struct sctp_association *asoc;
-       int retval = -EINVAL;
 
        if (optlen != sizeof(params))
-               goto out;
-
-       if (copy_from_user(&params, optval, optlen)) {
-               retval = -EFAULT;
-               goto out;
-       }
-
-       asoc = sctp_id2assoc(sk, params.assoc_id);
-       if (asoc) {
-               asoc->prsctp_enable = !!params.assoc_value;
-       } else if (!params.assoc_id) {
-               struct sctp_sock *sp = sctp_sk(sk);
+               return -EINVAL;
 
-               sp->ep->prsctp_enable = !!params.assoc_value;
-       } else {
-               goto out;
-       }
+       if (copy_from_user(&params, optval, optlen))
+               return -EFAULT;
 
-       retval = 0;
+       sctp_sk(sk)->ep->prsctp_enable = !!params.assoc_value;
 
-out:
-       return retval;
+       return 0;
 }
 
 static int sctp_setsockopt_default_prinfo(struct sock *sk,
index ffb940d3b57c1ca90dec8861b33da6d40f01824f..3892e7630f3adf6d42b57244b761c9e1aa558e95 100644 (file)
@@ -535,7 +535,6 @@ int sctp_send_add_streams(struct sctp_association *asoc,
                goto out;
        }
 
-       stream->incnt = incnt;
        stream->outcnt = outcnt;
 
        asoc->strreset_outstanding = !!out + !!in;
index 80e2119f1c7010ead3c493c60c511c125d6c7149..5fbaf1901571cd2e41a65773ac2f3dc7fa80525d 100644 (file)
@@ -127,6 +127,8 @@ static int smc_release(struct socket *sock)
        smc = smc_sk(sk);
 
        /* cleanup for a dangling non-blocking connect */
+       if (smc->connect_info && sk->sk_state == SMC_INIT)
+               tcp_abort(smc->clcsock->sk, ECONNABORTED);
        flush_work(&smc->connect_work);
        kfree(smc->connect_info);
        smc->connect_info = NULL;
@@ -547,7 +549,8 @@ static int smc_connect_rdma(struct smc_sock *smc,
 
        mutex_lock(&smc_create_lgr_pending);
        local_contact = smc_conn_create(smc, false, aclc->hdr.flag, ibdev,
-                                       ibport, &aclc->lcl, NULL, 0);
+                                       ibport, ntoh24(aclc->qpn), &aclc->lcl,
+                                       NULL, 0);
        if (local_contact < 0) {
                if (local_contact == -ENOMEM)
                        reason_code = SMC_CLC_DECL_MEM;/* insufficient memory*/
@@ -618,7 +621,7 @@ static int smc_connect_ism(struct smc_sock *smc,
        int rc = 0;
 
        mutex_lock(&smc_create_lgr_pending);
-       local_contact = smc_conn_create(smc, true, aclc->hdr.flag, NULL, 0,
+       local_contact = smc_conn_create(smc, true, aclc->hdr.flag, NULL, 0, 0,
                                        NULL, ismdev, aclc->gid);
        if (local_contact < 0)
                return smc_connect_abort(smc, SMC_CLC_DECL_MEM, 0);
@@ -1083,7 +1086,7 @@ static int smc_listen_rdma_init(struct smc_sock *new_smc,
                                int *local_contact)
 {
        /* allocate connection / link group */
-       *local_contact = smc_conn_create(new_smc, false, 0, ibdev, ibport,
+       *local_contact = smc_conn_create(new_smc, false, 0, ibdev, ibport, 0,
                                         &pclc->lcl, NULL, 0);
        if (*local_contact < 0) {
                if (*local_contact == -ENOMEM)
@@ -1107,7 +1110,7 @@ static int smc_listen_ism_init(struct smc_sock *new_smc,
        struct smc_clc_msg_smcd *pclc_smcd;
 
        pclc_smcd = smc_get_clc_msg_smcd(pclc);
-       *local_contact = smc_conn_create(new_smc, true, 0, NULL, 0, NULL,
+       *local_contact = smc_conn_create(new_smc, true, 0, NULL, 0, 0, NULL,
                                         ismdev, pclc_smcd->gid);
        if (*local_contact < 0) {
                if (*local_contact == -ENOMEM)
index ed5dcf03fe0b6ded9d363c1e5891be76f86fd49c..db83332ac1c8ce285f29e2bcc69e22f203b8afc3 100644 (file)
@@ -81,7 +81,7 @@ static inline void smc_cdc_add_pending_send(struct smc_connection *conn,
                sizeof(struct smc_cdc_msg) > SMC_WR_BUF_SIZE,
                "must increase SMC_WR_BUF_SIZE to at least sizeof(struct smc_cdc_msg)");
        BUILD_BUG_ON_MSG(
-               sizeof(struct smc_cdc_msg) != SMC_WR_TX_SIZE,
+               offsetofend(struct smc_cdc_msg, reserved) > SMC_WR_TX_SIZE,
                "must adapt SMC_WR_TX_SIZE to sizeof(struct smc_cdc_msg); if not all smc_wr upper layer protocols use the same message size any more, must start to set link->wr_tx_sges[i].length on each individual smc_wr_tx_send()");
        BUILD_BUG_ON_MSG(
                sizeof(struct smc_cdc_tx_pend) > SMC_WR_TX_PEND_PRIV_SIZE,
@@ -177,23 +177,24 @@ void smc_cdc_tx_dismiss_slots(struct smc_connection *conn)
 int smcd_cdc_msg_send(struct smc_connection *conn)
 {
        struct smc_sock *smc = container_of(conn, struct smc_sock, conn);
+       union smc_host_cursor curs;
        struct smcd_cdc_msg cdc;
        int rc, diff;
 
        memset(&cdc, 0, sizeof(cdc));
        cdc.common.type = SMC_CDC_MSG_TYPE;
-       cdc.prod_wrap = conn->local_tx_ctrl.prod.wrap;
-       cdc.prod_count = conn->local_tx_ctrl.prod.count;
-
-       cdc.cons_wrap = conn->local_tx_ctrl.cons.wrap;
-       cdc.cons_count = conn->local_tx_ctrl.cons.count;
-       cdc.prod_flags = conn->local_tx_ctrl.prod_flags;
-       cdc.conn_state_flags = conn->local_tx_ctrl.conn_state_flags;
+       curs.acurs.counter = atomic64_read(&conn->local_tx_ctrl.prod.acurs);
+       cdc.prod.wrap = curs.wrap;
+       cdc.prod.count = curs.count;
+       curs.acurs.counter = atomic64_read(&conn->local_tx_ctrl.cons.acurs);
+       cdc.cons.wrap = curs.wrap;
+       cdc.cons.count = curs.count;
+       cdc.cons.prod_flags = conn->local_tx_ctrl.prod_flags;
+       cdc.cons.conn_state_flags = conn->local_tx_ctrl.conn_state_flags;
        rc = smcd_tx_ism_write(conn, &cdc, sizeof(cdc), 0, 1);
        if (rc)
                return rc;
-       smc_curs_copy(&conn->rx_curs_confirmed, &conn->local_tx_ctrl.cons,
-                     conn);
+       smc_curs_copy(&conn->rx_curs_confirmed, &curs, conn);
        /* Calculate transmitted data and increment free send buffer space */
        diff = smc_curs_diff(conn->sndbuf_desc->len, &conn->tx_curs_fin,
                             &conn->tx_curs_sent);
@@ -331,13 +332,16 @@ static void smc_cdc_msg_recv(struct smc_sock *smc, struct smc_cdc_msg *cdc)
 static void smcd_cdc_rx_tsklet(unsigned long data)
 {
        struct smc_connection *conn = (struct smc_connection *)data;
+       struct smcd_cdc_msg *data_cdc;
        struct smcd_cdc_msg cdc;
        struct smc_sock *smc;
 
        if (!conn)
                return;
 
-       memcpy(&cdc, conn->rmb_desc->cpu_addr, sizeof(cdc));
+       data_cdc = (struct smcd_cdc_msg *)conn->rmb_desc->cpu_addr;
+       smcd_curs_copy(&cdc.prod, &data_cdc->prod, conn);
+       smcd_curs_copy(&cdc.cons, &data_cdc->cons, conn);
        smc = container_of(conn, struct smc_sock, conn);
        smc_cdc_msg_recv(smc, (struct smc_cdc_msg *)&cdc);
 }
index 934df4473a7cebc4f2cb4fa654d7189201745ac2..b5bfe38c7f9b6a87258adc0aecce58c31c2a164a 100644 (file)
@@ -48,21 +48,31 @@ struct smc_cdc_msg {
        struct smc_cdc_producer_flags   prod_flags;
        struct smc_cdc_conn_state_flags conn_state_flags;
        u8                              reserved[18];
-} __packed;                                    /* format defined in RFC7609 */
+};
+
+/* SMC-D cursor format */
+union smcd_cdc_cursor {
+       struct {
+               u16     wrap;
+               u32     count;
+               struct smc_cdc_producer_flags   prod_flags;
+               struct smc_cdc_conn_state_flags conn_state_flags;
+       } __packed;
+#ifdef KERNEL_HAS_ATOMIC64
+       atomic64_t              acurs;          /* for atomic processing */
+#else
+       u64                     acurs;          /* for atomic processing */
+#endif
+} __aligned(8);
 
 /* CDC message for SMC-D */
 struct smcd_cdc_msg {
        struct smc_wr_rx_hdr common;    /* Type = 0xFE */
        u8 res1[7];
-       u16 prod_wrap;
-       u32 prod_count;
-       u8 res2[2];
-       u16 cons_wrap;
-       u32 cons_count;
-       struct smc_cdc_producer_flags   prod_flags;
-       struct smc_cdc_conn_state_flags conn_state_flags;
+       union smcd_cdc_cursor   prod;
+       union smcd_cdc_cursor   cons;
        u8 res3[8];
-} __packed;
+} __aligned(8);
 
 static inline bool smc_cdc_rxed_any_close(struct smc_connection *conn)
 {
@@ -135,6 +145,21 @@ static inline void smc_curs_copy_net(union smc_cdc_cursor *tgt,
 #endif
 }
 
+static inline void smcd_curs_copy(union smcd_cdc_cursor *tgt,
+                                 union smcd_cdc_cursor *src,
+                                 struct smc_connection *conn)
+{
+#ifndef KERNEL_HAS_ATOMIC64
+       unsigned long flags;
+
+       spin_lock_irqsave(&conn->acurs_lock, flags);
+       tgt->acurs = src->acurs;
+       spin_unlock_irqrestore(&conn->acurs_lock, flags);
+#else
+       atomic64_set(&tgt->acurs, atomic64_read(&src->acurs));
+#endif
+}
+
 /* calculate cursor difference between old and new, where old <= new */
 static inline int smc_curs_diff(unsigned int size,
                                union smc_host_cursor *old,
@@ -222,12 +247,17 @@ static inline void smcr_cdc_msg_to_host(struct smc_host_cdc_msg *local,
 static inline void smcd_cdc_msg_to_host(struct smc_host_cdc_msg *local,
                                        struct smcd_cdc_msg *peer)
 {
-       local->prod.wrap = peer->prod_wrap;
-       local->prod.count = peer->prod_count;
-       local->cons.wrap = peer->cons_wrap;
-       local->cons.count = peer->cons_count;
-       local->prod_flags = peer->prod_flags;
-       local->conn_state_flags = peer->conn_state_flags;
+       union smc_host_cursor temp;
+
+       temp.wrap = peer->prod.wrap;
+       temp.count = peer->prod.count;
+       atomic64_set(&local->prod.acurs, atomic64_read(&temp.acurs));
+
+       temp.wrap = peer->cons.wrap;
+       temp.count = peer->cons.count;
+       atomic64_set(&local->cons.acurs, atomic64_read(&temp.acurs));
+       local->prod_flags = peer->cons.prod_flags;
+       local->conn_state_flags = peer->cons.conn_state_flags;
 }
 
 static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local,
index 18daebcef1813eadd35f287eaa9c8e922ad98005..1c9fa7f0261a3c723c47bde5a3430de72a3278bf 100644 (file)
@@ -184,6 +184,8 @@ free:
 
                if (!lgr->is_smcd && lnk->state != SMC_LNK_INACTIVE)
                        smc_llc_link_inactive(lnk);
+               if (lgr->is_smcd)
+                       smc_ism_signal_shutdown(lgr);
                smc_lgr_free(lgr);
        }
 }
@@ -485,7 +487,7 @@ void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport)
 }
 
 /* Called when SMC-D device is terminated or peer is lost */
-void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid)
+void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid, unsigned short vlan)
 {
        struct smc_link_group *lgr, *l;
        LIST_HEAD(lgr_free_list);
@@ -495,7 +497,7 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid)
        list_for_each_entry_safe(lgr, l, &smc_lgr_list.list, list) {
                if (lgr->is_smcd && lgr->smcd == dev &&
                    (!peer_gid || lgr->peer_gid == peer_gid) &&
-                   !list_empty(&lgr->list)) {
+                   (vlan == VLAN_VID_MASK || lgr->vlan_id == vlan)) {
                        __smc_lgr_terminate(lgr);
                        list_move(&lgr->list, &lgr_free_list);
                }
@@ -506,6 +508,8 @@ void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid)
        list_for_each_entry_safe(lgr, l, &lgr_free_list, list) {
                list_del_init(&lgr->list);
                cancel_delayed_work_sync(&lgr->free_work);
+               if (!peer_gid && vlan == VLAN_VID_MASK) /* dev terminated? */
+                       smc_ism_signal_shutdown(lgr);
                smc_lgr_free(lgr);
        }
 }
@@ -559,7 +563,7 @@ out:
 
 static bool smcr_lgr_match(struct smc_link_group *lgr,
                           struct smc_clc_msg_local *lcl,
-                          enum smc_lgr_role role)
+                          enum smc_lgr_role role, u32 clcqpn)
 {
        return !memcmp(lgr->peer_systemid, lcl->id_for_peer,
                       SMC_SYSTEMID_LEN) &&
@@ -567,7 +571,9 @@ static bool smcr_lgr_match(struct smc_link_group *lgr,
                        SMC_GID_SIZE) &&
                !memcmp(lgr->lnk[SMC_SINGLE_LINK].peer_mac, lcl->mac,
                        sizeof(lcl->mac)) &&
-               lgr->role == role;
+               lgr->role == role &&
+               (lgr->role == SMC_SERV ||
+                lgr->lnk[SMC_SINGLE_LINK].peer_qpn == clcqpn);
 }
 
 static bool smcd_lgr_match(struct smc_link_group *lgr,
@@ -578,7 +584,7 @@ static bool smcd_lgr_match(struct smc_link_group *lgr,
 
 /* create a new SMC connection (and a new link group if necessary) */
 int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
-                   struct smc_ib_device *smcibdev, u8 ibport,
+                   struct smc_ib_device *smcibdev, u8 ibport, u32 clcqpn,
                    struct smc_clc_msg_local *lcl, struct smcd_dev *smcd,
                    u64 peer_gid)
 {
@@ -603,7 +609,7 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
        list_for_each_entry(lgr, &smc_lgr_list.list, list) {
                write_lock_bh(&lgr->conns_lock);
                if ((is_smcd ? smcd_lgr_match(lgr, smcd, peer_gid) :
-                    smcr_lgr_match(lgr, lcl, role)) &&
+                    smcr_lgr_match(lgr, lcl, role, clcqpn)) &&
                    !lgr->sync_err &&
                    lgr->vlan_id == vlan_id &&
                    (role == SMC_CLNT ||
@@ -1024,6 +1030,8 @@ void smc_core_exit(void)
                        smc_llc_link_inactive(lnk);
                }
                cancel_delayed_work_sync(&lgr->free_work);
+               if (lgr->is_smcd)
+                       smc_ism_signal_shutdown(lgr);
                smc_lgr_free(lgr); /* free link group */
        }
 }
index c156674733c9dcb37af68e47a660785d140231b3..cf98f4d6093e940ad8c5b184439a2e9b3545f203 100644 (file)
@@ -247,7 +247,8 @@ void smc_lgr_free(struct smc_link_group *lgr);
 void smc_lgr_forget(struct smc_link_group *lgr);
 void smc_lgr_terminate(struct smc_link_group *lgr);
 void smc_port_terminate(struct smc_ib_device *smcibdev, u8 ibport);
-void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid);
+void smc_smcd_terminate(struct smcd_dev *dev, u64 peer_gid,
+                       unsigned short vlan);
 int smc_buf_create(struct smc_sock *smc, bool is_smcd);
 int smc_uncompress_bufsize(u8 compressed);
 int smc_rmb_rtoken_handling(struct smc_connection *conn,
@@ -262,7 +263,7 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id);
 
 void smc_conn_free(struct smc_connection *conn);
 int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
-                   struct smc_ib_device *smcibdev, u8 ibport,
+                   struct smc_ib_device *smcibdev, u8 ibport, u32 clcqpn,
                    struct smc_clc_msg_local *lcl, struct smcd_dev *smcd,
                    u64 peer_gid);
 void smcd_conn_free(struct smc_connection *conn);
index e36f21ce725208c62164847602e99df91d2c40ba..2fff79db1a59ce3d2908722941dd9355810c65a0 100644 (file)
@@ -187,22 +187,28 @@ struct smc_ism_event_work {
 #define ISM_EVENT_REQUEST              0x0001
 #define ISM_EVENT_RESPONSE             0x0002
 #define ISM_EVENT_REQUEST_IR           0x00000001
+#define ISM_EVENT_CODE_SHUTDOWN                0x80
 #define ISM_EVENT_CODE_TESTLINK                0x83
 
+union smcd_sw_event_info {
+       u64     info;
+       struct {
+               u8              uid[SMC_LGR_ID_SIZE];
+               unsigned short  vlan_id;
+               u16             code;
+       };
+};
+
 static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
 {
-       union {
-               u64     info;
-               struct {
-                       u32             uid;
-                       unsigned short  vlanid;
-                       u16             code;
-               };
-       } ev_info;
+       union smcd_sw_event_info ev_info;
 
+       ev_info.info = wrk->event.info;
        switch (wrk->event.code) {
+       case ISM_EVENT_CODE_SHUTDOWN:   /* Peer shut down DMBs */
+               smc_smcd_terminate(wrk->smcd, wrk->event.tok, ev_info.vlan_id);
+               break;
        case ISM_EVENT_CODE_TESTLINK:   /* Activity timer */
-               ev_info.info = wrk->event.info;
                if (ev_info.code == ISM_EVENT_REQUEST) {
                        ev_info.code = ISM_EVENT_RESPONSE;
                        wrk->smcd->ops->signal_event(wrk->smcd,
@@ -215,6 +221,21 @@ static void smcd_handle_sw_event(struct smc_ism_event_work *wrk)
        }
 }
 
+int smc_ism_signal_shutdown(struct smc_link_group *lgr)
+{
+       int rc;
+       union smcd_sw_event_info ev_info;
+
+       memcpy(ev_info.uid, lgr->id, SMC_LGR_ID_SIZE);
+       ev_info.vlan_id = lgr->vlan_id;
+       ev_info.code = ISM_EVENT_REQUEST;
+       rc = lgr->smcd->ops->signal_event(lgr->smcd, lgr->peer_gid,
+                                         ISM_EVENT_REQUEST_IR,
+                                         ISM_EVENT_CODE_SHUTDOWN,
+                                         ev_info.info);
+       return rc;
+}
+
 /* worker for SMC-D events */
 static void smc_ism_event_work(struct work_struct *work)
 {
@@ -223,7 +244,7 @@ static void smc_ism_event_work(struct work_struct *work)
 
        switch (wrk->event.type) {
        case ISM_EVENT_GID:     /* GID event, token is peer GID */
-               smc_smcd_terminate(wrk->smcd, wrk->event.tok);
+               smc_smcd_terminate(wrk->smcd, wrk->event.tok, VLAN_VID_MASK);
                break;
        case ISM_EVENT_DMB:
                break;
@@ -289,7 +310,7 @@ void smcd_unregister_dev(struct smcd_dev *smcd)
        spin_unlock(&smcd_dev_list.lock);
        flush_workqueue(smcd->event_wq);
        destroy_workqueue(smcd->event_wq);
-       smc_smcd_terminate(smcd, 0);
+       smc_smcd_terminate(smcd, 0, VLAN_VID_MASK);
 
        device_del(&smcd->dev);
 }
index aee45b860b799856c80862bc36160618af17610b..4da946cbfa29c2d7c233f16c983eaf4b738bd6bb 100644 (file)
@@ -45,4 +45,5 @@ int smc_ism_register_dmb(struct smc_link_group *lgr, int buf_size,
 int smc_ism_unregister_dmb(struct smcd_dev *dev, struct smc_buf_desc *dmb_desc);
 int smc_ism_write(struct smcd_dev *dev, const struct smc_ism_position *pos,
                  void *data, size_t len);
+int smc_ism_signal_shutdown(struct smc_link_group *lgr);
 #endif
index 3c458d27985574efc929c21565fd0aaae58f2c20..c2694750a6a8abe2f1353dae02e95420e5a01b48 100644 (file)
@@ -215,12 +215,14 @@ int smc_wr_tx_put_slot(struct smc_link *link,
 
        pend = container_of(wr_pend_priv, struct smc_wr_tx_pend, priv);
        if (pend->idx < link->wr_tx_cnt) {
+               u32 idx = pend->idx;
+
                /* clear the full struct smc_wr_tx_pend including .priv */
                memset(&link->wr_tx_pends[pend->idx], 0,
                       sizeof(link->wr_tx_pends[pend->idx]));
                memset(&link->wr_tx_bufs[pend->idx], 0,
                       sizeof(link->wr_tx_bufs[pend->idx]));
-               test_and_clear_bit(pend->idx, link->wr_tx_mask);
+               test_and_clear_bit(idx, link->wr_tx_mask);
                return 1;
        }
 
index 593826e11a5376bd1301b2cf19c61c377653c653..334fcc617ef2737acd0a84f7921e28a88771756f 100644 (file)
@@ -853,7 +853,7 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
        struct socket *sock = file->private_data;
 
        if (unlikely(!sock->ops->splice_read))
-               return -EINVAL;
+               return generic_file_splice_read(file, ppos, pipe, len, flags);
 
        return sock->ops->splice_read(sock, ppos, pipe, len, flags);
 }
index d8831b988b1e7a3273c73ee2457615b26c24b529..ab4a3be1542a0a6fcfb35153da1a62b3f852c2b6 100644 (file)
@@ -281,13 +281,7 @@ static bool generic_key_to_expire(struct rpc_cred *cred)
 {
        struct auth_cred *acred = &container_of(cred, struct generic_cred,
                                                gc_base)->acred;
-       bool ret;
-
-       get_rpccred(cred);
-       ret = test_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags);
-       put_rpccred(cred);
-
-       return ret;
+       return test_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags);
 }
 
 static const struct rpc_credops generic_credops = {
index 30f970cdc7f66375d45e5363dfa07cab233f4978..5d3f252659f191fe040452e6b55a862d850450e8 100644 (file)
@@ -1239,36 +1239,59 @@ gss_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
        return &gss_auth->rpc_auth;
 }
 
+static struct gss_cred *
+gss_dup_cred(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
+{
+       struct gss_cred *new;
+
+       /* Make a copy of the cred so that we can reference count it */
+       new = kzalloc(sizeof(*gss_cred), GFP_NOIO);
+       if (new) {
+               struct auth_cred acred = {
+                       .uid = gss_cred->gc_base.cr_uid,
+               };
+               struct gss_cl_ctx *ctx =
+                       rcu_dereference_protected(gss_cred->gc_ctx, 1);
+
+               rpcauth_init_cred(&new->gc_base, &acred,
+                               &gss_auth->rpc_auth,
+                               &gss_nullops);
+               new->gc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
+               new->gc_service = gss_cred->gc_service;
+               new->gc_principal = gss_cred->gc_principal;
+               kref_get(&gss_auth->kref);
+               rcu_assign_pointer(new->gc_ctx, ctx);
+               gss_get_ctx(ctx);
+       }
+       return new;
+}
+
 /*
- * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call
+ * gss_send_destroy_context will cause the RPCSEC_GSS to send a NULL RPC call
  * to the server with the GSS control procedure field set to
  * RPC_GSS_PROC_DESTROY. This should normally cause the server to release
  * all RPCSEC_GSS state associated with that context.
  */
-static int
-gss_destroying_context(struct rpc_cred *cred)
+static void
+gss_send_destroy_context(struct rpc_cred *cred)
 {
        struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
        struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth);
        struct gss_cl_ctx *ctx = rcu_dereference_protected(gss_cred->gc_ctx, 1);
+       struct gss_cred *new;
        struct rpc_task *task;
 
-       if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
-               return 0;
-
-       ctx->gc_proc = RPC_GSS_PROC_DESTROY;
-       cred->cr_ops = &gss_nullops;
-
-       /* Take a reference to ensure the cred will be destroyed either
-        * by the RPC call or by the put_rpccred() below */
-       get_rpccred(cred);
+       new = gss_dup_cred(gss_auth, gss_cred);
+       if (new) {
+               ctx->gc_proc = RPC_GSS_PROC_DESTROY;
 
-       task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC|RPC_TASK_SOFT);
-       if (!IS_ERR(task))
-               rpc_put_task(task);
+               task = rpc_call_null(gss_auth->client, &new->gc_base,
+                               RPC_TASK_ASYNC|RPC_TASK_SOFT);
+               if (!IS_ERR(task))
+                       rpc_put_task(task);
 
-       put_rpccred(cred);
-       return 1;
+               put_rpccred(&new->gc_base);
+       }
 }
 
 /* gss_destroy_cred (and gss_free_ctx) are used to clean up after failure
@@ -1330,8 +1353,8 @@ static void
 gss_destroy_cred(struct rpc_cred *cred)
 {
 
-       if (gss_destroying_context(cred))
-               return;
+       if (test_and_clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0)
+               gss_send_destroy_context(cred);
        gss_destroy_nullcred(cred);
 }
 
index 2bbb8d38d2bf5f6eeb87a5771aeb92683d25543f..f302c6eb8779063a71b9a590325a96b8026ab3e6 100644 (file)
@@ -546,7 +546,7 @@ EXPORT_SYMBOL_GPL(xdr_commit_encode);
 static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr,
                size_t nbytes)
 {
-       static __be32 *p;
+       __be32 *p;
        int space_left;
        int frag1bytes, frag2bytes;
 
@@ -673,11 +673,10 @@ void xdr_truncate_encode(struct xdr_stream *xdr, size_t len)
                WARN_ON_ONCE(xdr->iov);
                return;
        }
-       if (fraglen) {
+       if (fraglen)
                xdr->end = head->iov_base + head->iov_len;
-               xdr->page_ptr--;
-       }
        /* (otherwise assume xdr->end is already set) */
+       xdr->page_ptr--;
        head->iov_len = len;
        buf->len = len;
        xdr->p = head->iov_base + head->iov_len;
index 2830709957bddeb13adf0f352abb9aaacba3ec55..c138d68e8a695fde8fb1464f03a539cef5a03bd4 100644 (file)
@@ -166,7 +166,8 @@ static bool tipc_disc_addr_trial_msg(struct tipc_discoverer *d,
 
        /* Apply trial address if we just left trial period */
        if (!trial && !self) {
-               tipc_net_finalize(net, tn->trial_addr);
+               tipc_sched_net_finalize(net, tn->trial_addr);
+               msg_set_prevnode(buf_msg(d->skb), tn->trial_addr);
                msg_set_type(buf_msg(d->skb), DSC_REQ_MSG);
        }
 
@@ -300,14 +301,12 @@ static void tipc_disc_timeout(struct timer_list *t)
                goto exit;
        }
 
-       /* Trial period over ? */
-       if (!time_before(jiffies, tn->addr_trial_end)) {
-               /* Did we just leave it ? */
-               if (!tipc_own_addr(net))
-                       tipc_net_finalize(net, tn->trial_addr);
-
-               msg_set_type(buf_msg(d->skb), DSC_REQ_MSG);
-               msg_set_prevnode(buf_msg(d->skb), tipc_own_addr(net));
+       /* Did we just leave trial period ? */
+       if (!time_before(jiffies, tn->addr_trial_end) && !tipc_own_addr(net)) {
+               mod_timer(&d->timer, jiffies + TIPC_DISC_INIT);
+               spin_unlock_bh(&d->lock);
+               tipc_sched_net_finalize(net, tn->trial_addr);
+               return;
        }
 
        /* Adjust timeout interval according to discovery phase */
@@ -319,6 +318,8 @@ static void tipc_disc_timeout(struct timer_list *t)
                        d->timer_intv = TIPC_DISC_SLOW;
                else if (!d->num_nodes && d->timer_intv > TIPC_DISC_FAST)
                        d->timer_intv = TIPC_DISC_FAST;
+               msg_set_type(buf_msg(d->skb), DSC_REQ_MSG);
+               msg_set_prevnode(buf_msg(d->skb), tn->trial_addr);
        }
 
        mod_timer(&d->timer, jiffies + d->timer_intv);
index 62199cf5a56c04db99af54dad9fc2564df8d6b05..f076edb74338247f0bad99cfaa5d23e5b14730ab 100644 (file)
  *     - A local spin_lock protecting the queue of subscriber events.
 */
 
+struct tipc_net_work {
+       struct work_struct work;
+       struct net *net;
+       u32 addr;
+};
+
+static void tipc_net_finalize(struct net *net, u32 addr);
+
 int tipc_net_init(struct net *net, u8 *node_id, u32 addr)
 {
        if (tipc_own_id(net)) {
@@ -119,17 +127,38 @@ int tipc_net_init(struct net *net, u8 *node_id, u32 addr)
        return 0;
 }
 
-void tipc_net_finalize(struct net *net, u32 addr)
+static void tipc_net_finalize(struct net *net, u32 addr)
 {
        struct tipc_net *tn = tipc_net(net);
 
-       if (!cmpxchg(&tn->node_addr, 0, addr)) {
-               tipc_set_node_addr(net, addr);
-               tipc_named_reinit(net);
-               tipc_sk_reinit(net);
-               tipc_nametbl_publish(net, TIPC_CFG_SRV, addr, addr,
-                                    TIPC_CLUSTER_SCOPE, 0, addr);
-       }
+       if (cmpxchg(&tn->node_addr, 0, addr))
+               return;
+       tipc_set_node_addr(net, addr);
+       tipc_named_reinit(net);
+       tipc_sk_reinit(net);
+       tipc_nametbl_publish(net, TIPC_CFG_SRV, addr, addr,
+                            TIPC_CLUSTER_SCOPE, 0, addr);
+}
+
+static void tipc_net_finalize_work(struct work_struct *work)
+{
+       struct tipc_net_work *fwork;
+
+       fwork = container_of(work, struct tipc_net_work, work);
+       tipc_net_finalize(fwork->net, fwork->addr);
+       kfree(fwork);
+}
+
+void tipc_sched_net_finalize(struct net *net, u32 addr)
+{
+       struct tipc_net_work *fwork = kzalloc(sizeof(*fwork), GFP_ATOMIC);
+
+       if (!fwork)
+               return;
+       INIT_WORK(&fwork->work, tipc_net_finalize_work);
+       fwork->net = net;
+       fwork->addr = addr;
+       schedule_work(&fwork->work);
 }
 
 void tipc_net_stop(struct net *net)
index 09ad02b50bb1ba1e9798c41810c843d74b5e0185..b7f2e364eb99e774854ea22837107991619ef00a 100644 (file)
@@ -42,7 +42,7 @@
 extern const struct nla_policy tipc_nl_net_policy[];
 
 int tipc_net_init(struct net *net, u8 *node_id, u32 addr);
-void tipc_net_finalize(struct net *net, u32 addr);
+void tipc_sched_net_finalize(struct net *net, u32 addr);
 void tipc_net_stop(struct net *net);
 int tipc_nl_net_dump(struct sk_buff *skb, struct netlink_callback *cb);
 int tipc_nl_net_set(struct sk_buff *skb, struct genl_info *info);
index 2afc4f8c37a74db4896508283f434909a0151732..48801976643358efd72623e8c5de56cc77202afd 100644 (file)
@@ -584,12 +584,15 @@ static void  tipc_node_clear_links(struct tipc_node *node)
 /* tipc_node_cleanup - delete nodes that does not
  * have active links for NODE_CLEANUP_AFTER time
  */
-static int tipc_node_cleanup(struct tipc_node *peer)
+static bool tipc_node_cleanup(struct tipc_node *peer)
 {
        struct tipc_net *tn = tipc_net(peer->net);
        bool deleted = false;
 
-       spin_lock_bh(&tn->node_list_lock);
+       /* If lock held by tipc_node_stop() the node will be deleted anyway */
+       if (!spin_trylock_bh(&tn->node_list_lock))
+               return false;
+
        tipc_node_write_lock(peer);
 
        if (!node_is_up(peer) && time_after(jiffies, peer->delete_at)) {
index 636e6131769d83f9b5f7013a32210ec809835fb2..b57b1be7252baef2f6410710e225864877c08ac1 100644 (file)
@@ -1555,16 +1555,17 @@ static void tipc_sk_set_orig_addr(struct msghdr *m, struct sk_buff *skb)
 /**
  * tipc_sk_anc_data_recv - optionally capture ancillary data for received message
  * @m: descriptor for message info
- * @msg: received message header
+ * @skb: received message buffer
  * @tsk: TIPC port associated with message
  *
  * Note: Ancillary data is not captured if not requested by receiver.
  *
  * Returns 0 if successful, otherwise errno
  */
-static int tipc_sk_anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
+static int tipc_sk_anc_data_recv(struct msghdr *m, struct sk_buff *skb,
                                 struct tipc_sock *tsk)
 {
+       struct tipc_msg *msg;
        u32 anc_data[3];
        u32 err;
        u32 dest_type;
@@ -1573,6 +1574,7 @@ static int tipc_sk_anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
 
        if (likely(m->msg_controllen == 0))
                return 0;
+       msg = buf_msg(skb);
 
        /* Optionally capture errored message object(s) */
        err = msg ? msg_errcode(msg) : 0;
@@ -1583,6 +1585,9 @@ static int tipc_sk_anc_data_recv(struct msghdr *m, struct tipc_msg *msg,
                if (res)
                        return res;
                if (anc_data[1]) {
+                       if (skb_linearize(skb))
+                               return -ENOMEM;
+                       msg = buf_msg(skb);
                        res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1],
                                       msg_data(msg));
                        if (res)
@@ -1744,9 +1749,10 @@ static int tipc_recvmsg(struct socket *sock, struct msghdr *m,
 
        /* Collect msg meta data, including error code and rejected data */
        tipc_sk_set_orig_addr(m, skb);
-       rc = tipc_sk_anc_data_recv(m, hdr, tsk);
+       rc = tipc_sk_anc_data_recv(m, skb, tsk);
        if (unlikely(rc))
                goto exit;
+       hdr = buf_msg(skb);
 
        /* Capture data if non-error msg, otherwise just set return value */
        if (likely(!err)) {
@@ -1856,9 +1862,10 @@ static int tipc_recvstream(struct socket *sock, struct msghdr *m,
                /* Collect msg meta data, incl. error code and rejected data */
                if (!copied) {
                        tipc_sk_set_orig_addr(m, skb);
-                       rc = tipc_sk_anc_data_recv(m, hdr, tsk);
+                       rc = tipc_sk_anc_data_recv(m, skb, tsk);
                        if (rc)
                                break;
+                       hdr = buf_msg(skb);
                }
 
                /* Copy data if msg ok, otherwise return error/partial data */
index a0149db00be752555ff4178f66540543a5835955..6c6439f69a725f4bd46210fb3bb2c3e80a49fab2 100755 (executable)
@@ -71,7 +71,7 @@ die() {
 
 # Try to figure out the source directory prefix so we can remove it from the
 # addr2line output.  HACK ALERT: This assumes that start_kernel() is in
-# kernel/init.c!  This only works for vmlinux.  Otherwise it falls back to
+# init/main.c!  This only works for vmlinux.  Otherwise it falls back to
 # printing the absolute path.
 find_dir_prefix() {
        local objfile=$1
index 839e190bbd7a0075ef28040291fca87f44d3170a..5056fb3b897d0094e182bba4fca08ae491dab7cc 100755 (executable)
@@ -168,7 +168,6 @@ class id_parser(object):
         self.curline = 0
         try:
             for line in fd:
-                line = line.decode(locale.getpreferredencoding(False), errors='ignore')
                 self.curline += 1
                 if self.curline > maxlines:
                     break
index 6dc0751445087727f9d1b09a8c1efdbbc9105625..d775e03fbbcc7d87b9724529a4499b9449a9aa46 100644 (file)
@@ -106,6 +106,7 @@ int asymmetric_verify(struct key *keyring, const char *sig,
 
        pks.pkey_algo = "rsa";
        pks.hash_algo = hash_algo_name[hdr->hash_algo];
+       pks.encoding = "pkcs1";
        pks.digest = (u8 *)data;
        pks.digest_size = datalen;
        pks.s = hdr->sig;
index 7ce683259357750cdfd25feb978ee1d6a984312b..a67459eb62d5c8d3066a72c354f13894f68be8ae 100644 (file)
@@ -5318,6 +5318,9 @@ static int selinux_sctp_bind_connect(struct sock *sk, int optname,
        addr_buf = address;
 
        while (walk_size < addrlen) {
+               if (walk_size + sizeof(sa_family_t) > addrlen)
+                       return -EINVAL;
+
                addr = addr_buf;
                switch (addr->sa_family) {
                case AF_UNSPEC:
index 2fe459df3c858dc038e2a5e5f851ee4a0f07fafa..b7efa2296969c617dc292759b61c3c6f1ca450a5 100644 (file)
@@ -245,9 +245,13 @@ int mls_context_to_sid(struct policydb *pol,
        char *rangep[2];
 
        if (!pol->mls_enabled) {
-               if ((def_sid != SECSID_NULL && oldc) || (*scontext) == '\0')
-                       return 0;
-               return -EINVAL;
+               /*
+                * With no MLS, only return -EINVAL if there is a MLS field
+                * and it did not come from an xattr.
+                */
+               if (oldc && def_sid == SECSID_NULL)
+                       return -EINVAL;
+               return 0;
        }
 
        /*
index f8d4a419f3af957a2dd53ba8cf1673da607ec7e0..467039b342b511c7c4fb95f0d7c316f7715d7c70 100644 (file)
@@ -1062,8 +1062,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
        runtime->oss.channels = params_channels(params);
        runtime->oss.rate = params_rate(params);
 
-       vfree(runtime->oss.buffer);
-       runtime->oss.buffer = vmalloc(runtime->oss.period_bytes);
+       kvfree(runtime->oss.buffer);
+       runtime->oss.buffer = kvzalloc(runtime->oss.period_bytes, GFP_KERNEL);
        if (!runtime->oss.buffer) {
                err = -ENOMEM;
                goto failure;
@@ -2328,7 +2328,7 @@ static void snd_pcm_oss_release_substream(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime;
        runtime = substream->runtime;
-       vfree(runtime->oss.buffer);
+       kvfree(runtime->oss.buffer);
        runtime->oss.buffer = NULL;
 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
        snd_pcm_oss_plugin_clear(substream);
index 141c5f3a957501e0901102ce5bd519cbca73892e..31cb2acf8afcc5988d47cdb2332c005c0558d18a 100644 (file)
@@ -66,8 +66,8 @@ static int snd_pcm_plugin_alloc(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t
                return -ENXIO;
        size /= 8;
        if (plugin->buf_frames < frames) {
-               vfree(plugin->buf);
-               plugin->buf = vmalloc(size);
+               kvfree(plugin->buf);
+               plugin->buf = kvzalloc(size, GFP_KERNEL);
                plugin->buf_frames = frames;
        }
        if (!plugin->buf) {
@@ -191,7 +191,7 @@ int snd_pcm_plugin_free(struct snd_pcm_plugin *plugin)
        if (plugin->private_free)
                plugin->private_free(plugin);
        kfree(plugin->buf_channels);
-       vfree(plugin->buf);
+       kvfree(plugin->buf);
        kfree(plugin);
        return 0;
 }
index 0a24037184c33e2cd53554d7cf9e4dd6586dd19b..0a567634e5faddafd470220c7a9ebaff88ce8cef 100644 (file)
@@ -1177,6 +1177,7 @@ static const struct snd_pci_quirk ca0132_quirks[] = {
        SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE),
        SND_PCI_QUIRK(0x1102, 0x0010, "Sound Blaster Z", QUIRK_SBZ),
        SND_PCI_QUIRK(0x1102, 0x0023, "Sound Blaster Z", QUIRK_SBZ),
+       SND_PCI_QUIRK(0x1102, 0x0033, "Sound Blaster ZxR", QUIRK_SBZ),
        SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI),
        SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI),
        SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI),
@@ -8413,7 +8414,7 @@ static void ca0132_free(struct hda_codec *codec)
 
        snd_hda_power_down(codec);
        if (spec->mem_base)
-               iounmap(spec->mem_base);
+               pci_iounmap(codec->bus->pci, spec->mem_base);
        kfree(spec->spec_init_verbs);
        kfree(codec->spec);
 }
@@ -8488,7 +8489,7 @@ static void ca0132_config(struct hda_codec *codec)
                break;
        case QUIRK_AE5:
                codec_dbg(codec, "%s: QUIRK_AE5 applied.\n", __func__);
-               snd_hda_apply_pincfgs(codec, r3di_pincfgs);
+               snd_hda_apply_pincfgs(codec, ae5_pincfgs);
                break;
        }
 
index fa61674a560504224b9ee8ef35da2d4ddf85c6fe..970bc44a378b8d32f1f8a43045d224bc34d4f222 100644 (file)
@@ -6481,6 +6481,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
        SND_PCI_QUIRK(0x103c, 0x221c, "HP EliteBook 755 G2", ALC280_FIXUP_HP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x103c, 0x820d, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
        SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC),
        SND_PCI_QUIRK(0x103c, 0x827e, "HP x360", ALC295_FIXUP_HP_X360),
        SND_PCI_QUIRK(0x103c, 0x82bf, "HP", ALC221_FIXUP_HP_MIC_NO_PRESENCE),
index edbe81534c6d2941b955cd0ab15cf845110fb130..d07ccf8a23f7170be674d12a08957d673a560f77 100644 (file)
@@ -137,4 +137,10 @@ EXAMPLES
 
 SEE ALSO
 ========
-       **bpftool**\ (8), **bpftool-prog**\ (8), **bpftool-map**\ (8)
+       **bpf**\ (2),
+       **bpf-helpers**\ (7),
+       **bpftool**\ (8),
+       **bpftool-prog**\ (8),
+       **bpftool-map**\ (8),
+       **bpftool-net**\ (8),
+       **bpftool-perf**\ (8)
index f55a2daed59b7e8dead1a1fc429dd6a097f2f83f..7bb787cfa97145eb1bede4ea2057903d6587398f 100644 (file)
@@ -171,4 +171,10 @@ The following three commands are equivalent:
 
 SEE ALSO
 ========
-       **bpftool**\ (8), **bpftool-prog**\ (8), **bpftool-cgroup**\ (8)
+       **bpf**\ (2),
+       **bpf-helpers**\ (7),
+       **bpftool**\ (8),
+       **bpftool-prog**\ (8),
+       **bpftool-cgroup**\ (8),
+       **bpftool-net**\ (8),
+       **bpftool-perf**\ (8)
index 408ec30d88726206b3bad8436ec8c9abdd11d806..ed87c9b619adc889310e7795bcfcc4b790251827 100644 (file)
@@ -136,4 +136,10 @@ EXAMPLES
 
 SEE ALSO
 ========
-       **bpftool**\ (8), **bpftool-prog**\ (8), **bpftool-map**\ (8)
+       **bpf**\ (2),
+       **bpf-helpers**\ (7),
+       **bpftool**\ (8),
+       **bpftool-prog**\ (8),
+       **bpftool-map**\ (8),
+       **bpftool-cgroup**\ (8),
+       **bpftool-perf**\ (8)
index e3eb0eab76419427509b213e00c6458e68ff61fc..f4c5e5538bb8e516624b0f28f749bf613c5a477e 100644 (file)
@@ -78,4 +78,10 @@ EXAMPLES
 
 SEE ALSO
 ========
-       **bpftool**\ (8), **bpftool-prog**\ (8), **bpftool-map**\ (8)
+       **bpf**\ (2),
+       **bpf-helpers**\ (7),
+       **bpftool**\ (8),
+       **bpftool-prog**\ (8),
+       **bpftool-map**\ (8),
+       **bpftool-cgroup**\ (8),
+       **bpftool-net**\ (8)
index ac4e904b10fbd9b4b504d943f62aef0be68f0829..ecf618807125d9af832ec1ec969047c060393620 100644 (file)
@@ -124,7 +124,8 @@ OPTIONS
                  Generate human-readable JSON output. Implies **-j**.
 
        -f, --bpffs
-                 Show file names of pinned programs.
+                 When showing BPF programs, show file names of pinned
+                 programs.
 
 EXAMPLES
 ========
@@ -206,4 +207,10 @@ EXAMPLES
 
 SEE ALSO
 ========
-       **bpftool**\ (8), **bpftool-map**\ (8), **bpftool-cgroup**\ (8)
+       **bpf**\ (2),
+       **bpf-helpers**\ (7),
+       **bpftool**\ (8),
+       **bpftool-map**\ (8),
+       **bpftool-cgroup**\ (8),
+       **bpftool-net**\ (8),
+       **bpftool-perf**\ (8)
index 04cd4f92ab89c9dd8009180c3e4601c7b1956d1e..129b7a9c0f9bce5ac78f49d6678e39c8c6fbaa8b 100644 (file)
@@ -63,5 +63,10 @@ OPTIONS
 
 SEE ALSO
 ========
-       **bpftool-map**\ (8), **bpftool-prog**\ (8), **bpftool-cgroup**\ (8)
-        **bpftool-perf**\ (8), **bpftool-net**\ (8)
+       **bpf**\ (2),
+       **bpf-helpers**\ (7),
+       **bpftool-prog**\ (8),
+       **bpftool-map**\ (8),
+       **bpftool-cgroup**\ (8),
+       **bpftool-net**\ (8),
+       **bpftool-perf**\ (8)
index 25af85304ebee3b073d9e7d0036038c5c4c05d68..70fd48d79f611fd98666a0ecf156c00285007fd9 100644 (file)
@@ -130,16 +130,17 @@ static int mnt_bpffs(const char *target, char *buff, size_t bufflen)
        return 0;
 }
 
-int open_obj_pinned(char *path)
+int open_obj_pinned(char *path, bool quiet)
 {
        int fd;
 
        fd = bpf_obj_get(path);
        if (fd < 0) {
-               p_err("bpf obj get (%s): %s", path,
-                     errno == EACCES && !is_bpffs(dirname(path)) ?
-                   "directory not in bpf file system (bpffs)" :
-                   strerror(errno));
+               if (!quiet)
+                       p_err("bpf obj get (%s): %s", path,
+                             errno == EACCES && !is_bpffs(dirname(path)) ?
+                           "directory not in bpf file system (bpffs)" :
+                           strerror(errno));
                return -1;
        }
 
@@ -151,7 +152,7 @@ int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
        enum bpf_obj_type type;
        int fd;
 
-       fd = open_obj_pinned(path);
+       fd = open_obj_pinned(path, false);
        if (fd < 0)
                return -1;
 
@@ -304,7 +305,7 @@ char *get_fdinfo(int fd, const char *key)
                return NULL;
        }
 
-       while ((n = getline(&line, &line_n, fdi))) {
+       while ((n = getline(&line, &line_n, fdi)) > 0) {
                char *value;
                int len;
 
@@ -384,7 +385,7 @@ int build_pinned_obj_table(struct pinned_obj_table *tab,
                while ((ftse = fts_read(fts))) {
                        if (!(ftse->fts_info & FTS_F))
                                continue;
-                       fd = open_obj_pinned(ftse->fts_path);
+                       fd = open_obj_pinned(ftse->fts_path, true);
                        if (fd < 0)
                                continue;
 
index 28322ace285653f91a9fe42e69a29483b0a1280b..a8bf1e2d9818debfc200701f21d438d432e093fc 100644 (file)
@@ -127,7 +127,7 @@ int cmd_select(const struct cmd *cmds, int argc, char **argv,
 int get_fd_type(int fd);
 const char *get_fd_type_name(enum bpf_obj_type type);
 char *get_fdinfo(int fd, const char *key);
-int open_obj_pinned(char *path);
+int open_obj_pinned(char *path, bool quiet);
 int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type);
 int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32));
 int do_pin_fd(int fd, const char *name);
index 5302ee282409eb039458447ad40215f24516c48a..ccee180dfb761248f078ffa4b2154793d0308420 100644 (file)
@@ -357,10 +357,9 @@ static void print_prog_plain(struct bpf_prog_info *info, int fd)
        if (!hash_empty(prog_table.table)) {
                struct pinned_obj *obj;
 
-               printf("\n");
                hash_for_each_possible(prog_table.table, obj, hash, info->id) {
                        if (obj->id == info->id)
-                               printf("\tpinned %s\n", obj->path);
+                               printf("\n\tpinned %s", obj->path);
                }
        }
 
@@ -845,6 +844,7 @@ static int do_load(int argc, char **argv)
                        }
                        NEXT_ARG();
                } else if (is_prefix(*argv, "map")) {
+                       void *new_map_replace;
                        char *endptr, *name;
                        int fd;
 
@@ -878,12 +878,15 @@ static int do_load(int argc, char **argv)
                        if (fd < 0)
                                goto err_free_reuse_maps;
 
-                       map_replace = reallocarray(map_replace, old_map_fds + 1,
-                                                  sizeof(*map_replace));
-                       if (!map_replace) {
+                       new_map_replace = reallocarray(map_replace,
+                                                      old_map_fds + 1,
+                                                      sizeof(*map_replace));
+                       if (!new_map_replace) {
                                p_err("mem alloc failed");
                                goto err_free_reuse_maps;
                        }
+                       map_replace = new_map_replace;
+
                        map_replace[old_map_fds].idx = idx;
                        map_replace[old_map_fds].name = name;
                        map_replace[old_map_fds].fd = fd;
diff --git a/tools/include/uapi/linux/pkt_cls.h b/tools/include/uapi/linux/pkt_cls.h
new file mode 100644 (file)
index 0000000..401d0c1
--- /dev/null
@@ -0,0 +1,612 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_PKT_CLS_H
+#define __LINUX_PKT_CLS_H
+
+#include <linux/types.h>
+#include <linux/pkt_sched.h>
+
+#define TC_COOKIE_MAX_SIZE 16
+
+/* Action attributes */
+enum {
+       TCA_ACT_UNSPEC,
+       TCA_ACT_KIND,
+       TCA_ACT_OPTIONS,
+       TCA_ACT_INDEX,
+       TCA_ACT_STATS,
+       TCA_ACT_PAD,
+       TCA_ACT_COOKIE,
+       __TCA_ACT_MAX
+};
+
+#define TCA_ACT_MAX __TCA_ACT_MAX
+#define TCA_OLD_COMPAT (TCA_ACT_MAX+1)
+#define TCA_ACT_MAX_PRIO 32
+#define TCA_ACT_BIND   1
+#define TCA_ACT_NOBIND 0
+#define TCA_ACT_UNBIND 1
+#define TCA_ACT_NOUNBIND       0
+#define TCA_ACT_REPLACE                1
+#define TCA_ACT_NOREPLACE      0
+
+#define TC_ACT_UNSPEC  (-1)
+#define TC_ACT_OK              0
+#define TC_ACT_RECLASSIFY      1
+#define TC_ACT_SHOT            2
+#define TC_ACT_PIPE            3
+#define TC_ACT_STOLEN          4
+#define TC_ACT_QUEUED          5
+#define TC_ACT_REPEAT          6
+#define TC_ACT_REDIRECT                7
+#define TC_ACT_TRAP            8 /* For hw path, this means "trap to cpu"
+                                  * and don't further process the frame
+                                  * in hardware. For sw path, this is
+                                  * equivalent of TC_ACT_STOLEN - drop
+                                  * the skb and act like everything
+                                  * is alright.
+                                  */
+#define TC_ACT_VALUE_MAX       TC_ACT_TRAP
+
+/* There is a special kind of actions called "extended actions",
+ * which need a value parameter. These have a local opcode located in
+ * the highest nibble, starting from 1. The rest of the bits
+ * are used to carry the value. These two parts together make
+ * a combined opcode.
+ */
+#define __TC_ACT_EXT_SHIFT 28
+#define __TC_ACT_EXT(local) ((local) << __TC_ACT_EXT_SHIFT)
+#define TC_ACT_EXT_VAL_MASK ((1 << __TC_ACT_EXT_SHIFT) - 1)
+#define TC_ACT_EXT_OPCODE(combined) ((combined) & (~TC_ACT_EXT_VAL_MASK))
+#define TC_ACT_EXT_CMP(combined, opcode) (TC_ACT_EXT_OPCODE(combined) == opcode)
+
+#define TC_ACT_JUMP __TC_ACT_EXT(1)
+#define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)
+#define TC_ACT_EXT_OPCODE_MAX  TC_ACT_GOTO_CHAIN
+
+/* Action type identifiers*/
+enum {
+       TCA_ID_UNSPEC=0,
+       TCA_ID_POLICE=1,
+       /* other actions go here */
+       __TCA_ID_MAX=255
+};
+
+#define TCA_ID_MAX __TCA_ID_MAX
+
+struct tc_police {
+       __u32                   index;
+       int                     action;
+#define TC_POLICE_UNSPEC       TC_ACT_UNSPEC
+#define TC_POLICE_OK           TC_ACT_OK
+#define TC_POLICE_RECLASSIFY   TC_ACT_RECLASSIFY
+#define TC_POLICE_SHOT         TC_ACT_SHOT
+#define TC_POLICE_PIPE         TC_ACT_PIPE
+
+       __u32                   limit;
+       __u32                   burst;
+       __u32                   mtu;
+       struct tc_ratespec      rate;
+       struct tc_ratespec      peakrate;
+       int                     refcnt;
+       int                     bindcnt;
+       __u32                   capab;
+};
+
+struct tcf_t {
+       __u64   install;
+       __u64   lastuse;
+       __u64   expires;
+       __u64   firstuse;
+};
+
+struct tc_cnt {
+       int                   refcnt;
+       int                   bindcnt;
+};
+
+#define tc_gen \
+       __u32                 index; \
+       __u32                 capab; \
+       int                   action; \
+       int                   refcnt; \
+       int                   bindcnt
+
+enum {
+       TCA_POLICE_UNSPEC,
+       TCA_POLICE_TBF,
+       TCA_POLICE_RATE,
+       TCA_POLICE_PEAKRATE,
+       TCA_POLICE_AVRATE,
+       TCA_POLICE_RESULT,
+       TCA_POLICE_TM,
+       TCA_POLICE_PAD,
+       __TCA_POLICE_MAX
+#define TCA_POLICE_RESULT TCA_POLICE_RESULT
+};
+
+#define TCA_POLICE_MAX (__TCA_POLICE_MAX - 1)
+
+/* tca flags definitions */
+#define TCA_CLS_FLAGS_SKIP_HW  (1 << 0) /* don't offload filter to HW */
+#define TCA_CLS_FLAGS_SKIP_SW  (1 << 1) /* don't use filter in SW */
+#define TCA_CLS_FLAGS_IN_HW    (1 << 2) /* filter is offloaded to HW */
+#define TCA_CLS_FLAGS_NOT_IN_HW (1 << 3) /* filter isn't offloaded to HW */
+#define TCA_CLS_FLAGS_VERBOSE  (1 << 4) /* verbose logging */
+
+/* U32 filters */
+
+#define TC_U32_HTID(h) ((h)&0xFFF00000)
+#define TC_U32_USERHTID(h) (TC_U32_HTID(h)>>20)
+#define TC_U32_HASH(h) (((h)>>12)&0xFF)
+#define TC_U32_NODE(h) ((h)&0xFFF)
+#define TC_U32_KEY(h) ((h)&0xFFFFF)
+#define TC_U32_UNSPEC  0
+#define TC_U32_ROOT    (0xFFF00000)
+
+enum {
+       TCA_U32_UNSPEC,
+       TCA_U32_CLASSID,
+       TCA_U32_HASH,
+       TCA_U32_LINK,
+       TCA_U32_DIVISOR,
+       TCA_U32_SEL,
+       TCA_U32_POLICE,
+       TCA_U32_ACT,
+       TCA_U32_INDEV,
+       TCA_U32_PCNT,
+       TCA_U32_MARK,
+       TCA_U32_FLAGS,
+       TCA_U32_PAD,
+       __TCA_U32_MAX
+};
+
+#define TCA_U32_MAX (__TCA_U32_MAX - 1)
+
+struct tc_u32_key {
+       __be32          mask;
+       __be32          val;
+       int             off;
+       int             offmask;
+};
+
+struct tc_u32_sel {
+       unsigned char           flags;
+       unsigned char           offshift;
+       unsigned char           nkeys;
+
+       __be16                  offmask;
+       __u16                   off;
+       short                   offoff;
+
+       short                   hoff;
+       __be32                  hmask;
+       struct tc_u32_key       keys[0];
+};
+
+struct tc_u32_mark {
+       __u32           val;
+       __u32           mask;
+       __u32           success;
+};
+
+struct tc_u32_pcnt {
+       __u64 rcnt;
+       __u64 rhit;
+       __u64 kcnts[0];
+};
+
+/* Flags */
+
+#define TC_U32_TERMINAL                1
+#define TC_U32_OFFSET          2
+#define TC_U32_VAROFFSET       4
+#define TC_U32_EAT             8
+
+#define TC_U32_MAXDEPTH 8
+
+
+/* RSVP filter */
+
+enum {
+       TCA_RSVP_UNSPEC,
+       TCA_RSVP_CLASSID,
+       TCA_RSVP_DST,
+       TCA_RSVP_SRC,
+       TCA_RSVP_PINFO,
+       TCA_RSVP_POLICE,
+       TCA_RSVP_ACT,
+       __TCA_RSVP_MAX
+};
+
+#define TCA_RSVP_MAX (__TCA_RSVP_MAX - 1 )
+
+struct tc_rsvp_gpi {
+       __u32   key;
+       __u32   mask;
+       int     offset;
+};
+
+struct tc_rsvp_pinfo {
+       struct tc_rsvp_gpi dpi;
+       struct tc_rsvp_gpi spi;
+       __u8    protocol;
+       __u8    tunnelid;
+       __u8    tunnelhdr;
+       __u8    pad;
+};
+
+/* ROUTE filter */
+
+enum {
+       TCA_ROUTE4_UNSPEC,
+       TCA_ROUTE4_CLASSID,
+       TCA_ROUTE4_TO,
+       TCA_ROUTE4_FROM,
+       TCA_ROUTE4_IIF,
+       TCA_ROUTE4_POLICE,
+       TCA_ROUTE4_ACT,
+       __TCA_ROUTE4_MAX
+};
+
+#define TCA_ROUTE4_MAX (__TCA_ROUTE4_MAX - 1)
+
+
+/* FW filter */
+
+enum {
+       TCA_FW_UNSPEC,
+       TCA_FW_CLASSID,
+       TCA_FW_POLICE,
+       TCA_FW_INDEV, /*  used by CONFIG_NET_CLS_IND */
+       TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */
+       TCA_FW_MASK,
+       __TCA_FW_MAX
+};
+
+#define TCA_FW_MAX (__TCA_FW_MAX - 1)
+
+/* TC index filter */
+
+enum {
+       TCA_TCINDEX_UNSPEC,
+       TCA_TCINDEX_HASH,
+       TCA_TCINDEX_MASK,
+       TCA_TCINDEX_SHIFT,
+       TCA_TCINDEX_FALL_THROUGH,
+       TCA_TCINDEX_CLASSID,
+       TCA_TCINDEX_POLICE,
+       TCA_TCINDEX_ACT,
+       __TCA_TCINDEX_MAX
+};
+
+#define TCA_TCINDEX_MAX     (__TCA_TCINDEX_MAX - 1)
+
+/* Flow filter */
+
+enum {
+       FLOW_KEY_SRC,
+       FLOW_KEY_DST,
+       FLOW_KEY_PROTO,
+       FLOW_KEY_PROTO_SRC,
+       FLOW_KEY_PROTO_DST,
+       FLOW_KEY_IIF,
+       FLOW_KEY_PRIORITY,
+       FLOW_KEY_MARK,
+       FLOW_KEY_NFCT,
+       FLOW_KEY_NFCT_SRC,
+       FLOW_KEY_NFCT_DST,
+       FLOW_KEY_NFCT_PROTO_SRC,
+       FLOW_KEY_NFCT_PROTO_DST,
+       FLOW_KEY_RTCLASSID,
+       FLOW_KEY_SKUID,
+       FLOW_KEY_SKGID,
+       FLOW_KEY_VLAN_TAG,
+       FLOW_KEY_RXHASH,
+       __FLOW_KEY_MAX,
+};
+
+#define FLOW_KEY_MAX   (__FLOW_KEY_MAX - 1)
+
+enum {
+       FLOW_MODE_MAP,
+       FLOW_MODE_HASH,
+};
+
+enum {
+       TCA_FLOW_UNSPEC,
+       TCA_FLOW_KEYS,
+       TCA_FLOW_MODE,
+       TCA_FLOW_BASECLASS,
+       TCA_FLOW_RSHIFT,
+       TCA_FLOW_ADDEND,
+       TCA_FLOW_MASK,
+       TCA_FLOW_XOR,
+       TCA_FLOW_DIVISOR,
+       TCA_FLOW_ACT,
+       TCA_FLOW_POLICE,
+       TCA_FLOW_EMATCHES,
+       TCA_FLOW_PERTURB,
+       __TCA_FLOW_MAX
+};
+
+#define TCA_FLOW_MAX   (__TCA_FLOW_MAX - 1)
+
+/* Basic filter */
+
+enum {
+       TCA_BASIC_UNSPEC,
+       TCA_BASIC_CLASSID,
+       TCA_BASIC_EMATCHES,
+       TCA_BASIC_ACT,
+       TCA_BASIC_POLICE,
+       __TCA_BASIC_MAX
+};
+
+#define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1)
+
+
+/* Cgroup classifier */
+
+enum {
+       TCA_CGROUP_UNSPEC,
+       TCA_CGROUP_ACT,
+       TCA_CGROUP_POLICE,
+       TCA_CGROUP_EMATCHES,
+       __TCA_CGROUP_MAX,
+};
+
+#define TCA_CGROUP_MAX (__TCA_CGROUP_MAX - 1)
+
+/* BPF classifier */
+
+#define TCA_BPF_FLAG_ACT_DIRECT                (1 << 0)
+
+enum {
+       TCA_BPF_UNSPEC,
+       TCA_BPF_ACT,
+       TCA_BPF_POLICE,
+       TCA_BPF_CLASSID,
+       TCA_BPF_OPS_LEN,
+       TCA_BPF_OPS,
+       TCA_BPF_FD,
+       TCA_BPF_NAME,
+       TCA_BPF_FLAGS,
+       TCA_BPF_FLAGS_GEN,
+       TCA_BPF_TAG,
+       TCA_BPF_ID,
+       __TCA_BPF_MAX,
+};
+
+#define TCA_BPF_MAX (__TCA_BPF_MAX - 1)
+
+/* Flower classifier */
+
+enum {
+       TCA_FLOWER_UNSPEC,
+       TCA_FLOWER_CLASSID,
+       TCA_FLOWER_INDEV,
+       TCA_FLOWER_ACT,
+       TCA_FLOWER_KEY_ETH_DST,         /* ETH_ALEN */
+       TCA_FLOWER_KEY_ETH_DST_MASK,    /* ETH_ALEN */
+       TCA_FLOWER_KEY_ETH_SRC,         /* ETH_ALEN */
+       TCA_FLOWER_KEY_ETH_SRC_MASK,    /* ETH_ALEN */
+       TCA_FLOWER_KEY_ETH_TYPE,        /* be16 */
+       TCA_FLOWER_KEY_IP_PROTO,        /* u8 */
+       TCA_FLOWER_KEY_IPV4_SRC,        /* be32 */
+       TCA_FLOWER_KEY_IPV4_SRC_MASK,   /* be32 */
+       TCA_FLOWER_KEY_IPV4_DST,        /* be32 */
+       TCA_FLOWER_KEY_IPV4_DST_MASK,   /* be32 */
+       TCA_FLOWER_KEY_IPV6_SRC,        /* struct in6_addr */
+       TCA_FLOWER_KEY_IPV6_SRC_MASK,   /* struct in6_addr */
+       TCA_FLOWER_KEY_IPV6_DST,        /* struct in6_addr */
+       TCA_FLOWER_KEY_IPV6_DST_MASK,   /* struct in6_addr */
+       TCA_FLOWER_KEY_TCP_SRC,         /* be16 */
+       TCA_FLOWER_KEY_TCP_DST,         /* be16 */
+       TCA_FLOWER_KEY_UDP_SRC,         /* be16 */
+       TCA_FLOWER_KEY_UDP_DST,         /* be16 */
+
+       TCA_FLOWER_FLAGS,
+       TCA_FLOWER_KEY_VLAN_ID,         /* be16 */
+       TCA_FLOWER_KEY_VLAN_PRIO,       /* u8   */
+       TCA_FLOWER_KEY_VLAN_ETH_TYPE,   /* be16 */
+
+       TCA_FLOWER_KEY_ENC_KEY_ID,      /* be32 */
+       TCA_FLOWER_KEY_ENC_IPV4_SRC,    /* be32 */
+       TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,/* be32 */
+       TCA_FLOWER_KEY_ENC_IPV4_DST,    /* be32 */
+       TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,/* be32 */
+       TCA_FLOWER_KEY_ENC_IPV6_SRC,    /* struct in6_addr */
+       TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,/* struct in6_addr */
+       TCA_FLOWER_KEY_ENC_IPV6_DST,    /* struct in6_addr */
+       TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,/* struct in6_addr */
+
+       TCA_FLOWER_KEY_TCP_SRC_MASK,    /* be16 */
+       TCA_FLOWER_KEY_TCP_DST_MASK,    /* be16 */
+       TCA_FLOWER_KEY_UDP_SRC_MASK,    /* be16 */
+       TCA_FLOWER_KEY_UDP_DST_MASK,    /* be16 */
+       TCA_FLOWER_KEY_SCTP_SRC_MASK,   /* be16 */
+       TCA_FLOWER_KEY_SCTP_DST_MASK,   /* be16 */
+
+       TCA_FLOWER_KEY_SCTP_SRC,        /* be16 */
+       TCA_FLOWER_KEY_SCTP_DST,        /* be16 */
+
+       TCA_FLOWER_KEY_ENC_UDP_SRC_PORT,        /* be16 */
+       TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK,   /* be16 */
+       TCA_FLOWER_KEY_ENC_UDP_DST_PORT,        /* be16 */
+       TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK,   /* be16 */
+
+       TCA_FLOWER_KEY_FLAGS,           /* be32 */
+       TCA_FLOWER_KEY_FLAGS_MASK,      /* be32 */
+
+       TCA_FLOWER_KEY_ICMPV4_CODE,     /* u8 */
+       TCA_FLOWER_KEY_ICMPV4_CODE_MASK,/* u8 */
+       TCA_FLOWER_KEY_ICMPV4_TYPE,     /* u8 */
+       TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,/* u8 */
+       TCA_FLOWER_KEY_ICMPV6_CODE,     /* u8 */
+       TCA_FLOWER_KEY_ICMPV6_CODE_MASK,/* u8 */
+       TCA_FLOWER_KEY_ICMPV6_TYPE,     /* u8 */
+       TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,/* u8 */
+
+       TCA_FLOWER_KEY_ARP_SIP,         /* be32 */
+       TCA_FLOWER_KEY_ARP_SIP_MASK,    /* be32 */
+       TCA_FLOWER_KEY_ARP_TIP,         /* be32 */
+       TCA_FLOWER_KEY_ARP_TIP_MASK,    /* be32 */
+       TCA_FLOWER_KEY_ARP_OP,          /* u8 */
+       TCA_FLOWER_KEY_ARP_OP_MASK,     /* u8 */
+       TCA_FLOWER_KEY_ARP_SHA,         /* ETH_ALEN */
+       TCA_FLOWER_KEY_ARP_SHA_MASK,    /* ETH_ALEN */
+       TCA_FLOWER_KEY_ARP_THA,         /* ETH_ALEN */
+       TCA_FLOWER_KEY_ARP_THA_MASK,    /* ETH_ALEN */
+
+       TCA_FLOWER_KEY_MPLS_TTL,        /* u8 - 8 bits */
+       TCA_FLOWER_KEY_MPLS_BOS,        /* u8 - 1 bit */
+       TCA_FLOWER_KEY_MPLS_TC,         /* u8 - 3 bits */
+       TCA_FLOWER_KEY_MPLS_LABEL,      /* be32 - 20 bits */
+
+       TCA_FLOWER_KEY_TCP_FLAGS,       /* be16 */
+       TCA_FLOWER_KEY_TCP_FLAGS_MASK,  /* be16 */
+
+       TCA_FLOWER_KEY_IP_TOS,          /* u8 */
+       TCA_FLOWER_KEY_IP_TOS_MASK,     /* u8 */
+       TCA_FLOWER_KEY_IP_TTL,          /* u8 */
+       TCA_FLOWER_KEY_IP_TTL_MASK,     /* u8 */
+
+       TCA_FLOWER_KEY_CVLAN_ID,        /* be16 */
+       TCA_FLOWER_KEY_CVLAN_PRIO,      /* u8   */
+       TCA_FLOWER_KEY_CVLAN_ETH_TYPE,  /* be16 */
+
+       TCA_FLOWER_KEY_ENC_IP_TOS,      /* u8 */
+       TCA_FLOWER_KEY_ENC_IP_TOS_MASK, /* u8 */
+       TCA_FLOWER_KEY_ENC_IP_TTL,      /* u8 */
+       TCA_FLOWER_KEY_ENC_IP_TTL_MASK, /* u8 */
+
+       TCA_FLOWER_KEY_ENC_OPTS,
+       TCA_FLOWER_KEY_ENC_OPTS_MASK,
+
+       TCA_FLOWER_IN_HW_COUNT,
+
+       __TCA_FLOWER_MAX,
+};
+
+#define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
+
+enum {
+       TCA_FLOWER_KEY_ENC_OPTS_UNSPEC,
+       TCA_FLOWER_KEY_ENC_OPTS_GENEVE, /* Nested
+                                        * TCA_FLOWER_KEY_ENC_OPT_GENEVE_
+                                        * attributes
+                                        */
+       __TCA_FLOWER_KEY_ENC_OPTS_MAX,
+};
+
+#define TCA_FLOWER_KEY_ENC_OPTS_MAX (__TCA_FLOWER_KEY_ENC_OPTS_MAX - 1)
+
+enum {
+       TCA_FLOWER_KEY_ENC_OPT_GENEVE_UNSPEC,
+       TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS,            /* u16 */
+       TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE,             /* u8 */
+       TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA,             /* 4 to 128 bytes */
+
+       __TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX,
+};
+
+#define TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX \
+               (__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX - 1)
+
+enum {
+       TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
+       TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
+};
+
+/* Match-all classifier */
+
+enum {
+       TCA_MATCHALL_UNSPEC,
+       TCA_MATCHALL_CLASSID,
+       TCA_MATCHALL_ACT,
+       TCA_MATCHALL_FLAGS,
+       __TCA_MATCHALL_MAX,
+};
+
+#define TCA_MATCHALL_MAX (__TCA_MATCHALL_MAX - 1)
+
+/* Extended Matches */
+
+struct tcf_ematch_tree_hdr {
+       __u16           nmatches;
+       __u16           progid;
+};
+
+enum {
+       TCA_EMATCH_TREE_UNSPEC,
+       TCA_EMATCH_TREE_HDR,
+       TCA_EMATCH_TREE_LIST,
+       __TCA_EMATCH_TREE_MAX
+};
+#define TCA_EMATCH_TREE_MAX (__TCA_EMATCH_TREE_MAX - 1)
+
+struct tcf_ematch_hdr {
+       __u16           matchid;
+       __u16           kind;
+       __u16           flags;
+       __u16           pad; /* currently unused */
+};
+
+/*  0                   1
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 
+ * +-----------------------+-+-+---+
+ * |         Unused        |S|I| R |
+ * +-----------------------+-+-+---+
+ *
+ * R(2) ::= relation to next ematch
+ *          where: 0 0 END (last ematch)
+ *                 0 1 AND
+ *                 1 0 OR
+ *                 1 1 Unused (invalid)
+ * I(1) ::= invert result
+ * S(1) ::= simple payload
+ */
+#define TCF_EM_REL_END 0
+#define TCF_EM_REL_AND (1<<0)
+#define TCF_EM_REL_OR  (1<<1)
+#define TCF_EM_INVERT  (1<<2)
+#define TCF_EM_SIMPLE  (1<<3)
+
+#define TCF_EM_REL_MASK        3
+#define TCF_EM_REL_VALID(v) (((v) & TCF_EM_REL_MASK) != TCF_EM_REL_MASK)
+
+enum {
+       TCF_LAYER_LINK,
+       TCF_LAYER_NETWORK,
+       TCF_LAYER_TRANSPORT,
+       __TCF_LAYER_MAX
+};
+#define TCF_LAYER_MAX (__TCF_LAYER_MAX - 1)
+
+/* Ematch type assignments
+ *   1..32767          Reserved for ematches inside kernel tree
+ *   32768..65535      Free to use, not reliable
+ */
+#define        TCF_EM_CONTAINER        0
+#define        TCF_EM_CMP              1
+#define        TCF_EM_NBYTE            2
+#define        TCF_EM_U32              3
+#define        TCF_EM_META             4
+#define        TCF_EM_TEXT             5
+#define        TCF_EM_VLAN             6
+#define        TCF_EM_CANID            7
+#define        TCF_EM_IPSET            8
+#define        TCF_EM_IPT              9
+#define        TCF_EM_MAX              9
+
+enum {
+       TCF_EM_PROG_TC
+};
+
+enum {
+       TCF_EM_OPND_EQ,
+       TCF_EM_OPND_GT,
+       TCF_EM_OPND_LT
+};
+
+#endif
diff --git a/tools/include/uapi/linux/tc_act/tc_bpf.h b/tools/include/uapi/linux/tc_act/tc_bpf.h
new file mode 100644 (file)
index 0000000..6e89a5d
--- /dev/null
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2015 Jiri Pirko <jiri@resnulli.us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __LINUX_TC_BPF_H
+#define __LINUX_TC_BPF_H
+
+#include <linux/pkt_cls.h>
+
+#define TCA_ACT_BPF 13
+
+struct tc_act_bpf {
+       tc_gen;
+};
+
+enum {
+       TCA_ACT_BPF_UNSPEC,
+       TCA_ACT_BPF_TM,
+       TCA_ACT_BPF_PARMS,
+       TCA_ACT_BPF_OPS_LEN,
+       TCA_ACT_BPF_OPS,
+       TCA_ACT_BPF_FD,
+       TCA_ACT_BPF_NAME,
+       TCA_ACT_BPF_PAD,
+       TCA_ACT_BPF_TAG,
+       TCA_ACT_BPF_ID,
+       __TCA_ACT_BPF_MAX,
+};
+#define TCA_ACT_BPF_MAX (__TCA_ACT_BPF_MAX - 1)
+
+#endif
index 1dd5f4fcffd53f375ba00479bfed37d867399c4a..db66a952c173958395f9134c1fa029fbbd6d3950 100644 (file)
@@ -129,7 +129,7 @@ WARNINGS += $(call cc-supports,-Wno-pointer-sign)
 WARNINGS += $(call cc-supports,-Wdeclaration-after-statement)
 WARNINGS += -Wshadow
 
-CFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \
+override CFLAGS += -DVERSION=\"$(VERSION)\" -DPACKAGE=\"$(PACKAGE)\" \
                -DPACKAGE_BUGREPORT=\"$(PACKAGE_BUGREPORT)\" -D_GNU_SOURCE
 
 UTIL_OBJS =  utils/helpers/amd.o utils/helpers/msr.o \
@@ -156,12 +156,12 @@ LIB_SRC =         lib/cpufreq.c lib/cpupower.c lib/cpuidle.c
 LIB_OBJS =     lib/cpufreq.o lib/cpupower.o lib/cpuidle.o
 LIB_OBJS :=    $(addprefix $(OUTPUT),$(LIB_OBJS))
 
-CFLAGS +=      -pipe
+override CFLAGS +=     -pipe
 
 ifeq ($(strip $(NLS)),true)
        INSTALL_NLS += install-gmo
        COMPILE_NLS += create-gmo
-       CFLAGS += -DNLS
+       override CFLAGS += -DNLS
 endif
 
 ifeq ($(strip $(CPUFREQ_BENCH)),true)
@@ -175,7 +175,7 @@ ifeq ($(strip $(STATIC)),true)
         UTIL_SRC += $(LIB_SRC)
 endif
 
-CFLAGS += $(WARNINGS)
+override CFLAGS += $(WARNINGS)
 
 ifeq ($(strip $(V)),false)
        QUIET=@
@@ -188,10 +188,10 @@ export QUIET ECHO
 
 # if DEBUG is enabled, then we do not strip or optimize
 ifeq ($(strip $(DEBUG)),true)
-       CFLAGS += -O1 -g -DDEBUG
+       override CFLAGS += -O1 -g -DDEBUG
        STRIPCMD = /bin/true -Since_we_are_debugging
 else
-       CFLAGS += $(OPTIMIZATION) -fomit-frame-pointer
+       override CFLAGS += $(OPTIMIZATION) -fomit-frame-pointer
        STRIPCMD = $(STRIP) -s --remove-section=.note --remove-section=.comment
 endif
 
index d79ab161cc75f91ab6c7c1f0344387f14216663f..f68b4bc5527397f285cb1b7bedcf5347ebca52cf 100644 (file)
@@ -9,7 +9,7 @@ endif
 ifeq ($(strip $(STATIC)),true)
 LIBS = -L../ -L$(OUTPUT) -lm
 OBJS = $(OUTPUT)main.o $(OUTPUT)parse.o $(OUTPUT)system.o $(OUTPUT)benchmark.o \
-       $(OUTPUT)../lib/cpufreq.o $(OUTPUT)../lib/sysfs.o
+       $(OUTPUT)../lib/cpufreq.o $(OUTPUT)../lib/cpupower.o
 else
 LIBS = -L../ -L$(OUTPUT) -lm -lcpupower
 OBJS = $(OUTPUT)main.o $(OUTPUT)parse.o $(OUTPUT)system.o $(OUTPUT)benchmark.o
index 59af84b8ef455dfb33053948ec0fdef24a70f7e9..b1b6c43644e79be755cc867fb91717ecd1e631c3 100644 (file)
@@ -13,10 +13,10 @@ INSTALL = /usr/bin/install
 default: all
 
 $(OUTPUT)centrino-decode: ../i386/centrino-decode.c
-       $(CC) $(CFLAGS) -o $@ $<
+       $(CC) $(CFLAGS) -o $@ $(LDFLAGS) $<
 
 $(OUTPUT)powernow-k8-decode: ../i386/powernow-k8-decode.c
-       $(CC) $(CFLAGS) -o $@ $<
+       $(CC) $(CFLAGS) -o $@ $(LDFLAGS) $<
 
 all: $(OUTPUT)centrino-decode $(OUTPUT)powernow-k8-decode
 
index 1b993fe1ce2372a5e6fed1d057b6b2a1dc64d5d6..0c0f3e3f0d8038e138077b40d428faff6083cff8 100644 (file)
@@ -28,7 +28,7 @@ static unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname,
 
        snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
                         cpu, fname);
-       return sysfs_read_file(path, buf, buflen);
+       return cpupower_read_sysfs(path, buf, buflen);
 }
 
 /* helper function to write a new value to a /sys file */
index 9bd4c7655fdb2a4942d6aa0012174f232e25ee4f..852d25462388c2d61b67bf5c4ca162d591b16281 100644 (file)
@@ -319,7 +319,7 @@ static unsigned int sysfs_cpuidle_read_file(const char *fname, char *buf,
 
        snprintf(path, sizeof(path), PATH_TO_CPU "cpuidle/%s", fname);
 
-       return sysfs_read_file(path, buf, buflen);
+       return cpupower_read_sysfs(path, buf, buflen);
 }
 
 
index 9c395ec924def2538e973eab7724472eea34cb8d..9711d628b0f440151e239d1986bdce4fb8be59ef 100644 (file)
@@ -15,7 +15,7 @@
 #include "cpupower.h"
 #include "cpupower_intern.h"
 
-unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
+unsigned int cpupower_read_sysfs(const char *path, char *buf, size_t buflen)
 {
        int fd;
        ssize_t numread;
@@ -95,7 +95,7 @@ static int sysfs_topology_read_file(unsigned int cpu, const char *fname, int *re
 
        snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/topology/%s",
                         cpu, fname);
-       if (sysfs_read_file(path, linebuf, MAX_LINE_LEN) == 0)
+       if (cpupower_read_sysfs(path, linebuf, MAX_LINE_LEN) == 0)
                return -1;
        *result = strtol(linebuf, &endp, 0);
        if (endp == linebuf || errno == ERANGE)
index 92affdfbe4174e13f5a5fecded202d597b256dbc..4887c76d23f868c060364dab8795702570a91e6f 100644 (file)
@@ -3,4 +3,4 @@
 #define MAX_LINE_LEN 4096
 #define SYSFS_PATH_MAX 255
 
-unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen);
+unsigned int cpupower_read_sysfs(const char *path, char *buf, size_t buflen);
index 9527d47a1070ecbabc716273d6e46f34e18c1ca1..01ec04bf91b592e470c26512e744d5e59211a3d4 100644 (file)
@@ -140,8 +140,8 @@ static u32 handle[] = {
        [6] = NFIT_DIMM_HANDLE(1, 0, 0, 0, 1),
 };
 
-static unsigned long dimm_fail_cmd_flags[NUM_DCR];
-static int dimm_fail_cmd_code[NUM_DCR];
+static unsigned long dimm_fail_cmd_flags[ARRAY_SIZE(handle)];
+static int dimm_fail_cmd_code[ARRAY_SIZE(handle)];
 
 static const struct nd_intel_smart smart_def = {
        .flags = ND_INTEL_SMART_HEALTH_VALID
@@ -205,7 +205,7 @@ struct nfit_test {
                unsigned long deadline;
                spinlock_t lock;
        } ars_state;
-       struct device *dimm_dev[NUM_DCR];
+       struct device *dimm_dev[ARRAY_SIZE(handle)];
        struct nd_intel_smart *smart;
        struct nd_intel_smart_threshold *smart_threshold;
        struct badrange badrange;
@@ -2680,7 +2680,7 @@ static int nfit_test_probe(struct platform_device *pdev)
                u32 nfit_handle = __to_nfit_memdev(nfit_mem)->device_handle;
                int i;
 
-               for (i = 0; i < NUM_DCR; i++)
+               for (i = 0; i < ARRAY_SIZE(handle); i++)
                        if (nfit_handle == handle[i])
                                dev_set_drvdata(nfit_test->dimm_dev[i],
                                                nfit_mem);
index 7887df6933998c62d6d81926066918728d704c8c..44ed7f29f8ab6cec40c83c02c01d28ca36c36492 100644 (file)
@@ -81,7 +81,10 @@ int main(int argc, char **argv)
                goto err;
        }
 
-       assert(system("ping localhost -6 -c 10000 -f -q > /dev/null") == 0);
+       if (system("which ping6 &>/dev/null") == 0)
+               assert(!system("ping6 localhost -c 10000 -f -q > /dev/null"));
+       else
+               assert(!system("ping -6 localhost -c 10000 -f -q > /dev/null"));
 
        if (bpf_prog_query(cgroup_fd, BPF_CGROUP_INET_EGRESS, 0, NULL, NULL,
                           &prog_cnt)) {
index 6f61df62f690c69adceb2c328b231ab39b8b9c49..550b7e46bf4a4143059cc7ea58643adf11251353 100644 (file)
@@ -13896,6 +13896,25 @@ static struct bpf_test tests[] = {
                .prog_type = BPF_PROG_TYPE_SCHED_CLS,
                .result = ACCEPT,
        },
+       {
+               "calls: ctx read at start of subprog",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 5),
+                       BPF_JMP_REG(BPF_JSGT, BPF_REG_0, BPF_REG_0, 0),
+                       BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
+                       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_9, BPF_REG_1, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
+               .errstr_unpriv = "function calls to other bpf functions are allowed for root only",
+               .result_unpriv = REJECT,
+               .result = ACCEPT,
+       },
 };
 
 static int probe_filter_length(const struct bpf_insn *fp)
index 1b0e9e9a2ddce5a3377ded7dad656202586339dc..f2fa101c5a6ac149bd93c4f8140aed76798b8e69 100644 (file)
@@ -47,8 +47,9 @@ static int ok(void)
        return 0;
 }
 
-#define REG_POISON     0x5a5aUL
-#define POISONED_REG(n)        ((REG_POISON << 48) | ((n) << 32) | (REG_POISON << 16) | (n))
+#define REG_POISON     0x5a5a
+#define POISONED_REG(n)        ((((unsigned long)REG_POISON) << 48) | ((n) << 32) | \
+                        (((unsigned long)REG_POISON) << 16) | (n))
 
 static inline void poison_regs(void)
 {
@@ -105,6 +106,20 @@ static void dump_regs(void)
        }
 }
 
+#ifdef _CALL_AIXDESC
+struct opd {
+       unsigned long ip;
+       unsigned long toc;
+       unsigned long env;
+};
+static struct opd bad_opd = {
+       .ip = BAD_NIP,
+};
+#define BAD_FUNC (&bad_opd)
+#else
+#define BAD_FUNC BAD_NIP
+#endif
+
 int test_wild_bctr(void)
 {
        int (*func_ptr)(void);
@@ -133,7 +148,7 @@ int test_wild_bctr(void)
 
                poison_regs();
 
-               func_ptr = (int (*)(void))BAD_NIP;
+               func_ptr = (int (*)(void))BAD_FUNC;
                func_ptr();
 
                FAIL_IF(1); /* we didn't segv? */
index 87a04a8a5945c21222a21c103e5ed88bff0f5c67..7607ba3e3cbe4eba89dfe5a35badae9182b974a9 100755 (executable)
@@ -134,9 +134,9 @@ def exec_cmd(args, pm, stage, command):
     (rawout, serr) = proc.communicate()
 
     if proc.returncode != 0 and len(serr) > 0:
-        foutput = serr.decode("utf-8")
+        foutput = serr.decode("utf-8", errors="ignore")
     else:
-        foutput = rawout.decode("utf-8")
+        foutput = rawout.decode("utf-8", errors="ignore")
 
     proc.stdout.close()
     proc.stderr.close()
@@ -169,6 +169,8 @@ def prepare_env(args, pm, stage, prefix, cmdlist, output = None):
                   file=sys.stderr)
             print("\n{} *** Error message: \"{}\"".format(prefix, foutput),
                   file=sys.stderr)
+            print("returncode {}; expected {}".format(proc.returncode,
+                                                      exit_codes))
             print("\n{} *** Aborting test run.".format(prefix), file=sys.stderr)
             print("\n\n{} *** stdout ***".format(proc.stdout), file=sys.stderr)
             print("\n\n{} *** stderr ***".format(proc.stderr), file=sys.stderr)
@@ -195,12 +197,18 @@ def run_one_test(pm, args, index, tidx):
         print('-----> execute stage')
     pm.call_pre_execute()
     (p, procout) = exec_cmd(args, pm, 'execute', tidx["cmdUnderTest"])
-    exit_code = p.returncode
+    if p:
+        exit_code = p.returncode
+    else:
+        exit_code = None
+
     pm.call_post_execute()
 
-    if (exit_code != int(tidx["expExitCode"])):
+    if (exit_code is None or exit_code != int(tidx["expExitCode"])):
         result = False
-        print("exit:", exit_code, int(tidx["expExitCode"]))
+        print("exit: {!r}".format(exit_code))
+        print("exit: {}".format(int(tidx["expExitCode"])))
+        #print("exit: {!r} {}".format(exit_code, int(tidx["expExitCode"])))
         print(procout)
     else:
         if args.verbose > 0: