Merge tag 'mmc-v4.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 7 Oct 2017 17:03:03 +0000 (10:03 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 7 Oct 2017 17:03:03 +0000 (10:03 -0700)
Pull MMC fixes from Ulf Hansson:
 "MMC core:

   - Fix driver strength selection when selecting hs400es

   - Delete bounce buffer handling:

     This change fixes a problem related to how bounce buffers are being
     allocated. However, instead of trying to fix that, let's just
     remove the mmc bounce buffer code altogether, as it has practically
     no use.

  MMC host:

   - meson-gx: A couple of fixes related to clock/phase/tuning

   - sdhci-xenon: Fix clock resource by adding an optional bus clock"

* tag 'mmc-v4.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: sdhci-xenon: Fix clock resource by adding an optional bus clock
  mmc: meson-gx: include tx phase in the tuning process
  mmc: meson-gx: fix rx phase reset
  mmc: meson-gx: make sure the clock is rounded down
  mmc: Delete bounce buffer handling
  mmc: core: add driver strength selection when selecting hs400es

395 files changed:
.mailmap
Documentation/ABI/testing/sysfs-power
Documentation/core-api/workqueue.rst
Documentation/device-mapper/dm-raid.txt
Documentation/devicetree/bindings/net/marvell-pp2.txt
Documentation/devicetree/bindings/net/rockchip-dwmac.txt
Documentation/devicetree/bindings/reset/snps,hsdk-reset.txt [new file with mode: 0644]
Documentation/devicetree/bindings/serial/renesas,sci-serial.txt
Documentation/driver-model/driver.txt
Documentation/filesystems/overlayfs.txt
Documentation/filesystems/sysfs.txt
MAINTAINERS
arch/alpha/include/asm/mmu_context.h
arch/arc/Kconfig
arch/arc/Makefile
arch/arc/boot/dts/axs10x_mb.dtsi
arch/arc/boot/dts/hsdk.dts
arch/arc/configs/axs101_defconfig
arch/arc/configs/axs103_defconfig
arch/arc/configs/axs103_smp_defconfig
arch/arc/configs/haps_hs_smp_defconfig
arch/arc/configs/hsdk_defconfig
arch/arc/configs/vdk_hs38_defconfig
arch/arc/configs/vdk_hs38_smp_defconfig
arch/arc/include/asm/arcregs.h
arch/arc/kernel/setup.c
arch/arc/plat-axs10x/axs10x.c
arch/arc/plat-hsdk/Kconfig
arch/arc/plat-hsdk/platform.c
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am43x-epos-evm.dts
arch/arm/boot/dts/at91-sama5d27_som1_ek.dts
arch/arm/boot/dts/da850-evm.dts
arch/arm/boot/dts/dra7xx-clocks.dtsi
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/stm32429i-eval.dts
arch/arm/boot/dts/stm32f4-pinctrl.dtsi [new file with mode: 0644]
arch/arm/boot/dts/stm32f429-disco.dts
arch/arm/boot/dts/stm32f429-pinctrl.dtsi [new file with mode: 0644]
arch/arm/boot/dts/stm32f429.dtsi
arch/arm/boot/dts/stm32f469-disco.dts
arch/arm/boot/dts/stm32f469-pinctrl.dtsi [new file with mode: 0644]
arch/arm/configs/gemini_defconfig
arch/arm/configs/pxa_defconfig
arch/arm/configs/viper_defconfig
arch/arm/configs/zeus_defconfig
arch/arm/mach-at91/pm.c
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-hwacom-amazetv.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
arch/arm64/boot/dts/amlogic/meson-gxm-rbox-pro.dts
arch/arm64/boot/dts/marvell/armada-ap806.dtsi
arch/arm64/boot/dts/rockchip/rk3368.dtsi
arch/arm64/boot/dts/rockchip/rk3399.dtsi
arch/arm64/include/asm/memory.h
arch/arm64/kernel/armv8_deprecated.c
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/fpsimd.c
arch/arm64/mm/fault.c
arch/m32r/Kconfig
arch/m32r/kernel/traps.c
arch/parisc/kernel/process.c
arch/powerpc/kernel/dt_cpu_ftrs.c
arch/powerpc/kernel/mce_power.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/watchdog.c
arch/powerpc/kvm/book3s_xive.c
arch/powerpc/kvm/book3s_xive.h
arch/powerpc/mm/pgtable_32.c
arch/powerpc/platforms/powernv/setup.c
arch/powerpc/sysdev/fsl_rio.c
arch/powerpc/sysdev/fsl_rmu.c
arch/powerpc/sysdev/xive/common.c
arch/powerpc/sysdev/xive/spapr.c
arch/sh/include/cpu-sh2a/cpu/sh7264.h
arch/sh/include/cpu-sh2a/cpu/sh7269.h
arch/sh/include/cpu-sh4/cpu/sh7722.h
arch/sh/include/cpu-sh4/cpu/sh7757.h
arch/x86/events/intel/core.c
arch/x86/include/asm/kvm_para.h
arch/x86/kernel/kvm.c
arch/x86/kvm/Kconfig
arch/x86/kvm/emulate.c
arch/x86/kvm/mmu.c
arch/x86/net/bpf_jit_comp.c
block/blk-mq-debugfs.c
block/blk-throttle.c
block/bsg-lib.c
drivers/acpi/arm64/iort.c
drivers/android/binder.c
drivers/android/binder_alloc.c
drivers/ata/ahci.c
drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/auxdisplay/charlcd.c
drivers/auxdisplay/panel.c
drivers/base/arch_topology.c
drivers/base/platform.c
drivers/block/Kconfig
drivers/block/nbd.c
drivers/block/zram/zram_drv.c
drivers/clk/clk-bulk.c
drivers/clk/rockchip/clk-rk3128.c
drivers/clk/samsung/clk-exynos4.c
drivers/fpga/altera-cvp.c
drivers/gpu/drm/i915/intel_audio.c
drivers/gpu/drm/i915/intel_bios.c
drivers/gpu/drm/i915/intel_csr.c
drivers/gpu/drm/i915/intel_ddi.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dpio_phy.c
drivers/gpu/drm/i915/intel_modes.c
drivers/gpu/drm/i915/intel_runtime_pm.c
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
drivers/hid/hid-ids.h
drivers/hid/hid-multitouch.c
drivers/hid/hid-rmi.c
drivers/hid/hidraw.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
drivers/hv/channel_mgmt.c
drivers/hv/hv_fcopy.c
drivers/hwmon/xgene-hwmon.c
drivers/hwtracing/intel_th/pci.c
drivers/hwtracing/stm/core.c
drivers/i2c/busses/i2c-img-scb.c
drivers/ide/ide-probe.c
drivers/ide/ide-scan-pci.c
drivers/ide/setup-pci.c
drivers/iio/adc/ad7793.c
drivers/iio/adc/ad_sigma_delta.c
drivers/iio/adc/mcp320x.c
drivers/iio/adc/stm32-adc.c
drivers/iio/adc/ti-ads1015.c
drivers/iio/adc/twl4030-madc.c
drivers/iio/common/st_sensors/st_sensors_core.c
drivers/iio/industrialio-core.c
drivers/iio/magnetometer/st_magn_core.c
drivers/iio/pressure/bmp280-core.c
drivers/iio/trigger/stm32-timer-trigger.c
drivers/infiniband/core/iwpm_msg.c
drivers/infiniband/core/iwpm_util.c
drivers/infiniband/hw/i40iw/i40iw_ctrl.c
drivers/infiniband/hw/i40iw/i40iw_p.h
drivers/infiniband/hw/i40iw/i40iw_puda.c
drivers/infiniband/hw/i40iw/i40iw_verbs.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/qedr/qedr.h
drivers/infiniband/hw/qedr/qedr_cm.c
drivers/md/bcache/closure.c
drivers/md/dm-core.h
drivers/md/dm-crypt.c
drivers/md/dm-ioctl.c
drivers/md/dm-raid.c
drivers/md/dm.c
drivers/media/rc/ir-sharp-decoder.c
drivers/misc/cxl/cxllib.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/ethernet/aquantia/atlantic/aq_cfg.h
drivers/net/ethernet/aquantia/atlantic/aq_nic.c
drivers/net/ethernet/aquantia/atlantic/aq_nic.h
drivers/net/ethernet/aquantia/atlantic/aq_ring.c
drivers/net/ethernet/aquantia/atlantic/aq_ring.h
drivers/net/ethernet/aquantia/atlantic/aq_vec.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
drivers/net/ethernet/broadcom/cnic.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/marvell/mvpp2.c
drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h
drivers/net/ethernet/mellanox/mlx5/core/en_fs.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_stats.h
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
drivers/net/ethernet/mellanox/mlx5/core/fpga/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/fpga/cmd.h
drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
drivers/net/ethernet/mellanox/mlx5/core/sriov.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/qualcomm/emac/emac-mac.c
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
drivers/net/ethernet/rocker/rocker_tlv.h
drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ppp/ppp_generic.c
drivers/net/tun.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/r8152.c
drivers/net/usb/rndis_host.c
drivers/net/wireless/ath/ath10k/pci.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.c
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
drivers/net/wireless/intel/iwlwifi/mvm/scan.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.h
drivers/net/wireless/intel/iwlwifi/mvm/tt.c
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
drivers/net/wireless/quantenna/qtnfmac/cfg80211.h
drivers/net/wireless/quantenna/qtnfmac/event.c
drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c
drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h
drivers/nvme/host/core.c
drivers/nvme/host/pci.c
drivers/nvmem/core.c
drivers/rapidio/devices/tsi721.c
drivers/rapidio/rio-access.c
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/reset-hsdk.c [moved from drivers/reset/reset-hsdk-v1.c with 72% similarity]
drivers/staging/iio/adc/ad7192.c
drivers/staging/mt29f_spinand/mt29f_spinand.c
drivers/staging/pi433/rf69.c
drivers/staging/rtl8723bs/core/rtw_mlme.c
drivers/staging/rtl8723bs/os_dep/rtw_proc.c
drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx.c
drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.c
drivers/staging/speakup/main.c
drivers/staging/unisys/visorbus/visorchipset.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c
drivers/tty/mxser.c
drivers/tty/serial/bcm63xx_uart.c
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/sccnxp.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/config.c
drivers/usb/core/devio.c
drivers/usb/core/hub.c
drivers/usb/core/message.c
drivers/usb/dwc3/dwc3-of-simple.c
drivers/usb/dwc3/ep0.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_mass_storage.c
drivers/usb/gadget/function/f_mass_storage.h
drivers/usb/gadget/function/f_printer.c
drivers/usb/gadget/function/u_fs.h
drivers/usb/gadget/legacy/inode.c
drivers/usb/gadget/legacy/mass_storage.c
drivers/usb/gadget/udc/Kconfig
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/gadget/udc/core.c
drivers/usb/gadget/udc/dummy_hcd.c
drivers/usb/gadget/udc/renesas_usb3.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/storage/transport.c
drivers/usb/storage/uas-detect.h
drivers/usb/storage/uas.c
drivers/usb/storage/unusual_devs.h
drivers/uwb/hwa-rc.c
drivers/uwb/uwbd.c
fs/binfmt_misc.c
fs/binfmt_script.c
fs/btrfs/ctree.h
fs/btrfs/extent_io.c
fs/ceph/mds_client.c
fs/ceph/snap.c
fs/exec.c
fs/namespace.c
fs/overlayfs/copy_up.c
fs/overlayfs/dir.c
fs/overlayfs/namei.c
fs/overlayfs/overlayfs.h
fs/overlayfs/ovl_entry.h
fs/overlayfs/readdir.c
fs/overlayfs/super.c
fs/overlayfs/util.c
fs/userfaultfd.c
fs/xattr.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_reflink.c
include/asm-generic/percpu.h
include/dt-bindings/reset/snps,hsdk-reset.h [new file with mode: 0644]
include/dt-bindings/reset/snps,hsdk-v1-reset.h [deleted file]
include/linux/binfmts.h
include/linux/bitfield.h
include/linux/device.h
include/linux/fs.h
include/linux/iio/adc/ad_sigma_delta.h
include/linux/mlx5/device.h
include/linux/mlx5/driver.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mm.h
include/linux/mmu_notifier.h
include/linux/mmzone.h
include/linux/nmi.h
include/linux/sched/mm.h
include/linux/smpboot.h
include/net/netlink.h
include/net/protocol.h
include/net/route.h
include/net/tcp.h
include/net/udp.h
include/sound/hda_verbs.h
include/uapi/linux/bpf.h
include/uapi/linux/dm-ioctl.h
include/uapi/linux/usb/ch9.h
kernel/bpf/core.c
kernel/cgroup/cgroup.c
kernel/cpu.c
kernel/fork.c
kernel/kcmp.c
kernel/memremap.c
kernel/params.c
kernel/power/suspend.c
kernel/rcu/tree.c
kernel/smpboot.c
kernel/sysctl.c
kernel/trace/ftrace.c
kernel/watchdog.c
kernel/watchdog_hld.c
lib/idr.c
lib/kobject_uevent.c
lib/lz4/lz4_decompress.c
lib/ratelimit.c
mm/compaction.c
mm/filemap.c
mm/ksm.c
mm/list_lru.c
mm/madvise.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/oom_kill.c
mm/page_alloc.c
mm/percpu-stats.c
mm/percpu.c
mm/rodata_test.c
mm/slab_common.c
mm/swap.c
mm/swap_state.c
mm/z3fold.c
net/8021q/vlan_core.c
net/core/filter.c
net/core/rtnetlink.c
net/core/sock.c
net/dsa/slave.c
net/ipv4/inetpeer.c
net/ipv4/ip_gre.c
net/ipv4/ip_input.c
net/ipv4/ip_vti.c
net/ipv4/route.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_eth.c
net/l2tp/l2tp_ppp.c
net/netlink/af_netlink.c
net/packet/af_packet.c
net/sctp/sctp_diag.c
net/tipc/msg.c
scripts/checkpatch.pl
scripts/spelling.txt
security/smack/smack_lsm.c
sound/core/compress_offload.c
sound/core/pcm_compat.c
sound/pci/asihpi/hpioctl.c
sound/pci/echoaudio/echoaudio.c
sound/pci/hda/patch_hdmi.c
sound/usb/card.c
sound/usb/quirks.c
sound/usb/usx2y/usb_stream.c

index 5273cfd..c7b10ca 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -68,6 +68,8 @@ Jacob Shin <Jacob.Shin@amd.com>
 James Bottomley <jejb@mulgrave.(none)>
 James Bottomley <jejb@titanic.il.steeleye.com>
 James E Wilson <wilson@specifix.com>
+James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
+James Hogan <jhogan@kernel.org> <james@albanarts.com>
 James Ketrenos <jketreno@io.(none)>
 Javi Merino <javi.merino@kernel.org> <javi.merino@arm.com>
 <javier@osg.samsung.com> <javier.martinez@collabora.co.uk>
index 713cab1..a1d1612 100644 (file)
@@ -127,7 +127,7 @@ Description:
 
 What;          /sys/power/pm_trace_dev_match
 Date:          October 2010
-Contact:       James Hogan <james@albanarts.com>
+Contact:       James Hogan <jhogan@kernel.org>
 Description:
                The /sys/power/pm_trace_dev_match file contains the name of the
                device associated with the last PM event point saved in the RTC
index 3943b5b..00a5ba5 100644 (file)
@@ -39,8 +39,8 @@ up.
 Although MT wq wasted a lot of resource, the level of concurrency
 provided was unsatisfactory.  The limitation was common to both ST and
 MT wq albeit less severe on MT.  Each wq maintained its own separate
-worker pool.  A MT wq could provide only one execution context per CPU
-while a ST wq one for the whole system.  Work items had to compete for
+worker pool.  An MT wq could provide only one execution context per CPU
+while an ST wq one for the whole system.  Work items had to compete for
 those very limited execution contexts leading to various problems
 including proneness to deadlocks around the single execution context.
 
@@ -151,7 +151,7 @@ Application Programming Interface (API)
 
 ``alloc_workqueue()`` allocates a wq.  The original
 ``create_*workqueue()`` functions are deprecated and scheduled for
-removal.  ``alloc_workqueue()`` takes three arguments - @``name``,
+removal.  ``alloc_workqueue()`` takes three arguments - ``@name``,
 ``@flags`` and ``@max_active``.  ``@name`` is the name of the wq and
 also used as the name of the rescuer thread if there is one.
 
@@ -197,7 +197,7 @@ resources, scheduled and executed.
   served by worker threads with elevated nice level.
 
   Note that normal and highpri worker-pools don't interact with
-  each other.  Each maintain its separate pool of workers and
+  each other.  Each maintains its separate pool of workers and
   implements concurrency management among its workers.
 
 ``WQ_CPU_INTENSIVE``
@@ -249,8 +249,8 @@ unbound worker-pools and only one work item could be active at any given
 time thus achieving the same ordering property as ST wq.
 
 In the current implementation the above configuration only guarantees
-ST behavior within a given NUMA node. Instead alloc_ordered_queue should
-be used to achieve system wide ST behavior.
+ST behavior within a given NUMA node. Instead ``alloc_ordered_queue()`` should
+be used to achieve system-wide ST behavior.
 
 
 Example Execution Scenarios
index 4a0a746..32df07e 100644 (file)
@@ -344,3 +344,4 @@ Version History
        (wrong raid10_copies/raid10_format sequence)
 1.11.1  Add raid4/5/6 journal write-back support via journal_mode option
 1.12.1  fix for MD deadlock between mddev_suspend() and md_write_start() available
+1.13.0  Fix dev_health status at end of "recover" (was 'a', now 'A')
index 7e2dad0..1814fa1 100644 (file)
@@ -21,8 +21,9 @@ Required properties:
        - main controller clock (for both armada-375-pp2 and armada-7k-pp2)
        - GOP clock (for both armada-375-pp2 and armada-7k-pp2)
        - MG clock (only for armada-7k-pp2)
-- clock-names: names of used clocks, must be "pp_clk", "gop_clk" and
-  "mg_clk" (the latter only for armada-7k-pp2).
+       - AXI clock (only for armada-7k-pp2)
+- clock-names: names of used clocks, must be "pp_clk", "gop_clk", "mg_clk"
+  and "axi_clk" (the 2 latter only for armada-7k-pp2).
 
 The ethernet ports are represented by subnodes. At least one port is
 required.
@@ -78,8 +79,9 @@ Example for marvell,armada-7k-pp2:
 cpm_ethernet: ethernet@0 {
        compatible = "marvell,armada-7k-pp22";
        reg = <0x0 0x100000>, <0x129000 0xb000>;
-       clocks = <&cpm_syscon0 1 3>, <&cpm_syscon0 1 9>, <&cpm_syscon0 1 5>;
-       clock-names = "pp_clk", "gop_clk", "gp_clk";
+       clocks = <&cpm_syscon0 1 3>, <&cpm_syscon0 1 9>,
+                <&cpm_syscon0 1 5>, <&cpm_syscon0 1 18>;
+       clock-names = "pp_clk", "gop_clk", "gp_clk", "axi_clk";
 
        eth0: eth0 {
                interrupts = <ICU_GRP_NSR 39 IRQ_TYPE_LEVEL_HIGH>,
index 6af8eed..9c16ee2 100644 (file)
@@ -4,6 +4,7 @@ The device node has following properties.
 
 Required properties:
  - compatible: should be "rockchip,<name>-gamc"
+   "rockchip,rk3128-gmac": found on RK312x SoCs
    "rockchip,rk3228-gmac": found on RK322x SoCs
    "rockchip,rk3288-gmac": found on RK3288 SoCs
    "rockchip,rk3328-gmac": found on RK3328 SoCs
diff --git a/Documentation/devicetree/bindings/reset/snps,hsdk-reset.txt b/Documentation/devicetree/bindings/reset/snps,hsdk-reset.txt
new file mode 100644 (file)
index 0000000..830069b
--- /dev/null
@@ -0,0 +1,28 @@
+Binding for the Synopsys HSDK reset controller
+
+This binding uses the common reset binding[1].
+
+[1] Documentation/devicetree/bindings/reset/reset.txt
+
+Required properties:
+- compatible: should be "snps,hsdk-reset".
+- reg: should always contain 2 pairs address - length: first for reset
+  configuration register and second for corresponding SW reset and status bits
+  register.
+- #reset-cells: from common reset binding; Should always be set to 1.
+
+Example:
+       reset: reset@880 {
+               compatible = "snps,hsdk-reset";
+               #reset-cells = <1>;
+               reg = <0x8A0 0x4>, <0xFF0 0x4>;
+       };
+
+Specifying reset lines connected to IP modules:
+       ethernet@.... {
+               ....
+               resets = <&reset HSDK_V1_ETH_RESET>;
+               ....
+       };
+
+The index could be found in <dt-bindings/reset/snps,hsdk-reset.h>
index 4fc9694..cf504d0 100644 (file)
@@ -41,6 +41,8 @@ Required properties:
     - "renesas,hscif-r8a7795" for R8A7795 (R-Car H3) HSCIF compatible UART.
     - "renesas,scif-r8a7796" for R8A7796 (R-Car M3-W) SCIF compatible UART.
     - "renesas,hscif-r8a7796" for R8A7796 (R-Car M3-W) HSCIF compatible UART.
+    - "renesas,scif-r8a77970" for R8A77970 (R-Car V3M) SCIF compatible UART.
+    - "renesas,hscif-r8a77970" for R8A77970 (R-Car V3M) HSCIF compatible UART.
     - "renesas,scif-r8a77995" for R8A77995 (R-Car D3) SCIF compatible UART.
     - "renesas,hscif-r8a77995" for R8A77995 (R-Car D3) HSCIF compatible UART.
     - "renesas,scifa-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFA compatible UART.
index 4421135..d661e6f 100644 (file)
@@ -196,12 +196,13 @@ struct driver_attribute {
 };
 
 Device drivers can export attributes via their sysfs directories. 
-Drivers can declare attributes using a DRIVER_ATTR macro that works
-identically to the DEVICE_ATTR macro. 
+Drivers can declare attributes using a DRIVER_ATTR_RW and DRIVER_ATTR_RO
+macro that works identically to the DEVICE_ATTR_RW and DEVICE_ATTR_RO
+macros.
 
 Example:
 
-DRIVER_ATTR(debug,0644,show_debug,store_debug);
+DRIVER_ATTR_RW(debug);
 
 This is equivalent to declaring:
 
index 36f528a..8caa607 100644 (file)
@@ -210,8 +210,11 @@ path as another overlay mount and it may use a lower layer path that is
 beneath or above the path of another overlay lower layer path.
 
 Using an upper layer path and/or a workdir path that are already used by
-another overlay mount is not allowed and will fail with EBUSY.  Using
+another overlay mount is not allowed and may fail with EBUSY.  Using
 partially overlapping paths is not allowed but will not fail with EBUSY.
+If files are accessed from two overlayfs mounts which share or overlap the
+upper layer and/or workdir path the behavior of the overlay is undefined,
+though it will not result in a crash or deadlock.
 
 Mounting an overlay using an upper layer path, where the upper layer path
 was previously used by another mounted overlay in combination with a
index 24da7b3..9a3658c 100644 (file)
@@ -366,7 +366,8 @@ struct driver_attribute {
 
 Declaring:
 
-DRIVER_ATTR(_name, _mode, _show, _store)
+DRIVER_ATTR_RO(_name)
+DRIVER_ATTR_RW(_name)
 
 Creation/Removal:
 
index 65b0c88..2d3d750 100644 (file)
@@ -5259,7 +5259,8 @@ S:        Maintained
 F:     drivers/iommu/exynos-iommu.c
 
 EZchip NPS platform support
-M:     Noam Camus <noamc@ezchip.com>
+M:     Elad Kanfi <eladkan@mellanox.com>
+M:     Vineet Gupta <vgupta@synopsys.com>
 S:     Supported
 F:     arch/arc/plat-eznps
 F:     arch/arc/boot/dts/eznps.dts
@@ -6738,7 +6739,7 @@ F:        Documentation/devicetree/bindings/auxdisplay/img-ascii-lcd.txt
 F:     drivers/auxdisplay/img-ascii-lcd.c
 
 IMGTEC IR DECODER DRIVER
-M:     James Hogan <james.hogan@imgtec.com>
+M:     James Hogan <jhogan@kernel.org>
 S:     Maintained
 F:     drivers/media/rc/img-ir/
 
@@ -7562,7 +7563,7 @@ F:        arch/arm64/include/asm/kvm*
 F:     arch/arm64/kvm/
 
 KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
-M:     James Hogan <james.hogan@imgtec.com>
+M:     James Hogan <jhogan@kernel.org>
 L:     linux-mips@linux-mips.org
 S:     Supported
 F:     arch/mips/include/uapi/asm/kvm*
@@ -8264,6 +8265,12 @@ L:       libertas-dev@lists.infradead.org
 S:     Orphan
 F:     drivers/net/wireless/marvell/libertas/
 
+MARVELL MACCHIATOBIN SUPPORT
+M:     Russell King <rmk@armlinux.org.uk>
+L:     linux-arm-kernel@lists.infradead.org
+S:     Maintained
+F:     arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts
+
 MARVELL MV643XX ETHERNET DRIVER
 M:     Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 L:     netdev@vger.kernel.org
@@ -8885,7 +8892,7 @@ F:        Documentation/devicetree/bindings/media/meson-ao-cec.txt
 T:     git git://linuxtv.org/media_tree.git
 
 METAG ARCHITECTURE
-M:     James Hogan <james.hogan@imgtec.com>
+M:     James Hogan <jhogan@kernel.org>
 L:     linux-metag@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jhogan/metag.git
 S:     Odd Fixes
@@ -9354,7 +9361,7 @@ NETWORK BLOCK DEVICE (NBD)
 M:     Josef Bacik <jbacik@fb.com>
 S:     Maintained
 L:     linux-block@vger.kernel.org
-L:     nbd-general@lists.sourceforge.net
+L:     nbd@other.debian.org
 F:     Documentation/blockdev/nbd.txt
 F:     drivers/block/nbd.c
 F:     include/uapi/linux/nbd.h
@@ -12931,9 +12938,9 @@ F:      drivers/mmc/host/dw_mmc*
 SYNOPSYS HSDK RESET CONTROLLER DRIVER
 M:     Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
 S:     Supported
-F:     drivers/reset/reset-hsdk-v1.c
-F:     include/dt-bindings/reset/snps,hsdk-v1-reset.h
-F:     Documentation/devicetree/bindings/reset/snps,hsdk-v1-reset.txt
+F:     drivers/reset/reset-hsdk.c
+F:     include/dt-bindings/reset/snps,hsdk-reset.h
+F:     Documentation/devicetree/bindings/reset/snps,hsdk-reset.txt
 
 SYSTEM CONFIGURATION (SYSCON)
 M:     Lee Jones <lee.jones@linaro.org>
index 384bd47..45c020a 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/mm_types.h>
+#include <linux/sched.h>
 
 #include <asm/machvec.h>
 #include <asm/compiler.h>
index a598641..c84e67f 100644 (file)
@@ -24,7 +24,7 @@ config ARC
        select GENERIC_SMP_IDLE_THREAD
        select HAVE_ARCH_KGDB
        select HAVE_ARCH_TRACEHOOK
-       select HAVE_FUTEX_CMPXCHG
+       select HAVE_FUTEX_CMPXCHG if FUTEX
        select HAVE_IOREMAP_PROT
        select HAVE_KPROBES
        select HAVE_KRETPROBES
index 3a4b52b..d37f49d 100644 (file)
@@ -6,8 +6,6 @@
 # published by the Free Software Foundation.
 #
 
-UTS_MACHINE := arc
-
 ifeq ($(CROSS_COMPILE),)
 ifndef CONFIG_CPU_BIG_ENDIAN
 CROSS_COMPILE := arc-linux-
index 2367a67..e114000 100644 (file)
 
                        mmcclk: mmcclk {
                                compatible = "fixed-clock";
-                               clock-frequency = <50000000>;
+                               /*
+                                * DW sdio controller has external ciu clock divider
+                                * controlled via register in SDIO IP. It divides
+                                * sdio_ref_clk (which comes from CGU) by 16 for
+                                * default. So default mmcclk clock (which comes
+                                * to sdk_in) is 25000000 Hz.
+                                */
+                               clock-frequency = <25000000>;
                                #clock-cells = <0>;
                        };
 
index 229d13a..8adde1b 100644 (file)
@@ -12,6 +12,7 @@
 /dts-v1/;
 
 #include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/reset/snps,hsdk-reset.h>
 
 / {
        model = "snps,hsdk";
                };
        };
 
-       core_clk: core-clk {
+       input_clk: input-clk {
                #clock-cells = <0>;
                compatible = "fixed-clock";
-               clock-frequency = <500000000>;
+               clock-frequency = <33333333>;
        };
 
        cpu_intc: cpu-interrupt-controller {
 
                ranges = <0x00000000 0xf0000000 0x10000000>;
 
+               cgu_rst: reset-controller@8a0 {
+                       compatible = "snps,hsdk-reset";
+                       #reset-cells = <1>;
+                       reg = <0x8A0 0x4>, <0xFF0 0x4>;
+               };
+
+               core_clk: core-clk@0 {
+                       compatible = "snps,hsdk-core-pll-clock";
+                       reg = <0x00 0x10>, <0x14B8 0x4>;
+                       #clock-cells = <0>;
+                       clocks = <&input_clk>;
+               };
+
                serial: serial@5000 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x5000 0x100>;
 
                mmcclk_ciu: mmcclk-ciu {
                        compatible = "fixed-clock";
-                       clock-frequency = <100000000>;
+                       /*
+                        * DW sdio controller has external ciu clock divider
+                        * controlled via register in SDIO IP. Due to its
+                        * unexpected default value (it should devide by 1
+                        * but it devides by 8) SDIO IP uses wrong clock and
+                        * works unstable (see STAR 9001204800)
+                        * So add temporary fix and change clock frequency
+                        * from 100000000 to 12500000 Hz until we fix dw sdio
+                        * driver itself.
+                        */
+                       clock-frequency = <12500000>;
                        #clock-cells = <0>;
                };
 
                        clocks = <&gmacclk>;
                        clock-names = "stmmaceth";
                        phy-handle = <&phy0>;
+                       resets = <&cgu_rst HSDK_ETH_RESET>;
+                       reset-names = "stmmaceth";
 
                        mdio {
                                #address-cells = <1>;
index 6980b96..ec7c849 100644 (file)
@@ -105,7 +105,7 @@ CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_STRIP_ASM_SYMS=y
-CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
 CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=10
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
index 2233f57..63d3cf6 100644 (file)
@@ -104,7 +104,7 @@ CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_STRIP_ASM_SYMS=y
-CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
 CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=10
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
index 30a3d4c..f613eca 100644 (file)
@@ -107,7 +107,7 @@ CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_STRIP_ASM_SYMS=y
-CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
 CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=10
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
index 821a2e5..3507be2 100644 (file)
@@ -84,5 +84,5 @@ CONFIG_TMPFS=y
 CONFIG_NFS_FS=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
 # CONFIG_DEBUG_PREEMPT is not set
index 9a3fcf4..15f0f6b 100644 (file)
@@ -63,6 +63,7 @@ CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_DW=y
 # CONFIG_IOMMU_SUPPORT is not set
+CONFIG_RESET_HSDK=y
 CONFIG_EXT3_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
@@ -72,7 +73,7 @@ CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_STRIP_ASM_SYMS=y
-CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
 CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=10
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
index c0d6a01..4fcf4f2 100644 (file)
@@ -94,7 +94,7 @@ CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_STRIP_ASM_SYMS=y
 CONFIG_DEBUG_SHIRQ=y
-CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
 CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=10
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
index 5c09717..7b71464 100644 (file)
@@ -98,7 +98,7 @@ CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_STRIP_ASM_SYMS=y
 CONFIG_DEBUG_SHIRQ=y
-CONFIG_LOCKUP_DETECTOR=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
 CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=10
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
index ba8e802..b1c56d3 100644 (file)
@@ -98,6 +98,7 @@
 
 /* Auxiliary registers */
 #define AUX_IDENTITY           4
+#define AUX_EXEC_CTRL          8
 #define AUX_INTR_VEC_BASE      0x25
 #define AUX_VOL                        0x5e
 
@@ -135,12 +136,12 @@ struct bcr_identity {
 #endif
 };
 
-struct bcr_isa {
+struct bcr_isa_arcv2 {
 #ifdef CONFIG_CPU_BIG_ENDIAN
        unsigned int div_rem:4, pad2:4, ldd:1, unalign:1, atomic:1, be:1,
-                    pad1:11, atomic1:1, ver:8;
+                    pad1:12, ver:8;
 #else
-       unsigned int ver:8, atomic1:1, pad1:11, be:1, atomic:1, unalign:1,
+       unsigned int ver:8, pad1:12, be:1, atomic:1, unalign:1,
                     ldd:1, pad2:4, div_rem:4;
 #endif
 };
@@ -263,13 +264,13 @@ struct cpuinfo_arc {
        struct cpuinfo_arc_mmu mmu;
        struct cpuinfo_arc_bpu bpu;
        struct bcr_identity core;
-       struct bcr_isa isa;
+       struct bcr_isa_arcv2 isa;
        const char *details, *name;
        unsigned int vec_base;
        struct cpuinfo_arc_ccm iccm, dccm;
        struct {
                unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, swape:1, pad1:2,
-                            fpu_sp:1, fpu_dp:1, pad2:6,
+                            fpu_sp:1, fpu_dp:1, dual_iss_enb:1, dual_iss_exist:1, pad2:4,
                             debug:1, ap:1, smart:1, rtt:1, pad3:4,
                             timer0:1, timer1:1, rtc:1, gfrc:1, pad4:4;
        } extn;
index 877cec8..fb83844 100644 (file)
@@ -51,6 +51,7 @@ static const struct id_to_str arc_cpu_rel[] = {
        { 0x51, "R2.0" },
        { 0x52, "R2.1" },
        { 0x53, "R3.0" },
+       { 0x54, "R4.0" },
 #endif
        { 0x00, NULL   }
 };
@@ -62,6 +63,7 @@ static const struct id_to_str arc_cpu_nm[] = {
 #else
        { 0x40, "ARC EM"  },
        { 0x50, "ARC HS38"  },
+       { 0x54, "ARC HS48"  },
 #endif
        { 0x00, "Unknown"   }
 };
@@ -119,11 +121,11 @@ static void read_arc_build_cfg_regs(void)
        struct bcr_generic bcr;
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
        const struct id_to_str *tbl;
+       struct bcr_isa_arcv2 isa;
 
        FIX_PTR(cpu);
 
        READ_BCR(AUX_IDENTITY, cpu->core);
-       READ_BCR(ARC_REG_ISA_CFG_BCR, cpu->isa);
 
        for (tbl = &arc_cpu_rel[0]; tbl->id != 0; tbl++) {
                if (cpu->core.family == tbl->id) {
@@ -133,7 +135,7 @@ static void read_arc_build_cfg_regs(void)
        }
 
        for (tbl = &arc_cpu_nm[0]; tbl->id != 0; tbl++) {
-               if ((cpu->core.family & 0xF0) == tbl->id)
+               if ((cpu->core.family & 0xF4) == tbl->id)
                        break;
        }
        cpu->name = tbl->str;
@@ -192,6 +194,14 @@ static void read_arc_build_cfg_regs(void)
                cpu->bpu.full = bpu.ft;
                cpu->bpu.num_cache = 256 << bpu.bce;
                cpu->bpu.num_pred = 2048 << bpu.pte;
+
+               if (cpu->core.family >= 0x54) {
+                       unsigned int exec_ctrl;
+
+                       READ_BCR(AUX_EXEC_CTRL, exec_ctrl);
+                       cpu->extn.dual_iss_exist = 1;
+                       cpu->extn.dual_iss_enb = exec_ctrl & 1;
+               }
        }
 
        READ_BCR(ARC_REG_AP_BCR, bcr);
@@ -205,18 +215,25 @@ static void read_arc_build_cfg_regs(void)
 
        cpu->extn.debug = cpu->extn.ap | cpu->extn.smart | cpu->extn.rtt;
 
+       READ_BCR(ARC_REG_ISA_CFG_BCR, isa);
+
        /* some hacks for lack of feature BCR info in old ARC700 cores */
        if (is_isa_arcompact()) {
-               if (!cpu->isa.ver)      /* ISA BCR absent, use Kconfig info */
+               if (!isa.ver)   /* ISA BCR absent, use Kconfig info */
                        cpu->isa.atomic = IS_ENABLED(CONFIG_ARC_HAS_LLSC);
-               else
-                       cpu->isa.atomic = cpu->isa.atomic1;
+               else {
+                       /* ARC700_BUILD only has 2 bits of isa info */
+                       struct bcr_generic bcr = *(struct bcr_generic *)&isa;
+                       cpu->isa.atomic = bcr.info & 1;
+               }
 
                cpu->isa.be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN);
 
                 /* there's no direct way to distinguish 750 vs. 770 */
                if (unlikely(cpu->core.family < 0x34 || cpu->mmu.ver < 3))
                        cpu->name = "ARC750";
+       } else {
+               cpu->isa = isa;
        }
 }
 
@@ -232,10 +249,11 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
                       "\nIDENTITY\t: ARCVER [%#02x] ARCNUM [%#02x] CHIPID [%#4x]\n",
                       core->family, core->cpu_id, core->chip_id);
 
-       n += scnprintf(buf + n, len - n, "processor [%d]\t: %s %s (%s ISA) %s\n",
+       n += scnprintf(buf + n, len - n, "processor [%d]\t: %s %s (%s ISA) %s%s%s\n",
                       cpu_id, cpu->name, cpu->details,
                       is_isa_arcompact() ? "ARCompact" : "ARCv2",
-                      IS_AVAIL1(cpu->isa.be, "[Big-Endian]"));
+                      IS_AVAIL1(cpu->isa.be, "[Big-Endian]"),
+                      IS_AVAIL3(cpu->extn.dual_iss_exist, cpu->extn.dual_iss_enb, " Dual-Issue"));
 
        n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s%s%s\nISA Extn\t: ",
                       IS_AVAIL1(cpu->extn.timer0, "Timer0 "),
index f1ac679..cf14ebc 100644 (file)
@@ -111,6 +111,13 @@ static void __init axs10x_early_init(void)
 
        axs10x_enable_gpio_intc_wire();
 
+       /*
+        * Reset ethernet IP core.
+        * TODO: get rid of this quirk after axs10x reset driver (or simple
+        * reset driver) will be available in upstream.
+        */
+       iowrite32((1 << 5), (void __iomem *) CREG_MB_SW_RESET);
+
        scnprintf(mb, 32, "MainBoard v%d", mb_rev);
        axs10x_print_board_ver(CREG_MB_VER, mb);
 }
index 5a6ed5a..bd08de4 100644 (file)
@@ -6,4 +6,5 @@
 #
 
 menuconfig ARC_SOC_HSDK
-       bool "ARC HS Development Kit SOC"
+       bool "ARC HS Development Kit SOC"
+       select CLK_HSDK
index a2e7fd1..744e62e 100644 (file)
@@ -38,6 +38,42 @@ static void __init hsdk_init_per_cpu(unsigned int cpu)
 #define CREG_PAE               (CREG_BASE + 0x180)
 #define CREG_PAE_UPDATE                (CREG_BASE + 0x194)
 
+#define CREG_CORE_IF_CLK_DIV   (CREG_BASE + 0x4B8)
+#define CREG_CORE_IF_CLK_DIV_2 0x1
+#define CGU_BASE               ARC_PERIPHERAL_BASE
+#define CGU_PLL_STATUS         (ARC_PERIPHERAL_BASE + 0x4)
+#define CGU_PLL_CTRL           (ARC_PERIPHERAL_BASE + 0x0)
+#define CGU_PLL_STATUS_LOCK    BIT(0)
+#define CGU_PLL_STATUS_ERR     BIT(1)
+#define CGU_PLL_CTRL_1GHZ      0x3A10
+#define HSDK_PLL_LOCK_TIMEOUT  500
+
+#define HSDK_PLL_LOCKED() \
+       !!(ioread32((void __iomem *) CGU_PLL_STATUS) & CGU_PLL_STATUS_LOCK)
+
+#define HSDK_PLL_ERR() \
+       !!(ioread32((void __iomem *) CGU_PLL_STATUS) & CGU_PLL_STATUS_ERR)
+
+static void __init hsdk_set_cpu_freq_1ghz(void)
+{
+       u32 timeout = HSDK_PLL_LOCK_TIMEOUT;
+
+       /*
+        * As we set cpu clock which exceeds 500MHz, the divider for the interface
+        * clock must be programmed to div-by-2.
+        */
+       iowrite32(CREG_CORE_IF_CLK_DIV_2, (void __iomem *) CREG_CORE_IF_CLK_DIV);
+
+       /* Set cpu clock to 1GHz */
+       iowrite32(CGU_PLL_CTRL_1GHZ, (void __iomem *) CGU_PLL_CTRL);
+
+       while (!HSDK_PLL_LOCKED() && timeout--)
+               cpu_relax();
+
+       if (!HSDK_PLL_LOCKED() || HSDK_PLL_ERR())
+               pr_err("Failed to setup CPU frequency to 1GHz!");
+}
+
 static void __init hsdk_init_early(void)
 {
        /*
@@ -52,6 +88,12 @@ static void __init hsdk_init_early(void)
 
        /* Really apply settings made above */
        writel(1, (void __iomem *) CREG_PAE_UPDATE);
+
+       /*
+        * Setup CPU frequency to 1GHz.
+        * TODO: remove it after smart hsdk pll driver will be introduced.
+        */
+       hsdk_set_cpu_freq_1ghz();
 }
 
 static const char *hsdk_compat[] __initconst = {
index 7d7ca05..e58fab8 100644 (file)
@@ -36,6 +36,8 @@
                phy1 = &usb1_phy;
                ethernet0 = &cpsw_emac0;
                ethernet1 = &cpsw_emac1;
+               spi0 = &spi0;
+               spi1 = &spi1;
        };
 
        cpus {
index 9d276af..081fa68 100644 (file)
        pinctrl-0 = <&cpsw_default>;
        pinctrl-1 = <&cpsw_sleep>;
        status = "okay";
+       slaves = <1>;
 };
 
 &davinci_mdio {
        phy-mode = "rmii";
 };
 
-&cpsw_emac1 {
-       phy_id = <&davinci_mdio>, <1>;
-       phy-mode = "rmii";
-};
-
 &phy_sel {
        rmii-clock-ext;
 };
index 9c9088c..60cb084 100644 (file)
 
                usb1: ohci@00400000 {
                        num-ports = <3>;
-                       atmel,vbus-gpio = <&pioA PIN_PA10 GPIO_ACTIVE_HIGH>;
+                       atmel,vbus-gpio = <0 /* &pioA PIN_PD20 GPIO_ACTIVE_HIGH */
+                                          &pioA PIN_PA27 GPIO_ACTIVE_HIGH
+                                          0
+                                         >;
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_usb_default>;
                        status = "okay";
                                pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_mikrobus2_uart>;
                                atmel,use-dma-rx;
-                               atmel-use-dma-tx;
+                               atmel,use-dma-tx;
                                status = "okay";
                        };
 
                        uart4: serial@fc00c000 {
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
-                               pinctrl-name = "default";
+                               pinctrl-names = "default";
                                pinctrl-0 = <&pinctrl_mikrobus1_uart>;
                                status = "okay";
                        };
                                };
 
                                pinctrl_led_gpio_default: led_gpio_default {
-                                       pinmux = <PIN_PA27__GPIO>,
+                                       pinmux = <PIN_PA10__GPIO>,
                                                 <PIN_PB1__GPIO>,
                                                 <PIN_PA31__GPIO>;
                                        bias-pull-up;
                                };
 
                                pinctrl_usb_default: usb_default {
-                                       pinmux = <PIN_PA10__GPIO>,
+                                       pinmux = <PIN_PA27__GPIO>,
                                                 <PIN_PD19__GPIO>;
                                        bias-disable;
                                };
 
                red {
                        label = "red";
-                       gpios = <&pioA PIN_PA27 GPIO_ACTIVE_LOW>;
+                       gpios = <&pioA PIN_PA10 GPIO_ACTIVE_HIGH>;
                };
 
                green {
                        label = "green";
-                       gpios = <&pioA PIN_PB1 GPIO_ACTIVE_LOW>;
+                       gpios = <&pioA PIN_PB1 GPIO_ACTIVE_HIGH>;
                };
 
                blue {
                        label = "blue";
-                       gpios = <&pioA PIN_PA31 GPIO_ACTIVE_LOW>;
+                       gpios = <&pioA PIN_PA31 GPIO_ACTIVE_HIGH>;
                        linux,default-trigger = "heartbeat";
                };
        };
index 67e72bc..c755079 100644 (file)
        compatible = "ti,da850-evm", "ti,da850";
        model = "DA850/AM1808/OMAP-L138 EVM";
 
+       aliases {
+               serial0 = &serial0;
+               serial1 = &serial1;
+               serial2 = &serial2;
+               ethernet0 = &eth0;
+       };
+
        soc@1c00000 {
                pmx_core: pinmux@14120 {
                        status = "okay";
index cf229df..e62b628 100644 (file)
                clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
                ti,bit-shift = <24>;
                reg = <0x1868>;
+               assigned-clocks = <&mcasp3_ahclkx_mux>;
+               assigned-clock-parents = <&abe_24m_fclk>;
        };
 
        mcasp3_aux_gfclk_mux: mcasp3_aux_gfclk_mux@1868 {
index 26c20e1..4acd32a 100644 (file)
                io-channel-names = "temp", "bsi", "vbat";
        };
 
-       rear_camera: camera@0 {
-               compatible = "linux,camera";
-
-               module {
-                       model = "TCM8341MD";
-                       sensor = <&cam1>;
-               };
-       };
-
        pwm9: dmtimer-pwm {
                compatible = "ti,omap-dmtimer-pwm";
                #pwm-cells = <3>;
                                clock-lanes = <1>;
                                data-lanes = <0>;
                                lane-polarity = <0 0>;
-                               clock-inv = <0>;
                                /* Select strobe = <1> for back camera, <0> for front camera */
                                strobe = <1>;
-                               crc = <0>;
                        };
                };
        };
index 97b1c23..293ecb9 100644 (file)
@@ -47,6 +47,7 @@
 
 /dts-v1/;
 #include "stm32f429.dtsi"
+#include "stm32f429-pinctrl.dtsi"
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/gpio/gpio.h>
 
        stmpe1600: stmpe1600@42 {
                compatible = "st,stmpe1600";
                reg = <0x42>;
-               irq-gpio = <&gpioi 8 0>;
-               irq-trigger = <3>;
                interrupts = <8 3>;
-               interrupt-parent = <&exti>;
+               interrupt-parent = <&gpioi>;
                interrupt-controller;
                wakeup-source;
 
diff --git a/arch/arm/boot/dts/stm32f4-pinctrl.dtsi b/arch/arm/boot/dts/stm32f4-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..7f3560c
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2017 - Alexandre Torgue <alexandre.torgue@st.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
+#include <dt-bindings/mfd/stm32f4-rcc.h>
+
+/ {
+       soc {
+               pinctrl: pin-controller {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x40020000 0x3000>;
+                       interrupt-parent = <&exti>;
+                       st,syscfg = <&syscfg 0x8>;
+                       pins-are-numbered;
+
+                       gpioa: gpio@40020000 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               reg = <0x0 0x400>;
+                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOA)>;
+                               st,bank-name = "GPIOA";
+                       };
+
+                       gpiob: gpio@40020400 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               reg = <0x400 0x400>;
+                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOB)>;
+                               st,bank-name = "GPIOB";
+                       };
+
+                       gpioc: gpio@40020800 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               reg = <0x800 0x400>;
+                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOC)>;
+                               st,bank-name = "GPIOC";
+                       };
+
+                       gpiod: gpio@40020c00 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               reg = <0xc00 0x400>;
+                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOD)>;
+                               st,bank-name = "GPIOD";
+                       };
+
+                       gpioe: gpio@40021000 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               reg = <0x1000 0x400>;
+                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOE)>;
+                               st,bank-name = "GPIOE";
+                       };
+
+                       gpiof: gpio@40021400 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               reg = <0x1400 0x400>;
+                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOF)>;
+                               st,bank-name = "GPIOF";
+                       };
+
+                       gpiog: gpio@40021800 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               reg = <0x1800 0x400>;
+                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOG)>;
+                               st,bank-name = "GPIOG";
+                       };
+
+                       gpioh: gpio@40021c00 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               reg = <0x1c00 0x400>;
+                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOH)>;
+                               st,bank-name = "GPIOH";
+                       };
+
+                       gpioi: gpio@40022000 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               reg = <0x2000 0x400>;
+                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOI)>;
+                               st,bank-name = "GPIOI";
+                       };
+
+                       gpioj: gpio@40022400 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               reg = <0x2400 0x400>;
+                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOJ)>;
+                               st,bank-name = "GPIOJ";
+                       };
+
+                       gpiok: gpio@40022800 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               reg = <0x2800 0x400>;
+                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOK)>;
+                               st,bank-name = "GPIOK";
+                       };
+
+                       usart1_pins_a: usart1@0 {
+                               pins1 {
+                                       pinmux = <STM32F429_PA9_FUNC_USART1_TX>;
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <0>;
+                               };
+                               pins2 {
+                                       pinmux = <STM32F429_PA10_FUNC_USART1_RX>;
+                                       bias-disable;
+                               };
+                       };
+
+                       usart3_pins_a: usart3@0 {
+                               pins1 {
+                                       pinmux = <STM32F429_PB10_FUNC_USART3_TX>;
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <0>;
+                               };
+                               pins2 {
+                                       pinmux = <STM32F429_PB11_FUNC_USART3_RX>;
+                                       bias-disable;
+                               };
+                       };
+
+                       usbotg_fs_pins_a: usbotg_fs@0 {
+                               pins {
+                                       pinmux = <STM32F429_PA10_FUNC_OTG_FS_ID>,
+                                                <STM32F429_PA11_FUNC_OTG_FS_DM>,
+                                                <STM32F429_PA12_FUNC_OTG_FS_DP>;
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <2>;
+                               };
+                       };
+
+                       usbotg_fs_pins_b: usbotg_fs@1 {
+                               pins {
+                                       pinmux = <STM32F429_PB12_FUNC_OTG_HS_ID>,
+                                                <STM32F429_PB14_FUNC_OTG_HS_DM>,
+                                                <STM32F429_PB15_FUNC_OTG_HS_DP>;
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <2>;
+                               };
+                       };
+
+                       usbotg_hs_pins_a: usbotg_hs@0 {
+                               pins {
+                                       pinmux = <STM32F429_PH4_FUNC_OTG_HS_ULPI_NXT>,
+                                                <STM32F429_PI11_FUNC_OTG_HS_ULPI_DIR>,
+                                                <STM32F429_PC0_FUNC_OTG_HS_ULPI_STP>,
+                                                <STM32F429_PA5_FUNC_OTG_HS_ULPI_CK>,
+                                                <STM32F429_PA3_FUNC_OTG_HS_ULPI_D0>,
+                                                <STM32F429_PB0_FUNC_OTG_HS_ULPI_D1>,
+                                                <STM32F429_PB1_FUNC_OTG_HS_ULPI_D2>,
+                                                <STM32F429_PB10_FUNC_OTG_HS_ULPI_D3>,
+                                                <STM32F429_PB11_FUNC_OTG_HS_ULPI_D4>,
+                                                <STM32F429_PB12_FUNC_OTG_HS_ULPI_D5>,
+                                                <STM32F429_PB13_FUNC_OTG_HS_ULPI_D6>,
+                                                <STM32F429_PB5_FUNC_OTG_HS_ULPI_D7>;
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <2>;
+                               };
+                       };
+
+                       ethernet_mii: mii@0 {
+                               pins {
+                                       pinmux = <STM32F429_PG13_FUNC_ETH_MII_TXD0_ETH_RMII_TXD0>,
+                                                <STM32F429_PG14_FUNC_ETH_MII_TXD1_ETH_RMII_TXD1>,
+                                                <STM32F429_PC2_FUNC_ETH_MII_TXD2>,
+                                                <STM32F429_PB8_FUNC_ETH_MII_TXD3>,
+                                                <STM32F429_PC3_FUNC_ETH_MII_TX_CLK>,
+                                                <STM32F429_PG11_FUNC_ETH_MII_TX_EN_ETH_RMII_TX_EN>,
+                                                <STM32F429_PA2_FUNC_ETH_MDIO>,
+                                                <STM32F429_PC1_FUNC_ETH_MDC>,
+                                                <STM32F429_PA1_FUNC_ETH_MII_RX_CLK_ETH_RMII_REF_CLK>,
+                                                <STM32F429_PA7_FUNC_ETH_MII_RX_DV_ETH_RMII_CRS_DV>,
+                                                <STM32F429_PC4_FUNC_ETH_MII_RXD0_ETH_RMII_RXD0>,
+                                                <STM32F429_PC5_FUNC_ETH_MII_RXD1_ETH_RMII_RXD1>,
+                                                <STM32F429_PH6_FUNC_ETH_MII_RXD2>,
+                                                <STM32F429_PH7_FUNC_ETH_MII_RXD3>;
+                                       slew-rate = <2>;
+                               };
+                       };
+
+                       adc3_in8_pin: adc@200 {
+                               pins {
+                                       pinmux = <STM32F429_PF10_FUNC_ANALOG>;
+                               };
+                       };
+
+                       pwm1_pins: pwm@1 {
+                               pins {
+                                       pinmux = <STM32F429_PA8_FUNC_TIM1_CH1>,
+                                                <STM32F429_PB13_FUNC_TIM1_CH1N>,
+                                                <STM32F429_PB12_FUNC_TIM1_BKIN>;
+                               };
+                       };
+
+                       pwm3_pins: pwm@3 {
+                               pins {
+                                       pinmux = <STM32F429_PB4_FUNC_TIM3_CH1>,
+                                                <STM32F429_PB5_FUNC_TIM3_CH2>;
+                               };
+                       };
+
+                       i2c1_pins: i2c1@0 {
+                               pins {
+                                       pinmux = <STM32F429_PB9_FUNC_I2C1_SDA>,
+                                                <STM32F429_PB6_FUNC_I2C1_SCL>;
+                                       bias-disable;
+                                       drive-open-drain;
+                                       slew-rate = <3>;
+                               };
+                       };
+
+                       ltdc_pins: ltdc@0 {
+                               pins {
+                                       pinmux = <STM32F429_PI12_FUNC_LCD_HSYNC>,
+                                                <STM32F429_PI13_FUNC_LCD_VSYNC>,
+                                                <STM32F429_PI14_FUNC_LCD_CLK>,
+                                                <STM32F429_PI15_FUNC_LCD_R0>,
+                                                <STM32F429_PJ0_FUNC_LCD_R1>,
+                                                <STM32F429_PJ1_FUNC_LCD_R2>,
+                                                <STM32F429_PJ2_FUNC_LCD_R3>,
+                                                <STM32F429_PJ3_FUNC_LCD_R4>,
+                                                <STM32F429_PJ4_FUNC_LCD_R5>,
+                                                <STM32F429_PJ5_FUNC_LCD_R6>,
+                                                <STM32F429_PJ6_FUNC_LCD_R7>,
+                                                <STM32F429_PJ7_FUNC_LCD_G0>,
+                                                <STM32F429_PJ8_FUNC_LCD_G1>,
+                                                <STM32F429_PJ9_FUNC_LCD_G2>,
+                                                <STM32F429_PJ10_FUNC_LCD_G3>,
+                                                <STM32F429_PJ11_FUNC_LCD_G4>,
+                                                <STM32F429_PJ12_FUNC_LCD_B0>,
+                                                <STM32F429_PJ13_FUNC_LCD_B1>,
+                                                <STM32F429_PJ14_FUNC_LCD_B2>,
+                                                <STM32F429_PJ15_FUNC_LCD_B3>,
+                                                <STM32F429_PK0_FUNC_LCD_G5>,
+                                                <STM32F429_PK1_FUNC_LCD_G6>,
+                                                <STM32F429_PK2_FUNC_LCD_G7>,
+                                                <STM32F429_PK3_FUNC_LCD_B4>,
+                                                <STM32F429_PK4_FUNC_LCD_B5>,
+                                                <STM32F429_PK5_FUNC_LCD_B6>,
+                                                <STM32F429_PK6_FUNC_LCD_B7>,
+                                                <STM32F429_PK7_FUNC_LCD_DE>;
+                                       slew-rate = <2>;
+                               };
+                       };
+
+                       dcmi_pins: dcmi@0 {
+                               pins {
+                                       pinmux = <STM32F429_PA4_FUNC_DCMI_HSYNC>,
+                                                <STM32F429_PB7_FUNC_DCMI_VSYNC>,
+                                                <STM32F429_PA6_FUNC_DCMI_PIXCLK>,
+                                                <STM32F429_PC6_FUNC_DCMI_D0>,
+                                                <STM32F429_PC7_FUNC_DCMI_D1>,
+                                                <STM32F429_PC8_FUNC_DCMI_D2>,
+                                                <STM32F429_PC9_FUNC_DCMI_D3>,
+                                                <STM32F429_PC11_FUNC_DCMI_D4>,
+                                                <STM32F429_PD3_FUNC_DCMI_D5>,
+                                                <STM32F429_PB8_FUNC_DCMI_D6>,
+                                                <STM32F429_PE6_FUNC_DCMI_D7>,
+                                                <STM32F429_PC10_FUNC_DCMI_D8>,
+                                                <STM32F429_PC12_FUNC_DCMI_D9>,
+                                                <STM32F429_PD6_FUNC_DCMI_D10>,
+                                                <STM32F429_PD2_FUNC_DCMI_D11>;
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <3>;
+                               };
+                       };
+               };
+       };
+};
index c66d617..5ceb2cf 100644 (file)
@@ -47,6 +47,7 @@
 
 /dts-v1/;
 #include "stm32f429.dtsi"
+#include "stm32f429-pinctrl.dtsi"
 #include <dt-bindings/input/input.h>
 
 / {
diff --git a/arch/arm/boot/dts/stm32f429-pinctrl.dtsi b/arch/arm/boot/dts/stm32f429-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..3e7a17d
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2017 - Alexandre Torgue <alexandre.torgue@st.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "stm32f4-pinctrl.dtsi"
+
+/ {
+       soc {
+               pinctrl: pin-controller {
+                       compatible = "st,stm32f429-pinctrl";
+
+                       gpioa: gpio@40020000 {
+                               gpio-ranges = <&pinctrl 0 0 16>;
+                       };
+
+                       gpiob: gpio@40020400 {
+                               gpio-ranges = <&pinctrl 0 16 16>;
+                       };
+
+                       gpioc: gpio@40020800 {
+                               gpio-ranges = <&pinctrl 0 32 16>;
+                       };
+
+                       gpiod: gpio@40020c00 {
+                               gpio-ranges = <&pinctrl 0 48 16>;
+                       };
+
+                       gpioe: gpio@40021000 {
+                               gpio-ranges = <&pinctrl 0 64 16>;
+                       };
+
+                       gpiof: gpio@40021400 {
+                               gpio-ranges = <&pinctrl 0 80 16>;
+                       };
+
+                       gpiog: gpio@40021800 {
+                               gpio-ranges = <&pinctrl 0 96 16>;
+                       };
+
+                       gpioh: gpio@40021c00 {
+                               gpio-ranges = <&pinctrl 0 112 16>;
+                       };
+
+                       gpioi: gpio@40022000 {
+                               gpio-ranges = <&pinctrl 0 128 16>;
+                       };
+
+                       gpioj: gpio@40022400 {
+                               gpio-ranges = <&pinctrl 0 144 16>;
+                       };
+
+                       gpiok: gpio@40022800 {
+                               gpio-ranges = <&pinctrl 0 160 8>;
+                       };
+               };
+       };
+};
index dd7e99b..5b36eb1 100644 (file)
@@ -47,7 +47,6 @@
 
 #include "skeleton.dtsi"
 #include "armv7-m.dtsi"
-#include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
 #include <dt-bindings/clock/stm32fx-clock.h>
 #include <dt-bindings/mfd/stm32f4-rcc.h>
 
                        status = "disabled";
                };
 
-               pinctrl: pin-controller {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "st,stm32f429-pinctrl";
-                       ranges = <0 0x40020000 0x3000>;
-                       interrupt-parent = <&exti>;
-                       st,syscfg = <&syscfg 0x8>;
-                       pins-are-numbered;
-
-                       gpioa: gpio@40020000 {
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               reg = <0x0 0x400>;
-                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOA)>;
-                               st,bank-name = "GPIOA";
-                       };
-
-                       gpiob: gpio@40020400 {
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               reg = <0x400 0x400>;
-                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOB)>;
-                               st,bank-name = "GPIOB";
-                       };
-
-                       gpioc: gpio@40020800 {
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               reg = <0x800 0x400>;
-                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOC)>;
-                               st,bank-name = "GPIOC";
-                       };
-
-                       gpiod: gpio@40020c00 {
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               reg = <0xc00 0x400>;
-                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOD)>;
-                               st,bank-name = "GPIOD";
-                       };
-
-                       gpioe: gpio@40021000 {
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               reg = <0x1000 0x400>;
-                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOE)>;
-                               st,bank-name = "GPIOE";
-                       };
-
-                       gpiof: gpio@40021400 {
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               reg = <0x1400 0x400>;
-                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOF)>;
-                               st,bank-name = "GPIOF";
-                       };
-
-                       gpiog: gpio@40021800 {
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               reg = <0x1800 0x400>;
-                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOG)>;
-                               st,bank-name = "GPIOG";
-                       };
-
-                       gpioh: gpio@40021c00 {
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               reg = <0x1c00 0x400>;
-                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOH)>;
-                               st,bank-name = "GPIOH";
-                       };
-
-                       gpioi: gpio@40022000 {
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               reg = <0x2000 0x400>;
-                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOI)>;
-                               st,bank-name = "GPIOI";
-                       };
-
-                       gpioj: gpio@40022400 {
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               reg = <0x2400 0x400>;
-                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOJ)>;
-                               st,bank-name = "GPIOJ";
-                       };
-
-                       gpiok: gpio@40022800 {
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               reg = <0x2800 0x400>;
-                               clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOK)>;
-                               st,bank-name = "GPIOK";
-                       };
-
-                       usart1_pins_a: usart1@0 {
-                               pins1 {
-                                       pinmux = <STM32F429_PA9_FUNC_USART1_TX>;
-                                       bias-disable;
-                                       drive-push-pull;
-                                       slew-rate = <0>;
-                               };
-                               pins2 {
-                                       pinmux = <STM32F429_PA10_FUNC_USART1_RX>;
-                                       bias-disable;
-                               };
-                       };
-
-                       usart3_pins_a: usart3@0 {
-                               pins1 {
-                                       pinmux = <STM32F429_PB10_FUNC_USART3_TX>;
-                                       bias-disable;
-                                       drive-push-pull;
-                                       slew-rate = <0>;
-                               };
-                               pins2 {
-                                       pinmux = <STM32F429_PB11_FUNC_USART3_RX>;
-                                       bias-disable;
-                               };
-                       };
-
-                       usbotg_fs_pins_a: usbotg_fs@0 {
-                               pins {
-                                       pinmux = <STM32F429_PA10_FUNC_OTG_FS_ID>,
-                                                <STM32F429_PA11_FUNC_OTG_FS_DM>,
-                                                <STM32F429_PA12_FUNC_OTG_FS_DP>;
-                                       bias-disable;
-                                       drive-push-pull;
-                                       slew-rate = <2>;
-                               };
-                       };
-
-                       usbotg_fs_pins_b: usbotg_fs@1 {
-                               pins {
-                                       pinmux = <STM32F429_PB12_FUNC_OTG_HS_ID>,
-                                                <STM32F429_PB14_FUNC_OTG_HS_DM>,
-                                                <STM32F429_PB15_FUNC_OTG_HS_DP>;
-                                       bias-disable;
-                                       drive-push-pull;
-                                       slew-rate = <2>;
-                               };
-                       };
-
-                       usbotg_hs_pins_a: usbotg_hs@0 {
-                               pins {
-                                       pinmux = <STM32F429_PH4_FUNC_OTG_HS_ULPI_NXT>,
-                                                <STM32F429_PI11_FUNC_OTG_HS_ULPI_DIR>,
-                                                <STM32F429_PC0_FUNC_OTG_HS_ULPI_STP>,
-                                                <STM32F429_PA5_FUNC_OTG_HS_ULPI_CK>,
-                                                <STM32F429_PA3_FUNC_OTG_HS_ULPI_D0>,
-                                                <STM32F429_PB0_FUNC_OTG_HS_ULPI_D1>,
-                                                <STM32F429_PB1_FUNC_OTG_HS_ULPI_D2>,
-                                                <STM32F429_PB10_FUNC_OTG_HS_ULPI_D3>,
-                                                <STM32F429_PB11_FUNC_OTG_HS_ULPI_D4>,
-                                                <STM32F429_PB12_FUNC_OTG_HS_ULPI_D5>,
-                                                <STM32F429_PB13_FUNC_OTG_HS_ULPI_D6>,
-                                                <STM32F429_PB5_FUNC_OTG_HS_ULPI_D7>;
-                                       bias-disable;
-                                       drive-push-pull;
-                                       slew-rate = <2>;
-                               };
-                       };
-
-                       ethernet_mii: mii@0 {
-                               pins {
-                                       pinmux = <STM32F429_PG13_FUNC_ETH_MII_TXD0_ETH_RMII_TXD0>,
-                                                <STM32F429_PG14_FUNC_ETH_MII_TXD1_ETH_RMII_TXD1>,
-                                                <STM32F429_PC2_FUNC_ETH_MII_TXD2>,
-                                                <STM32F429_PB8_FUNC_ETH_MII_TXD3>,
-                                                <STM32F429_PC3_FUNC_ETH_MII_TX_CLK>,
-                                                <STM32F429_PG11_FUNC_ETH_MII_TX_EN_ETH_RMII_TX_EN>,
-                                                <STM32F429_PA2_FUNC_ETH_MDIO>,
-                                                <STM32F429_PC1_FUNC_ETH_MDC>,
-                                                <STM32F429_PA1_FUNC_ETH_MII_RX_CLK_ETH_RMII_REF_CLK>,
-                                                <STM32F429_PA7_FUNC_ETH_MII_RX_DV_ETH_RMII_CRS_DV>,
-                                                <STM32F429_PC4_FUNC_ETH_MII_RXD0_ETH_RMII_RXD0>,
-                                                <STM32F429_PC5_FUNC_ETH_MII_RXD1_ETH_RMII_RXD1>,
-                                                <STM32F429_PH6_FUNC_ETH_MII_RXD2>,
-                                                <STM32F429_PH7_FUNC_ETH_MII_RXD3>;
-                                       slew-rate = <2>;
-                               };
-                       };
-
-                       adc3_in8_pin: adc@200 {
-                               pins {
-                                       pinmux = <STM32F429_PF10_FUNC_ANALOG>;
-                               };
-                       };
-
-                       pwm1_pins: pwm@1 {
-                               pins {
-                                       pinmux = <STM32F429_PA8_FUNC_TIM1_CH1>,
-                                                <STM32F429_PB13_FUNC_TIM1_CH1N>,
-                                                <STM32F429_PB12_FUNC_TIM1_BKIN>;
-                               };
-                       };
-
-                       pwm3_pins: pwm@3 {
-                               pins {
-                                       pinmux = <STM32F429_PB4_FUNC_TIM3_CH1>,
-                                                <STM32F429_PB5_FUNC_TIM3_CH2>;
-                               };
-                       };
-
-                       i2c1_pins: i2c1@0 {
-                               pins {
-                                       pinmux = <STM32F429_PB9_FUNC_I2C1_SDA>,
-                                                <STM32F429_PB6_FUNC_I2C1_SCL>;
-                                       bias-disable;
-                                       drive-open-drain;
-                                       slew-rate = <3>;
-                               };
-                       };
-
-                       ltdc_pins: ltdc@0 {
-                               pins {
-                                       pinmux = <STM32F429_PI12_FUNC_LCD_HSYNC>,
-                                                <STM32F429_PI13_FUNC_LCD_VSYNC>,
-                                                <STM32F429_PI14_FUNC_LCD_CLK>,
-                                                <STM32F429_PI15_FUNC_LCD_R0>,
-                                                <STM32F429_PJ0_FUNC_LCD_R1>,
-                                                <STM32F429_PJ1_FUNC_LCD_R2>,
-                                                <STM32F429_PJ2_FUNC_LCD_R3>,
-                                                <STM32F429_PJ3_FUNC_LCD_R4>,
-                                                <STM32F429_PJ4_FUNC_LCD_R5>,
-                                                <STM32F429_PJ5_FUNC_LCD_R6>,
-                                                <STM32F429_PJ6_FUNC_LCD_R7>,
-                                                <STM32F429_PJ7_FUNC_LCD_G0>,
-                                                <STM32F429_PJ8_FUNC_LCD_G1>,
-                                                <STM32F429_PJ9_FUNC_LCD_G2>,
-                                                <STM32F429_PJ10_FUNC_LCD_G3>,
-                                                <STM32F429_PJ11_FUNC_LCD_G4>,
-                                                <STM32F429_PJ12_FUNC_LCD_B0>,
-                                                <STM32F429_PJ13_FUNC_LCD_B1>,
-                                                <STM32F429_PJ14_FUNC_LCD_B2>,
-                                                <STM32F429_PJ15_FUNC_LCD_B3>,
-                                                <STM32F429_PK0_FUNC_LCD_G5>,
-                                                <STM32F429_PK1_FUNC_LCD_G6>,
-                                                <STM32F429_PK2_FUNC_LCD_G7>,
-                                                <STM32F429_PK3_FUNC_LCD_B4>,
-                                                <STM32F429_PK4_FUNC_LCD_B5>,
-                                                <STM32F429_PK5_FUNC_LCD_B6>,
-                                                <STM32F429_PK6_FUNC_LCD_B7>,
-                                                <STM32F429_PK7_FUNC_LCD_DE>;
-                                       slew-rate = <2>;
-                               };
-                       };
-
-                       dcmi_pins: dcmi@0 {
-                               pins {
-                                       pinmux = <STM32F429_PA4_FUNC_DCMI_HSYNC>,
-                                                <STM32F429_PB7_FUNC_DCMI_VSYNC>,
-                                                <STM32F429_PA6_FUNC_DCMI_PIXCLK>,
-                                                <STM32F429_PC6_FUNC_DCMI_D0>,
-                                                <STM32F429_PC7_FUNC_DCMI_D1>,
-                                                <STM32F429_PC8_FUNC_DCMI_D2>,
-                                                <STM32F429_PC9_FUNC_DCMI_D3>,
-                                                <STM32F429_PC11_FUNC_DCMI_D4>,
-                                                <STM32F429_PD3_FUNC_DCMI_D5>,
-                                                <STM32F429_PB8_FUNC_DCMI_D6>,
-                                                <STM32F429_PE6_FUNC_DCMI_D7>,
-                                                <STM32F429_PC10_FUNC_DCMI_D8>,
-                                                <STM32F429_PC12_FUNC_DCMI_D9>,
-                                                <STM32F429_PD6_FUNC_DCMI_D10>,
-                                                <STM32F429_PD2_FUNC_DCMI_D11>;
-                                       bias-disable;
-                                       drive-push-pull;
-                                       slew-rate = <3>;
-                               };
-                       };
-               };
-
                crc: crc@40023000 {
                        compatible = "st,stm32f4-crc";
                        reg = <0x40023000 0x400>;
index 6ae1f03..c18acbe 100644 (file)
@@ -47,6 +47,7 @@
 
 /dts-v1/;
 #include "stm32f429.dtsi"
+#include "stm32f469-pinctrl.dtsi"
 
 / {
        model = "STMicroelectronics STM32F469i-DISCO board";
diff --git a/arch/arm/boot/dts/stm32f469-pinctrl.dtsi b/arch/arm/boot/dts/stm32f469-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..fff5426
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2017 - Alexandre Torgue <alexandre.torgue@st.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "stm32f4-pinctrl.dtsi"
+
+/ {
+       soc {
+               pinctrl: pin-controller {
+                       compatible = "st,stm32f469-pinctrl";
+
+                       gpioa: gpio@40020000 {
+                               gpio-ranges = <&pinctrl 0 0 16>;
+                       };
+
+                       gpiob: gpio@40020400 {
+                               gpio-ranges = <&pinctrl 0 16 16>;
+                       };
+
+                       gpioc: gpio@40020800 {
+                               gpio-ranges = <&pinctrl 0 32 16>;
+                       };
+
+                       gpiod: gpio@40020c00 {
+                               gpio-ranges = <&pinctrl 0 48 16>;
+                       };
+
+                       gpioe: gpio@40021000 {
+                               gpio-ranges = <&pinctrl 0 64 16>;
+                       };
+
+                       gpiof: gpio@40021400 {
+                               gpio-ranges = <&pinctrl 0 80 16>;
+                       };
+
+                       gpiog: gpio@40021800 {
+                               gpio-ranges = <&pinctrl 0 96 16>;
+                       };
+
+                       gpioh: gpio@40021c00 {
+                               gpio-ranges = <&pinctrl 0 112 16>;
+                       };
+
+                       gpioi: gpio@40022000 {
+                               gpio-ranges = <&pinctrl 0 128 16>;
+                       };
+
+                       gpioj: gpio@40022400 {
+                               gpio-ranges = <&pinctrl 0 144 6>,
+                                             <&pinctrl 12 156 4>;
+                       };
+
+                       gpiok: gpio@40022800 {
+                               gpio-ranges = <&pinctrl 3 163 5>;
+                       };
+               };
+       };
+};
index d2d75fa..2a63fa1 100644 (file)
@@ -32,6 +32,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384
 CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_ATA=y
+CONFIG_PATA_FTIDE010=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
@@ -55,8 +56,8 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_GEMINI=y
 CONFIG_DMADEVICES=y
+CONFIG_AMBA_PL08X=y
 # CONFIG_DNOTIFY is not set
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
index 64e3a2a..d5e1370 100644 (file)
@@ -471,7 +471,7 @@ CONFIG_LCD_PLATFORM=m
 CONFIG_LCD_TOSA=m
 CONFIG_BACKLIGHT_PWM=m
 CONFIG_BACKLIGHT_TOSA=m
-CONFIG_FRAMEBUFFER_CONSOLE=m
+CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
index 44d4fa5..070e507 100644 (file)
@@ -113,7 +113,7 @@ CONFIG_FB_PXA_PARAMETERS=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_BACKLIGHT_PWM=m
 # CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=m
+CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
 CONFIG_SND=m
index 8d4c0c9..09e7050 100644 (file)
@@ -112,7 +112,7 @@ CONFIG_FB_PXA=m
 CONFIG_FB_PXA_PARAMETERS=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=m
+CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
 CONFIG_SND=m
index 5036f99..849014c 100644 (file)
@@ -533,8 +533,8 @@ static void __init at91_pm_backup_init(void)
        }
 
        pm_bu->suspended = 0;
-       pm_bu->canary = virt_to_phys(&canary);
-       pm_bu->resume = virt_to_phys(cpu_resume);
+       pm_bu->canary = __pa_symbol(&canary);
+       pm_bu->resume = __pa_symbol(cpu_resume);
 
        return;
 
index 5b61438..6d28aa2 100644 (file)
@@ -58,10 +58,10 @@ void omap_hsmmc_late_init(struct omap2_hsmmc_info *c)
        struct platform_device *pdev;
        int res;
 
-       if (omap_hsmmc_done != 1)
+       if (omap_hsmmc_done)
                return;
 
-       omap_hsmmc_done++;
+       omap_hsmmc_done = 1;
 
        for (; c->mmc; c++) {
                pdev = c->pdev;
index f040244..2f4f700 100644 (file)
@@ -839,6 +839,7 @@ static struct omap_hwmod dra7xx_gpio1_hwmod = {
        .name           = "gpio1",
        .class          = &dra7xx_gpio_hwmod_class,
        .clkdm_name     = "wkupaon_clkdm",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .main_clk       = "wkupaon_iclk_mux",
        .prcm = {
                .omap4 = {
index c89010e..4157987 100644 (file)
 &sd_emmc_a {
        status = "okay";
        pinctrl-0 = <&sdio_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdio_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
        #address-cells = <1>;
        #size-cells = <0>;
 
 &sd_emmc_b {
        status = "okay";
        pinctrl-0 = <&sdcard_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdcard_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <4>;
        cap-sd-highspeed;
 &sd_emmc_c {
        status = "okay";
        pinctrl-0 = <&emmc_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&emmc_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <8>;
-       cap-sd-highspeed;
        cap-mmc-highspeed;
        max-frequency = <200000000>;
        non-removable;
index 9697a7a..4b17a76 100644 (file)
 
                states = <3300000 0>,
                         <1800000 1>;
+
+               regulator-settling-time-up-us = <100>;
+               regulator-settling-time-down-us = <5000>;
        };
 
        wifi_32k: wifi-32k {
 &sd_emmc_a {
        status = "okay";
        pinctrl-0 = <&sdio_pins>, <&sdio_irq_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdio_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
        #address-cells = <1>;
        #size-cells = <0>;
 
 &sd_emmc_b {
        status = "okay";
        pinctrl-0 = <&sdcard_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdcard_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <4>;
        cap-sd-highspeed;
-       max-frequency = <100000000>;
+       sd-uhs-sdr12;
+       sd-uhs-sdr25;
+       sd-uhs-sdr50;
+       sd-uhs-sdr104;
+       max-frequency = <200000000>;
        disable-wp;
 
        cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
 &sd_emmc_c {
        status = "disabled";
        pinctrl-0 = <&emmc_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&emmc_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <8>;
-       cap-sd-highspeed;
        max-frequency = <200000000>;
        non-removable;
        disable-wp;
index 9c59c3c..38dfdde 100644 (file)
@@ -51,7 +51,7 @@
 / {
        compatible = "nexbox,a95x", "amlogic,meson-gxbb";
        model = "NEXBOX A95X";
-       
+
        aliases {
                serial0 = &uart_AO;
        };
 &sd_emmc_a {
        status = "okay";
        pinctrl-0 = <&sdio_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdio_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
        #address-cells = <1>;
        #size-cells = <0>;
 
 &sd_emmc_b {
        status = "okay";
        pinctrl-0 = <&sdcard_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdcard_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <4>;
        cap-sd-highspeed;
 &sd_emmc_c {
        status = "okay";
        pinctrl-0 = <&emmc_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&emmc_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <8>;
-       cap-sd-highspeed;
        cap-mmc-highspeed;
        max-frequency = <200000000>;
        non-removable;
index d147c85..1ffa1c2 100644 (file)
@@ -50,7 +50,7 @@
 / {
        compatible = "hardkernel,odroid-c2", "amlogic,meson-gxbb";
        model = "Hardkernel ODROID-C2";
-       
+
        aliases {
                serial0 = &uart_AO;
        };
 &sd_emmc_b {
        status = "okay";
        pinctrl-0 = <&sdcard_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdcard_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <4>;
        cap-sd-highspeed;
 &sd_emmc_c {
        status = "okay";
        pinctrl-0 = <&emmc_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&emmc_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <8>;
-       cap-sd-highspeed;
        max-frequency = <200000000>;
        non-removable;
        disable-wp;
index 81ffc68..23c08c3 100644 (file)
 &sd_emmc_a {
        status = "okay";
        pinctrl-0 = <&sdio_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdio_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
        #address-cells = <1>;
        #size-cells = <0>;
 
 &sd_emmc_b {
        status = "okay";
        pinctrl-0 = <&sdcard_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdcard_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <4>;
        cap-sd-highspeed;
+       sd-uhs-sdr12;
+       sd-uhs-sdr25;
+       sd-uhs-sdr50;
        max-frequency = <100000000>;
        disable-wp;
 
 &sd_emmc_c {
        status = "okay";
        pinctrl-0 = <&emmc_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&emmc_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <8>;
-       cap-sd-highspeed;
        cap-mmc-highspeed;
        max-frequency = <200000000>;
        non-removable;
index 346753f..f2bc6de 100644 (file)
 &sd_emmc_a {
        status = "okay";
        pinctrl-0 = <&sdio_pins &sdio_irq_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdio_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
        #address-cells = <1>;
        #size-cells = <0>;
 
 &sd_emmc_b {
        status = "okay";
        pinctrl-0 = <&sdcard_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdcard_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <4>;
        cap-sd-highspeed;
 &sd_emmc_c {
        status = "okay";
        pinctrl-0 = <&emmc_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&emmc_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <8>;
-       cap-sd-highspeed;
        cap-mmc-highspeed;
        max-frequency = <200000000>;
        non-removable;
index 52f1687..af834cd 100644 (file)
                        };
                };
 
+               emmc_clk_gate_pins: emmc_clk_gate {
+                       mux {
+                               groups = "BOOT_8";
+                               function = "gpio_periphs";
+                       };
+                       cfg-pull-down {
+                               pins = "BOOT_8";
+                               bias-pull-down;
+                       };
+               };
+
                nor_pins: nor {
                        mux {
                                groups = "nor_d",
                        };
                };
 
+               sdcard_clk_gate_pins: sdcard_clk_gate {
+                       mux {
+                               groups = "CARD_2";
+                               function = "gpio_periphs";
+                       };
+                       cfg-pull-down {
+                               pins = "CARD_2";
+                               bias-pull-down;
+                       };
+               };
+
                sdio_pins: sdio {
                        mux {
                                groups = "sdio_d0",
                        };
                };
 
+               sdio_clk_gate_pins: sdio_clk_gate {
+                       mux {
+                               groups = "GPIOX_4";
+                               function = "gpio_periphs";
+                       };
+                       cfg-pull-down {
+                               pins = "GPIOX_4";
+                               bias-pull-down;
+                       };
+               };
+
                sdio_irq_pins: sdio_irq {
                        mux {
                                groups = "sdio_irq";
 
 &sd_emmc_a {
        clocks = <&clkc CLKID_SD_EMMC_A>,
-                <&xtal>,
+                <&clkc CLKID_SD_EMMC_A_CLK0>,
                 <&clkc CLKID_FCLK_DIV2>;
        clock-names = "core", "clkin0", "clkin1";
 };
 
 &sd_emmc_b {
        clocks = <&clkc CLKID_SD_EMMC_B>,
-                <&xtal>,
+                <&clkc CLKID_SD_EMMC_B_CLK0>,
                 <&clkc CLKID_FCLK_DIV2>;
        clock-names = "core", "clkin0", "clkin1";
 };
 
 &sd_emmc_c {
        clocks = <&clkc CLKID_SD_EMMC_C>,
-                <&xtal>,
+                <&clkc CLKID_SD_EMMC_C_CLK0>,
                 <&clkc CLKID_FCLK_DIV2>;
        clock-names = "core", "clkin0", "clkin1";
 };
index 2a5804c..977b424 100644 (file)
 &sd_emmc_b {
        status = "okay";
        pinctrl-0 = <&sdcard_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdcard_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <4>;
        cap-sd-highspeed;
 &sd_emmc_c {
        status = "okay";
        pinctrl-0 = <&emmc_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&emmc_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <8>;
-       cap-sd-highspeed;
        cap-mmc-highspeed;
        max-frequency = <100000000>;
        non-removable;
index 69ca14a..64c54c9 100644 (file)
@@ -91,6 +91,9 @@
 
                states = <3300000 0>,
                         <1800000 1>;
+
+               regulator-settling-time-up-us = <200>;
+               regulator-settling-time-down-us = <50000>;
        };
 
        vddio_boot: regulator-vddio_boot {
 &sd_emmc_b {
        status = "okay";
        pinctrl-0 = <&sdcard_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdcard_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <4>;
        cap-sd-highspeed;
+       sd-uhs-sdr12;
+       sd-uhs-sdr25;
+       sd-uhs-sdr50;
        max-frequency = <100000000>;
        disable-wp;
 
 &sd_emmc_c {
        status = "okay";
        pinctrl-0 = <&emmc_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&emmc_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <8>;
        cap-mmc-highspeed;
+       mmc-ddr-3_3v;
        max-frequency = <50000000>;
        non-removable;
        disable-wp;
index 4c2ac76..1b8f328 100644 (file)
 &sd_emmc_a {
        status = "okay";
        pinctrl-0 = <&sdio_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdio_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
        #address-cells = <1>;
        #size-cells = <0>;
 
 &sd_emmc_b {
        status = "okay";
        pinctrl-0 = <&sdcard_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdcard_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <4>;
        cap-sd-highspeed;
 &sd_emmc_c {
        status = "okay";
        pinctrl-0 = <&emmc_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&emmc_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <8>;
-       cap-sd-highspeed;
        cap-mmc-highspeed;
        max-frequency = <200000000>;
        non-removable;
index f3eea8e..129af90 100644 (file)
@@ -95,7 +95,8 @@
 &sd_emmc_a {
        status = "okay";
        pinctrl-0 = <&sdio_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdio_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
        #address-cells = <1>;
        #size-cells = <0>;
 
 &sd_emmc_b {
        status = "okay";
        pinctrl-0 = <&sdcard_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdcard_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <4>;
        cap-sd-highspeed;
 &sd_emmc_c {
        status = "okay";
        pinctrl-0 = <&emmc_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&emmc_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <8>;
-       cap-sd-highspeed;
        cap-mmc-highspeed;
        max-frequency = <200000000>;
        non-removable;
index d6876e6..d8dd329 100644 (file)
                        };
                };
 
+               emmc_clk_gate_pins: emmc_clk_gate {
+                       mux {
+                               groups = "BOOT_8";
+                               function = "gpio_periphs";
+                       };
+                       cfg-pull-down {
+                               pins = "BOOT_8";
+                               bias-pull-down;
+                       };
+               };
+
                nor_pins: nor {
                        mux {
                                groups = "nor_d",
                        };
                };
 
+               sdcard_clk_gate_pins: sdcard_clk_gate {
+                       mux {
+                               groups = "CARD_2";
+                               function = "gpio_periphs";
+                       };
+                       cfg-pull-down {
+                               pins = "CARD_2";
+                               bias-pull-down;
+                       };
+               };
+
                sdio_pins: sdio {
                        mux {
                                groups = "sdio_d0",
                        };
                };
 
+               sdio_clk_gate_pins: sdio_clk_gate {
+                       mux {
+                               groups = "GPIOX_4";
+                               function = "gpio_periphs";
+                       };
+                       cfg-pull-down {
+                               pins = "GPIOX_4";
+                               bias-pull-down;
+                       };
+               };
+
                sdio_irq_pins: sdio_irq {
                        mux {
                                groups = "sdio_irq";
 
 &sd_emmc_a {
        clocks = <&clkc CLKID_SD_EMMC_A>,
-                <&xtal>,
+                <&clkc CLKID_SD_EMMC_A_CLK0>,
                 <&clkc CLKID_FCLK_DIV2>;
        clock-names = "core", "clkin0", "clkin1";
 };
 
 &sd_emmc_b {
        clocks = <&clkc CLKID_SD_EMMC_B>,
-                <&xtal>,
+                <&clkc CLKID_SD_EMMC_B_CLK0>,
                 <&clkc CLKID_FCLK_DIV2>;
        clock-names = "core", "clkin0", "clkin1";
 };
 
 &sd_emmc_c {
        clocks = <&clkc CLKID_SD_EMMC_C>,
-                <&xtal>,
+                <&clkc CLKID_SD_EMMC_C_CLK0>,
                 <&clkc CLKID_FCLK_DIV2>;
        clock-names = "core", "clkin0", "clkin1";
 };
index 9b10c5f..22c6977 100644 (file)
 &sd_emmc_b {
        status = "okay";
        pinctrl-0 = <&sdcard_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&sdcard_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <4>;
        cap-sd-highspeed;
 &sd_emmc_c {
        status = "okay";
        pinctrl-0 = <&emmc_pins>;
-       pinctrl-names = "default";
+       pinctrl-1 = <&emmc_clk_gate_pins>;
+       pinctrl-names = "default", "clk-gate";
 
        bus-width = <8>;
-       cap-sd-highspeed;
        cap-mmc-highspeed;
        max-frequency = <200000000>;
        non-removable;
index 08f1dd6..470f72b 100644 (file)
        pinctrl-names = "default";
 
        bus-width = <8>;
-       cap-sd-highspeed;
        cap-mmc-highspeed;
        max-frequency = <200000000>;
        non-removable;
index 4d36071..30d48ec 100644 (file)
 
                        ap_syscon: system-controller@6f4000 {
                                compatible = "syscon", "simple-mfd";
-                               reg = <0x6f4000 0x1000>;
+                               reg = <0x6f4000 0x2000>;
 
                                ap_clk: clock {
                                        compatible = "marvell,ap806-clock";
                                        compatible = "marvell,ap806-pinctrl";
                                };
 
-                               ap_gpio: gpio {
+                               ap_gpio: gpio@1040 {
                                        compatible = "marvell,armada-8k-gpio";
                                        offset = <0x1040>;
                                        ngpios = <20>;
index e0518b4..19fbaa5 100644 (file)
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x0>;
                        enable-method = "psci";
-                       clocks = <&cru ARMCLKL>;
-                       operating-points-v2 = <&cluster0_opp>;
+
                        #cooling-cells = <2>; /* min followed by max */
                };
 
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x1>;
                        enable-method = "psci";
-                       clocks = <&cru ARMCLKL>;
-                       operating-points-v2 = <&cluster0_opp>;
                };
 
                cpu_l2: cpu@2 {
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x2>;
                        enable-method = "psci";
-                       clocks = <&cru ARMCLKL>;
-                       operating-points-v2 = <&cluster0_opp>;
                };
 
                cpu_l3: cpu@3 {
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x3>;
                        enable-method = "psci";
-                       clocks = <&cru ARMCLKL>;
-                       operating-points-v2 = <&cluster0_opp>;
                };
 
                cpu_b0: cpu@100 {
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x100>;
                        enable-method = "psci";
-                       clocks = <&cru ARMCLKB>;
-                       operating-points-v2 = <&cluster1_opp>;
+
                        #cooling-cells = <2>; /* min followed by max */
                };
 
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x101>;
                        enable-method = "psci";
-                       clocks = <&cru ARMCLKB>;
-                       operating-points-v2 = <&cluster1_opp>;
                };
 
                cpu_b2: cpu@102 {
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x102>;
                        enable-method = "psci";
-                       clocks = <&cru ARMCLKB>;
-                       operating-points-v2 = <&cluster1_opp>;
                };
 
                cpu_b3: cpu@103 {
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x103>;
                        enable-method = "psci";
-                       clocks = <&cru ARMCLKB>;
-                       operating-points-v2 = <&cluster1_opp>;
-               };
-       };
-
-       cluster0_opp: opp-table0 {
-               compatible = "operating-points-v2";
-               opp-shared;
-
-               opp00 {
-                       opp-hz = /bits/ 64 <312000000>;
-                       opp-microvolt = <950000>;
-                       clock-latency-ns = <40000>;
-               };
-               opp01 {
-                       opp-hz = /bits/ 64 <408000000>;
-                       opp-microvolt = <950000>;
-               };
-               opp02 {
-                       opp-hz = /bits/ 64 <600000000>;
-                       opp-microvolt = <950000>;
-               };
-               opp03 {
-                       opp-hz = /bits/ 64 <816000000>;
-                       opp-microvolt = <1025000>;
-               };
-               opp04 {
-                       opp-hz = /bits/ 64 <1008000000>;
-                       opp-microvolt = <1125000>;
-               };
-       };
-
-       cluster1_opp: opp-table1 {
-               compatible = "operating-points-v2";
-               opp-shared;
-
-               opp00 {
-                       opp-hz = /bits/ 64 <312000000>;
-                       opp-microvolt = <950000>;
-                       clock-latency-ns = <40000>;
-               };
-               opp01 {
-                       opp-hz = /bits/ 64 <408000000>;
-                       opp-microvolt = <950000>;
-               };
-               opp02 {
-                       opp-hz = /bits/ 64 <600000000>;
-                       opp-microvolt = <950000>;
-               };
-               opp03 {
-                       opp-hz = /bits/ 64 <816000000>;
-                       opp-microvolt = <975000>;
-               };
-               opp04 {
-                       opp-hz = /bits/ 64 <1008000000>;
-                       opp-microvolt = <1050000>;
                };
        };
 
index d79e9b3..ab7629c 100644 (file)
                compatible = "rockchip,rk3399-mipi-dsi", "snps,dw-mipi-dsi";
                reg = <0x0 0xff960000 0x0 0x8000>;
                interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH 0>;
-               clocks = <&cru SCLK_MIPIDPHY_REF>, <&cru PCLK_MIPI_DSI0>,
-                        <&cru SCLK_DPHY_TX0_CFG>;
-               clock-names = "ref", "pclk", "phy_cfg";
+               clocks = <&cru SCLK_DPHY_PLL>, <&cru PCLK_MIPI_DSI0>,
+                        <&cru SCLK_DPHY_TX0_CFG>, <&cru PCLK_VIO_GRF>;
+               clock-names = "ref", "pclk", "phy_cfg", "grf";
                power-domains = <&power RK3399_PD_VIO>;
                rockchip,grf = <&grf>;
                status = "disabled";
index 3585a5e..f7c4d21 100644 (file)
 #define KERNEL_END        _end
 
 /*
- * The size of the KASAN shadow region. This should be 1/8th of the
- * size of the entire kernel virtual address space.
+ * KASAN requires 1/8th of the kernel virtual address space for the shadow
+ * region. KASAN can bloat the stack significantly, so double the (minimum)
+ * stack size when KASAN is in use.
  */
 #ifdef CONFIG_KASAN
 #define KASAN_SHADOW_SIZE      (UL(1) << (VA_BITS - 3))
+#define KASAN_THREAD_SHIFT     1
 #else
 #define KASAN_SHADOW_SIZE      (0)
+#define KASAN_THREAD_SHIFT     0
 #endif
 
-#define MIN_THREAD_SHIFT       14
+#define MIN_THREAD_SHIFT       (14 + KASAN_THREAD_SHIFT)
 
 /*
  * VMAP'd stacks are allocated at page granularity, so we must ensure that such
index f0e6d71..d06fbe4 100644 (file)
@@ -649,4 +649,4 @@ static int __init armv8_deprecated_init(void)
        return 0;
 }
 
-late_initcall(armv8_deprecated_init);
+core_initcall(armv8_deprecated_init);
index cd52d36..21e2c95 100644 (file)
@@ -1307,4 +1307,4 @@ static int __init enable_mrs_emulation(void)
        return 0;
 }
 
-late_initcall(enable_mrs_emulation);
+core_initcall(enable_mrs_emulation);
index f444f37..5d547de 100644 (file)
@@ -444,4 +444,4 @@ static int __init fpsimd_init(void)
 
        return 0;
 }
-late_initcall(fpsimd_init);
+core_initcall(fpsimd_init);
index 2069e9b..b64958b 100644 (file)
@@ -97,7 +97,7 @@ static void data_abort_decode(unsigned int esr)
                         (esr & ESR_ELx_SF) >> ESR_ELx_SF_SHIFT,
                         (esr & ESR_ELx_AR) >> ESR_ELx_AR_SHIFT);
        } else {
-               pr_alert("  ISV = 0, ISS = 0x%08lu\n", esr & ESR_ELx_ISS_MASK);
+               pr_alert("  ISV = 0, ISS = 0x%08lx\n", esr & ESR_ELx_ISS_MASK);
        }
 
        pr_alert("  CM = %lu, WnR = %lu\n",
index 87cde1e..0777f3a 100644 (file)
@@ -194,6 +194,10 @@ config TIMER_DIVIDE
        int "Timer divider (integer)"
        default "128"
 
+config CPU_BIG_ENDIAN
+        bool "Generate big endian code"
+       default n
+
 config CPU_LITTLE_ENDIAN
         bool "Generate little endian code"
        default n
index 647dd94..72b96f2 100644 (file)
@@ -114,6 +114,15 @@ static void set_eit_vector_entries(void)
        _flush_cache_copyback_all();
 }
 
+void abort(void)
+{
+       BUG();
+
+       /* if that doesn't kill us, halt */
+       panic("Oops failed to kill thread");
+}
+EXPORT_SYMBOL(abort);
+
 void __init trap_init(void)
 {
        set_eit_vector_entries();
index a45a67d..30f9239 100644 (file)
@@ -146,7 +146,7 @@ void machine_power_off(void)
 
        /* prevent soft lockup/stalled CPU messages for endless loop. */
        rcu_sysrq_start();
-       lockup_detector_suspend();
+       lockup_detector_soft_poweroff();
        for (;;);
 }
 
index 1df770e..7275fed 100644 (file)
@@ -102,10 +102,10 @@ static void cpufeatures_flush_tlb(void)
        case PVR_POWER8:
        case PVR_POWER8E:
        case PVR_POWER8NVL:
-               __flush_tlb_power8(POWER8_TLB_SETS);
+               __flush_tlb_power8(TLB_INVAL_SCOPE_GLOBAL);
                break;
        case PVR_POWER9:
-               __flush_tlb_power9(POWER9_TLB_SETS_HASH);
+               __flush_tlb_power9(TLB_INVAL_SCOPE_GLOBAL);
                break;
        default:
                pr_err("unknown CPU version for boot TLB flush\n");
index b76ca19..72f153c 100644 (file)
@@ -624,5 +624,18 @@ long __machine_check_early_realmode_p8(struct pt_regs *regs)
 
 long __machine_check_early_realmode_p9(struct pt_regs *regs)
 {
+       /*
+        * On POWER9 DD2.1 and below, it's possible to get a machine check
+        * caused by a paste instruction where only DSISR bit 25 is set. This
+        * will result in the MCE handler seeing an unknown event and the kernel
+        * crashing. An MCE that occurs like this is spurious, so we don't need
+        * to do anything in terms of servicing it. If there is something that
+        * needs to be serviced, the CPU will raise the MCE again with the
+        * correct DSISR so that it can be serviced properly. So detect this
+        * case and mark it as handled.
+        */
+       if (SRR1_MC_LOADSTORE(regs->msr) && regs->dsisr == 0x02000000)
+               return 1;
+
        return mce_handle_error(regs, mce_p9_derror_table, mce_p9_ierror_table);
 }
index 0ac741f..2e3bc16 100644 (file)
@@ -904,9 +904,6 @@ void __init setup_arch(char **cmdline_p)
 #endif
 #endif
 
-#ifdef CONFIG_PPC_64K_PAGES
-       init_mm.context.pte_frag = NULL;
-#endif
 #ifdef CONFIG_SPAPR_TCE_IOMMU
        mm_iommu_init(&init_mm);
 #endif
index 2f6eadd..c702a89 100644 (file)
@@ -310,9 +310,6 @@ static int start_wd_on_cpu(unsigned int cpu)
        if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
                return 0;
 
-       if (watchdog_suspended)
-               return 0;
-
        if (!cpumask_test_cpu(cpu, &watchdog_cpumask))
                return 0;
 
@@ -358,36 +355,39 @@ static void watchdog_calc_timeouts(void)
        wd_timer_period_ms = watchdog_thresh * 1000 * 2 / 5;
 }
 
-void watchdog_nmi_reconfigure(void)
+void watchdog_nmi_stop(void)
 {
        int cpu;
 
-       watchdog_calc_timeouts();
-
        for_each_cpu(cpu, &wd_cpus_enabled)
                stop_wd_on_cpu(cpu);
+}
 
+void watchdog_nmi_start(void)
+{
+       int cpu;
+
+       watchdog_calc_timeouts();
        for_each_cpu_and(cpu, cpu_online_mask, &watchdog_cpumask)
                start_wd_on_cpu(cpu);
 }
 
 /*
- * This runs after lockup_detector_init() which sets up watchdog_cpumask.
+ * Invoked from core watchdog init.
  */
-static int __init powerpc_watchdog_init(void)
+int __init watchdog_nmi_probe(void)
 {
        int err;
 
-       watchdog_calc_timeouts();
-
-       err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powerpc/watchdog:online",
-                               start_wd_on_cpu, stop_wd_on_cpu);
-       if (err < 0)
+       err = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
+                                       "powerpc/watchdog:online",
+                                       start_wd_on_cpu, stop_wd_on_cpu);
+       if (err < 0) {
                pr_warn("Watchdog could not be initialized");
-
+               return err;
+       }
        return 0;
 }
-arch_initcall(powerpc_watchdog_init);
 
 static void handle_backtrace_ipi(struct pt_regs *regs)
 {
index 1330462..bf45784 100644 (file)
@@ -622,7 +622,7 @@ int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server,
                return -EINVAL;
        state = &sb->irq_state[idx];
        arch_spin_lock(&sb->lock);
-       *server = state->guest_server;
+       *server = state->act_server;
        *priority = state->guest_priority;
        arch_spin_unlock(&sb->lock);
 
@@ -1331,7 +1331,7 @@ static int xive_get_source(struct kvmppc_xive *xive, long irq, u64 addr)
        xive->saved_src_count++;
 
        /* Convert saved state into something compatible with xics */
-       val = state->guest_server;
+       val = state->act_server;
        prio = state->saved_scan_prio;
 
        if (prio == MASKED) {
@@ -1507,7 +1507,6 @@ static int xive_set_source(struct kvmppc_xive *xive, long irq, u64 addr)
        /* First convert prio and mark interrupt as untargetted */
        act_prio = xive_prio_from_guest(guest_prio);
        state->act_priority = MASKED;
-       state->guest_server = server;
 
        /*
         * We need to drop the lock due to the mutex below. Hopefully
index 5938f76..6ba63f8 100644 (file)
@@ -35,7 +35,6 @@ struct kvmppc_xive_irq_state {
        struct xive_irq_data *pt_data;  /* XIVE Pass-through associated data */
 
        /* Targetting as set by guest */
-       u32 guest_server;               /* Current guest selected target */
        u8 guest_priority;              /* Guest set priority */
        u8 saved_priority;              /* Saved priority when masking */
 
index 65eda19..f6c7f54 100644 (file)
@@ -361,9 +361,9 @@ static int change_page_attr(struct page *page, int numpages, pgprot_t prot)
                        break;
        }
        wmb();
+       local_irq_restore(flags);
        flush_tlb_kernel_range((unsigned long)page_address(start),
                               (unsigned long)page_address(page));
-       local_irq_restore(flags);
        return err;
 }
 
index 897aa14..bbb73aa 100644 (file)
@@ -272,7 +272,15 @@ static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
 static unsigned long pnv_memory_block_size(void)
 {
-       return 256UL * 1024 * 1024;
+       /*
+        * We map the kernel linear region with 1GB large pages on radix. For
+        * memory hot unplug to work our memory block size must be at least
+        * this size.
+        */
+       if (radix_enabled())
+               return 1UL * 1024 * 1024 * 1024;
+       else
+               return 256UL * 1024 * 1024;
 }
 #endif
 
index 9234be1..5011ffe 100644 (file)
@@ -71,6 +71,8 @@
 #define RIWAR_WRTYP_ALLOC      0x00006000
 #define RIWAR_SIZE_MASK                0x0000003F
 
+static DEFINE_SPINLOCK(fsl_rio_config_lock);
+
 #define __fsl_read_rio_config(x, addr, err, op)                \
        __asm__ __volatile__(                           \
                "1:     "op" %1,0(%2)\n"                \
@@ -184,6 +186,7 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
                        u8 hopcount, u32 offset, int len, u32 *val)
 {
        struct rio_priv *priv = mport->priv;
+       unsigned long flags;
        u8 *data;
        u32 rval, err = 0;
 
@@ -197,6 +200,8 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
        if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
                return -EINVAL;
 
+       spin_lock_irqsave(&fsl_rio_config_lock, flags);
+
        out_be32(&priv->maint_atmu_regs->rowtar,
                 (destid << 22) | (hopcount << 12) | (offset >> 12));
        out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
@@ -213,6 +218,7 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
                __fsl_read_rio_config(rval, data, err, "lwz");
                break;
        default:
+               spin_unlock_irqrestore(&fsl_rio_config_lock, flags);
                return -EINVAL;
        }
 
@@ -221,6 +227,7 @@ fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid,
                         err, destid, hopcount, offset);
        }
 
+       spin_unlock_irqrestore(&fsl_rio_config_lock, flags);
        *val = rval;
 
        return err;
@@ -244,7 +251,10 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
                        u8 hopcount, u32 offset, int len, u32 val)
 {
        struct rio_priv *priv = mport->priv;
+       unsigned long flags;
        u8 *data;
+       int ret = 0;
+
        pr_debug
                ("fsl_rio_config_write:"
                " index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n",
@@ -255,6 +265,8 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
        if (offset > (0x1000000 - len) || !IS_ALIGNED(offset, len))
                return -EINVAL;
 
+       spin_lock_irqsave(&fsl_rio_config_lock, flags);
+
        out_be32(&priv->maint_atmu_regs->rowtar,
                 (destid << 22) | (hopcount << 12) | (offset >> 12));
        out_be32(&priv->maint_atmu_regs->rowtear, (destid >> 10));
@@ -271,10 +283,11 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
                out_be32((u32 *) data, val);
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
        }
+       spin_unlock_irqrestore(&fsl_rio_config_lock, flags);
 
-       return 0;
+       return ret;
 }
 
 static void fsl_rio_inbound_mem_init(struct rio_priv *priv)
index ab7a74c..88b35a3 100644 (file)
 
 #define DOORBELL_MESSAGE_SIZE  0x08
 
+static DEFINE_SPINLOCK(fsl_rio_doorbell_lock);
+
 struct rio_msg_regs {
        u32 omr;
        u32 osr;
@@ -626,9 +628,13 @@ err_out:
 int fsl_rio_doorbell_send(struct rio_mport *mport,
                                int index, u16 destid, u16 data)
 {
+       unsigned long flags;
+
        pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n",
                 index, destid, data);
 
+       spin_lock_irqsave(&fsl_rio_doorbell_lock, flags);
+
        /* In the serial version silicons, such as MPC8548, MPC8641,
         * below operations is must be.
         */
@@ -638,6 +644,8 @@ int fsl_rio_doorbell_send(struct rio_mport *mport,
        out_be32(&dbell->dbell_regs->oddatr, (index << 20) | data);
        out_be32(&dbell->dbell_regs->odmr, 0x00000001);
 
+       spin_unlock_irqrestore(&fsl_rio_doorbell_lock, flags);
+
        return 0;
 }
 
index f387318..a3b8d7d 100644 (file)
@@ -1402,6 +1402,14 @@ void xive_teardown_cpu(void)
 
        if (xive_ops->teardown_cpu)
                xive_ops->teardown_cpu(cpu, xc);
+
+#ifdef CONFIG_SMP
+       /* Get rid of IPI */
+       xive_cleanup_cpu_ipi(cpu, xc);
+#endif
+
+       /* Disable and free the queues */
+       xive_cleanup_cpu_queues(cpu, xc);
 }
 
 void xive_kexec_teardown_cpu(int secondary)
index f24a70b..d9c4c93 100644 (file)
@@ -431,7 +431,11 @@ static int xive_spapr_get_ipi(unsigned int cpu, struct xive_cpu *xc)
 
 static void xive_spapr_put_ipi(unsigned int cpu, struct xive_cpu *xc)
 {
+       if (!xc->hw_ipi)
+               return;
+
        xive_irq_bitmap_free(xc->hw_ipi);
+       xc->hw_ipi = 0;
 }
 #endif /* CONFIG_SMP */
 
index 4d1ef6d..2ae0e93 100644 (file)
@@ -43,9 +43,7 @@ enum {
        GPIO_PG7, GPIO_PG6, GPIO_PG5, GPIO_PG4,
        GPIO_PG3, GPIO_PG2, GPIO_PG1, GPIO_PG0,
 
-       /* Port H */
-       GPIO_PH7, GPIO_PH6, GPIO_PH5, GPIO_PH4,
-       GPIO_PH3, GPIO_PH2, GPIO_PH1, GPIO_PH0,
+       /* Port H - Port H does not have a Data Register */
 
        /* Port I - not on device */
 
index 2a0ca87..13c495a 100644 (file)
@@ -45,9 +45,7 @@ enum {
        GPIO_PG7, GPIO_PG6, GPIO_PG5, GPIO_PG4,
        GPIO_PG3, GPIO_PG2, GPIO_PG1, GPIO_PG0,
 
-       /* Port H */
-       GPIO_PH7, GPIO_PH6, GPIO_PH5, GPIO_PH4,
-       GPIO_PH3, GPIO_PH2, GPIO_PH1, GPIO_PH0,
+       /* Port H - Port H does not have a Data Register */
 
        /* Port I - not on device */
 
index 3bb74e5..78961ab 100644 (file)
@@ -67,7 +67,7 @@ enum {
        GPIO_PTN3, GPIO_PTN2, GPIO_PTN1, GPIO_PTN0,
 
        /* PTQ */
-       GPIO_PTQ7, GPIO_PTQ6, GPIO_PTQ5, GPIO_PTQ4,
+       GPIO_PTQ6, GPIO_PTQ5, GPIO_PTQ4,
        GPIO_PTQ3, GPIO_PTQ2, GPIO_PTQ1, GPIO_PTQ0,
 
        /* PTR */
index 5340f3b..b40fb54 100644 (file)
@@ -40,7 +40,7 @@ enum {
 
        /* PTJ */
        GPIO_PTJ0, GPIO_PTJ1, GPIO_PTJ2, GPIO_PTJ3,
-       GPIO_PTJ4, GPIO_PTJ5, GPIO_PTJ6, GPIO_PTJ7_RESV,
+       GPIO_PTJ4, GPIO_PTJ5, GPIO_PTJ6,
 
        /* PTK */
        GPIO_PTK0, GPIO_PTK1, GPIO_PTK2, GPIO_PTK3,
@@ -48,7 +48,7 @@ enum {
 
        /* PTL */
        GPIO_PTL0, GPIO_PTL1, GPIO_PTL2, GPIO_PTL3,
-       GPIO_PTL4, GPIO_PTL5, GPIO_PTL6, GPIO_PTL7_RESV,
+       GPIO_PTL4, GPIO_PTL5, GPIO_PTL6,
 
        /* PTM */
        GPIO_PTM0, GPIO_PTM1, GPIO_PTM2, GPIO_PTM3,
@@ -56,7 +56,7 @@ enum {
 
        /* PTN */
        GPIO_PTN0, GPIO_PTN1, GPIO_PTN2, GPIO_PTN3,
-       GPIO_PTN4, GPIO_PTN5, GPIO_PTN6, GPIO_PTN7_RESV,
+       GPIO_PTN4, GPIO_PTN5, GPIO_PTN6,
 
        /* PTO */
        GPIO_PTO0, GPIO_PTO1, GPIO_PTO2, GPIO_PTO3,
@@ -68,7 +68,7 @@ enum {
 
        /* PTQ */
        GPIO_PTQ0, GPIO_PTQ1, GPIO_PTQ2, GPIO_PTQ3,
-       GPIO_PTQ4, GPIO_PTQ5, GPIO_PTQ6, GPIO_PTQ7_RESV,
+       GPIO_PTQ4, GPIO_PTQ5, GPIO_PTQ6,
 
        /* PTR */
        GPIO_PTR0, GPIO_PTR1, GPIO_PTR2, GPIO_PTR3,
index 829e89c..9fb9a1f 100644 (file)
@@ -4409,10 +4409,9 @@ static __init int fixup_ht_bug(void)
                return 0;
        }
 
-       if (lockup_detector_suspend() != 0) {
-               pr_debug("failed to disable PMU erratum BJ122, BV98, HSD29 workaround\n");
-               return 0;
-       }
+       cpus_read_lock();
+
+       hardlockup_detector_perf_stop();
 
        x86_pmu.flags &= ~(PMU_FL_EXCL_CNTRS | PMU_FL_EXCL_ENABLED);
 
@@ -4420,9 +4419,7 @@ static __init int fixup_ht_bug(void)
        x86_pmu.commit_scheduling = NULL;
        x86_pmu.stop_scheduling = NULL;
 
-       lockup_detector_resume();
-
-       cpus_read_lock();
+       hardlockup_detector_perf_restart();
 
        for_each_online_cpu(c)
                free_excl_cntrs(c);
index bc62e7c..59ad3d1 100644 (file)
@@ -88,7 +88,7 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
 bool kvm_para_available(void);
 unsigned int kvm_arch_para_features(void);
 void __init kvm_guest_init(void);
-void kvm_async_pf_task_wait(u32 token);
+void kvm_async_pf_task_wait(u32 token, int interrupt_kernel);
 void kvm_async_pf_task_wake(u32 token);
 u32 kvm_read_and_reset_pf_reason(void);
 extern void kvm_disable_steal_time(void);
@@ -103,7 +103,7 @@ static inline void kvm_spinlock_init(void)
 
 #else /* CONFIG_KVM_GUEST */
 #define kvm_guest_init() do {} while (0)
-#define kvm_async_pf_task_wait(T) do {} while(0)
+#define kvm_async_pf_task_wait(T, I) do {} while(0)
 #define kvm_async_pf_task_wake(T) do {} while(0)
 
 static inline bool kvm_para_available(void)
index e675704..8bb9594 100644 (file)
@@ -117,7 +117,11 @@ static struct kvm_task_sleep_node *_find_apf_task(struct kvm_task_sleep_head *b,
        return NULL;
 }
 
-void kvm_async_pf_task_wait(u32 token)
+/*
+ * @interrupt_kernel: Is this called from a routine which interrupts the kernel
+ *                   (other than user space)?
+ */
+void kvm_async_pf_task_wait(u32 token, int interrupt_kernel)
 {
        u32 key = hash_32(token, KVM_TASK_SLEEP_HASHBITS);
        struct kvm_task_sleep_head *b = &async_pf_sleepers[key];
@@ -140,8 +144,10 @@ void kvm_async_pf_task_wait(u32 token)
 
        n.token = token;
        n.cpu = smp_processor_id();
-       n.halted = is_idle_task(current) || preempt_count() > 1 ||
-                  rcu_preempt_depth();
+       n.halted = is_idle_task(current) ||
+                  (IS_ENABLED(CONFIG_PREEMPT_COUNT)
+                   ? preempt_count() > 1 || rcu_preempt_depth()
+                   : interrupt_kernel);
        init_swait_queue_head(&n.wq);
        hlist_add_head(&n.link, &b->list);
        raw_spin_unlock(&b->lock);
@@ -269,7 +275,7 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code)
        case KVM_PV_REASON_PAGE_NOT_PRESENT:
                /* page is swapped out by the host. */
                prev_state = exception_enter();
-               kvm_async_pf_task_wait((u32)read_cr2());
+               kvm_async_pf_task_wait((u32)read_cr2(), !user_mode(regs));
                exception_exit(prev_state);
                break;
        case KVM_PV_REASON_PAGE_READY:
index 3ea6244..3c48bc8 100644 (file)
@@ -23,6 +23,7 @@ config KVM
        depends on HIGH_RES_TIMERS
        # for TASKSTATS/TASK_DELAY_ACCT:
        depends on NET && MULTIUSER
+       depends on X86_LOCAL_APIC
        select PREEMPT_NOTIFIERS
        select MMU_NOTIFIER
        select ANON_INODES
index a36254c..d90cdc7 100644 (file)
@@ -425,8 +425,10 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
        #op " %al \n\t" \
        FOP_RET
 
-asm(".global kvm_fastop_exception \n"
-    "kvm_fastop_exception: xor %esi, %esi; ret");
+asm(".pushsection .fixup, \"ax\"\n"
+    ".global kvm_fastop_exception \n"
+    "kvm_fastop_exception: xor %esi, %esi; ret\n"
+    ".popsection");
 
 FOP_START(setcc)
 FOP_SETCC(seto)
index eca30c1..106d4a0 100644 (file)
@@ -3837,7 +3837,7 @@ int kvm_handle_page_fault(struct kvm_vcpu *vcpu, u64 error_code,
        case KVM_PV_REASON_PAGE_NOT_PRESENT:
                vcpu->arch.apf.host_apf_reason = 0;
                local_irq_disable();
-               kvm_async_pf_task_wait(fault_address);
+               kvm_async_pf_task_wait(fault_address, 0);
                local_irq_enable();
                break;
        case KVM_PV_REASON_PAGE_READY:
index 8c95736..0554e8a 100644 (file)
@@ -284,9 +284,9 @@ static void emit_bpf_tail_call(u8 **pprog)
        /* if (index >= array->map.max_entries)
         *   goto out;
         */
-       EMIT4(0x48, 0x8B, 0x46,                   /* mov rax, qword ptr [rsi + 16] */
+       EMIT2(0x89, 0xD2);                        /* mov edx, edx */
+       EMIT3(0x39, 0x56,                         /* cmp dword ptr [rsi + 16], edx */
              offsetof(struct bpf_array, map.max_entries));
-       EMIT3(0x48, 0x39, 0xD0);                  /* cmp rax, rdx */
 #define OFFSET1 43 /* number of bytes to jump */
        EMIT2(X86_JBE, OFFSET1);                  /* jbe out */
        label1 = cnt;
index 980e730..de294d7 100644 (file)
@@ -815,10 +815,14 @@ int blk_mq_debugfs_register(struct request_queue *q)
                goto err;
 
        /*
-        * blk_mq_init_hctx() attempted to do this already, but q->debugfs_dir
+        * blk_mq_init_sched() attempted to do this already, but q->debugfs_dir
         * didn't exist yet (because we don't know what to name the directory
         * until the queue is registered to a gendisk).
         */
+       if (q->elevator && !q->sched_debugfs_dir)
+               blk_mq_debugfs_register_sched(q);
+
+       /* Similarly, blk_mq_init_hctx() couldn't do this previously. */
        queue_for_each_hw_ctx(q, hctx, i) {
                if (!hctx->debugfs_dir && blk_mq_debugfs_register_hctx(q, hctx))
                        goto err;
index 0fea76a..17816a0 100644 (file)
@@ -1911,11 +1911,11 @@ static void throtl_upgrade_state(struct throtl_data *td)
 
                tg->disptime = jiffies - 1;
                throtl_select_dispatch(sq);
-               throtl_schedule_next_dispatch(sq, false);
+               throtl_schedule_next_dispatch(sq, true);
        }
        rcu_read_unlock();
        throtl_select_dispatch(&td->service_queue);
-       throtl_schedule_next_dispatch(&td->service_queue, false);
+       throtl_schedule_next_dispatch(&td->service_queue, true);
        queue_work(kthrotld_workqueue, &td->dispatch_work);
 }
 
index dbddff8..15d25cc 100644 (file)
@@ -207,20 +207,34 @@ static int bsg_init_rq(struct request_queue *q, struct request *req, gfp_t gfp)
        struct bsg_job *job = blk_mq_rq_to_pdu(req);
        struct scsi_request *sreq = &job->sreq;
 
+       /* called right after the request is allocated for the request_queue */
+
+       sreq->sense = kzalloc(SCSI_SENSE_BUFFERSIZE, gfp);
+       if (!sreq->sense)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void bsg_initialize_rq(struct request *req)
+{
+       struct bsg_job *job = blk_mq_rq_to_pdu(req);
+       struct scsi_request *sreq = &job->sreq;
+       void *sense = sreq->sense;
+
+       /* called right before the request is given to the request_queue user */
+
        memset(job, 0, sizeof(*job));
 
        scsi_req_init(sreq);
+
+       sreq->sense = sense;
        sreq->sense_len = SCSI_SENSE_BUFFERSIZE;
-       sreq->sense = kzalloc(sreq->sense_len, gfp);
-       if (!sreq->sense)
-               return -ENOMEM;
 
        job->req = req;
-       job->reply = sreq->sense;
+       job->reply = sense;
        job->reply_len = sreq->sense_len;
        job->dd_data = job + 1;
-
-       return 0;
 }
 
 static void bsg_exit_rq(struct request_queue *q, struct request *req)
@@ -251,6 +265,7 @@ struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
        q->cmd_size = sizeof(struct bsg_job) + dd_job_size;
        q->init_rq_fn = bsg_init_rq;
        q->exit_rq_fn = bsg_exit_rq;
+       q->initialize_rq_fn = bsg_initialize_rq;
        q->request_fn = bsg_request_fn;
 
        ret = blk_init_allocated_queue(q);
index 9565d57..de56394 100644 (file)
@@ -1178,12 +1178,44 @@ dev_put:
        return ret;
 }
 
+static bool __init iort_enable_acs(struct acpi_iort_node *iort_node)
+{
+       if (iort_node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX) {
+               struct acpi_iort_node *parent;
+               struct acpi_iort_id_mapping *map;
+               int i;
+
+               map = ACPI_ADD_PTR(struct acpi_iort_id_mapping, iort_node,
+                                  iort_node->mapping_offset);
+
+               for (i = 0; i < iort_node->mapping_count; i++, map++) {
+                       if (!map->output_reference)
+                               continue;
+
+                       parent = ACPI_ADD_PTR(struct acpi_iort_node,
+                                       iort_table,  map->output_reference);
+                       /*
+                        * If we detect a RC->SMMU mapping, make sure
+                        * we enable ACS on the system.
+                        */
+                       if ((parent->type == ACPI_IORT_NODE_SMMU) ||
+                               (parent->type == ACPI_IORT_NODE_SMMU_V3)) {
+                               pci_request_acs();
+                               return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
 static void __init iort_init_platform_devices(void)
 {
        struct acpi_iort_node *iort_node, *iort_end;
        struct acpi_table_iort *iort;
        struct fwnode_handle *fwnode;
        int i, ret;
+       bool acs_enabled = false;
 
        /*
         * iort_table and iort both point to the start of IORT table, but
@@ -1203,6 +1235,9 @@ static void __init iort_init_platform_devices(void)
                        return;
                }
 
+               if (!acs_enabled)
+                       acs_enabled = iort_enable_acs(iort_node);
+
                if ((iort_node->type == ACPI_IORT_NODE_SMMU) ||
                        (iort_node->type == ACPI_IORT_NODE_SMMU_V3)) {
 
index d055b3f..ab34239 100644 (file)
@@ -2217,7 +2217,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
                                       debug_id, (u64)fda->num_fds);
                                continue;
                        }
-                       fd_array = (u32 *)(parent_buffer + fda->parent_offset);
+                       fd_array = (u32 *)(parent_buffer + (uintptr_t)fda->parent_offset);
                        for (fd_index = 0; fd_index < fda->num_fds; fd_index++)
                                task_close_fd(proc, fd_array[fd_index]);
                } break;
@@ -2326,7 +2326,6 @@ static int binder_translate_handle(struct flat_binder_object *fp,
                             (u64)node->ptr);
                binder_node_unlock(node);
        } else {
-               int ret;
                struct binder_ref_data dest_rdata;
 
                binder_node_unlock(node);
@@ -2442,7 +2441,7 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda,
         */
        parent_buffer = parent->buffer -
                binder_alloc_get_user_buffer_offset(&target_proc->alloc);
-       fd_array = (u32 *)(parent_buffer + fda->parent_offset);
+       fd_array = (u32 *)(parent_buffer + (uintptr_t)fda->parent_offset);
        if (!IS_ALIGNED((unsigned long)fd_array, sizeof(u32))) {
                binder_user_error("%d:%d parent offset not aligned correctly.\n",
                                  proc->pid, thread->pid);
@@ -2508,7 +2507,7 @@ static int binder_fixup_parent(struct binder_transaction *t,
                                  proc->pid, thread->pid);
                return -EINVAL;
        }
-       parent_buffer = (u8 *)(parent->buffer -
+       parent_buffer = (u8 *)((uintptr_t)parent->buffer -
                        binder_alloc_get_user_buffer_offset(
                                &target_proc->alloc));
        *(binder_uintptr_t *)(parent_buffer + bp->parent_offset) = bp->buffer;
@@ -3083,6 +3082,7 @@ static void binder_transaction(struct binder_proc *proc,
 err_dead_proc_or_thread:
        return_error = BR_DEAD_REPLY;
        return_error_line = __LINE__;
+       binder_dequeue_work(proc, tcomplete);
 err_translate_failed:
 err_bad_object_type:
 err_bad_offset:
index 8fe1658..064f5e3 100644 (file)
@@ -913,6 +913,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
        struct binder_alloc *alloc;
        uintptr_t page_addr;
        size_t index;
+       struct vm_area_struct *vma;
 
        alloc = page->alloc;
        if (!mutex_trylock(&alloc->mutex))
@@ -923,16 +924,22 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
 
        index = page - alloc->pages;
        page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE;
-       if (alloc->vma) {
+       vma = alloc->vma;
+       if (vma) {
                mm = get_task_mm(alloc->tsk);
                if (!mm)
                        goto err_get_task_mm_failed;
                if (!down_write_trylock(&mm->mmap_sem))
                        goto err_down_write_mmap_sem_failed;
+       }
+
+       list_lru_isolate(lru, item);
+       spin_unlock(lock);
 
+       if (vma) {
                trace_binder_unmap_user_start(alloc, index);
 
-               zap_page_range(alloc->vma,
+               zap_page_range(vma,
                               page_addr + alloc->user_buffer_offset,
                               PAGE_SIZE);
 
@@ -950,13 +957,12 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
 
        trace_binder_unmap_kernel_end(alloc, index);
 
-       list_lru_isolate(lru, item);
-
+       spin_lock(lock);
        mutex_unlock(&alloc->mutex);
-       return LRU_REMOVED;
+       return LRU_REMOVED_RETRY;
 
 err_down_write_mmap_sem_failed:
-       mmput(mm);
+       mmput_async(mm);
 err_get_task_mm_failed:
 err_page_already_freed:
        mutex_unlock(&alloc->mutex);
index cb9b0e9..9f78bb0 100644 (file)
@@ -621,8 +621,11 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev,
 static int ahci_pci_reset_controller(struct ata_host *host)
 {
        struct pci_dev *pdev = to_pci_dev(host->dev);
+       int rc;
 
-       ahci_reset_controller(host);
+       rc = ahci_reset_controller(host);
+       if (rc)
+               return rc;
 
        if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
                struct ahci_host_priv *hpriv = host->private_data;
index 8401c3b..b702c20 100644 (file)
@@ -492,6 +492,7 @@ static const struct ich_laptop ich_laptop[] = {
        { 0x27DF, 0x152D, 0x0778 },     /* ICH7 on unknown Intel */
        { 0x24CA, 0x1025, 0x0061 },     /* ICH4 on ACER Aspire 2023WLMi */
        { 0x24CA, 0x1025, 0x003d },     /* ICH4 on ACER TM290 */
+       { 0x24CA, 0x10CF, 0x11AB },     /* ICH4M on Fujitsu-Siemens Lifebook S6120 */
        { 0x266F, 0x1025, 0x0066 },     /* ICH6 on ACER Aspire 1694WLMi */
        { 0x2653, 0x1043, 0x82D8 },     /* ICH6M on Asus Eee 701 */
        { 0x27df, 0x104d, 0x900e },     /* ICH7 on Sony TZ-90 */
index 1945a8e..ee4c1ec 100644 (file)
@@ -3234,19 +3234,19 @@ static const struct ata_timing ata_timing[] = {
 };
 
 #define ENOUGH(v, unit)                (((v)-1)/(unit)+1)
-#define EZ(v, unit)            ((v)?ENOUGH(v, unit):0)
+#define EZ(v, unit)            ((v)?ENOUGH(((v) * 1000), unit):0)
 
 static void ata_timing_quantize(const struct ata_timing *t, struct ata_timing *q, int T, int UT)
 {
-       q->setup        = EZ(t->setup      * 1000,  T);
-       q->act8b        = EZ(t->act8b      * 1000,  T);
-       q->rec8b        = EZ(t->rec8b      * 1000,  T);
-       q->cyc8b        = EZ(t->cyc8b      * 1000,  T);
-       q->active       = EZ(t->active     * 1000,  T);
-       q->recover      = EZ(t->recover    * 1000,  T);
-       q->dmack_hold   = EZ(t->dmack_hold * 1000,  T);
-       q->cycle        = EZ(t->cycle      * 1000,  T);
-       q->udma         = EZ(t->udma       * 1000, UT);
+       q->setup        = EZ(t->setup,       T);
+       q->act8b        = EZ(t->act8b,       T);
+       q->rec8b        = EZ(t->rec8b,       T);
+       q->cyc8b        = EZ(t->cyc8b,       T);
+       q->active       = EZ(t->active,      T);
+       q->recover      = EZ(t->recover,     T);
+       q->dmack_hold   = EZ(t->dmack_hold,  T);
+       q->cycle        = EZ(t->cycle,       T);
+       q->udma         = EZ(t->udma,       UT);
 }
 
 void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
index cfeb049..642afd8 100644 (file)
@@ -647,18 +647,25 @@ static ssize_t charlcd_write(struct file *file, const char __user *buf,
 static int charlcd_open(struct inode *inode, struct file *file)
 {
        struct charlcd_priv *priv = to_priv(the_charlcd);
+       int ret;
 
+       ret = -EBUSY;
        if (!atomic_dec_and_test(&charlcd_available))
-               return -EBUSY;  /* open only once at a time */
+               goto fail;      /* open only once at a time */
 
+       ret = -EPERM;
        if (file->f_mode & FMODE_READ)  /* device is write-only */
-               return -EPERM;
+               goto fail;
 
        if (priv->must_clear) {
                charlcd_clear_display(&priv->lcd);
                priv->must_clear = false;
        }
        return nonseekable_open(inode, file);
+
+ fail:
+       atomic_inc(&charlcd_available);
+       return ret;
 }
 
 static int charlcd_release(struct inode *inode, struct file *file)
index df126dc..6911acd 100644 (file)
@@ -1105,14 +1105,21 @@ static ssize_t keypad_read(struct file *file,
 
 static int keypad_open(struct inode *inode, struct file *file)
 {
+       int ret;
+
+       ret = -EBUSY;
        if (!atomic_dec_and_test(&keypad_available))
-               return -EBUSY;  /* open only once at a time */
+               goto fail;      /* open only once at a time */
 
+       ret = -EPERM;
        if (file->f_mode & FMODE_WRITE) /* device is read-only */
-               return -EPERM;
+               goto fail;
 
        keypad_buflen = 0;      /* flush the buffer on opening */
        return 0;
+ fail:
+       atomic_inc(&keypad_available);
+       return ret;
 }
 
 static int keypad_release(struct inode *inode, struct file *file)
index 41be9ff..6df7d66 100644 (file)
@@ -166,11 +166,11 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
 }
 
 #ifdef CONFIG_CPU_FREQ
-static cpumask_var_t cpus_to_visit;
-static void parsing_done_workfn(struct work_struct *work);
-static DECLARE_WORK(parsing_done_work, parsing_done_workfn);
+static cpumask_var_t cpus_to_visit __initdata;
+static void __init parsing_done_workfn(struct work_struct *work);
+static __initdata DECLARE_WORK(parsing_done_work, parsing_done_workfn);
 
-static int
+static int __init
 init_cpu_capacity_callback(struct notifier_block *nb,
                           unsigned long val,
                           void *data)
@@ -206,7 +206,7 @@ init_cpu_capacity_callback(struct notifier_block *nb,
        return 0;
 }
 
-static struct notifier_block init_cpu_capacity_notifier = {
+static struct notifier_block init_cpu_capacity_notifier __initdata = {
        .notifier_call = init_cpu_capacity_callback,
 };
 
@@ -232,7 +232,7 @@ static int __init register_cpufreq_notifier(void)
 }
 core_initcall(register_cpufreq_notifier);
 
-static void parsing_done_workfn(struct work_struct *work)
+static void __init parsing_done_workfn(struct work_struct *work)
 {
        cpufreq_unregister_notifier(&init_cpu_capacity_notifier,
                                         CPUFREQ_POLICY_NOTIFIER);
index d1bd992..9045c5f 100644 (file)
@@ -868,7 +868,8 @@ static ssize_t driver_override_store(struct device *dev,
        struct platform_device *pdev = to_platform_device(dev);
        char *driver_override, *old, *cp;
 
-       if (count > PATH_MAX)
+       /* We need to keep extra room for a newline */
+       if (count >= (PAGE_SIZE - 1))
                return -EINVAL;
 
        driver_override = kstrndup(buf, count, GFP_KERNEL);
index 4a438b8..2dfe99b 100644 (file)
@@ -17,7 +17,7 @@ if BLK_DEV
 
 config BLK_DEV_NULL_BLK
        tristate "Null test block driver"
-       depends on CONFIGFS_FS
+       select CONFIGFS_FS
 
 config BLK_DEV_FD
        tristate "Normal floppy disk support"
index 3684e21..883dfeb 100644 (file)
@@ -820,9 +820,13 @@ static blk_status_t nbd_queue_rq(struct blk_mq_hw_ctx *hctx,
         * appropriate.
         */
        ret = nbd_handle_cmd(cmd, hctx->queue_num);
+       if (ret < 0)
+               ret = BLK_STS_IOERR;
+       else if (!ret)
+               ret = BLK_STS_OK;
        complete(&cmd->send_complete);
 
-       return ret < 0 ? BLK_STS_IOERR : BLK_STS_OK;
+       return ret;
 }
 
 static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg,
index 2981c27..f149d3e 100644 (file)
@@ -766,27 +766,6 @@ static void zram_slot_unlock(struct zram *zram, u32 index)
        bit_spin_unlock(ZRAM_ACCESS, &zram->table[index].value);
 }
 
-static bool zram_same_page_read(struct zram *zram, u32 index,
-                               struct page *page,
-                               unsigned int offset, unsigned int len)
-{
-       zram_slot_lock(zram, index);
-       if (unlikely(!zram_get_handle(zram, index) ||
-                       zram_test_flag(zram, index, ZRAM_SAME))) {
-               void *mem;
-
-               zram_slot_unlock(zram, index);
-               mem = kmap_atomic(page);
-               zram_fill_page(mem + offset, len,
-                                       zram_get_element(zram, index));
-               kunmap_atomic(mem);
-               return true;
-       }
-       zram_slot_unlock(zram, index);
-
-       return false;
-}
-
 static void zram_meta_free(struct zram *zram, u64 disksize)
 {
        size_t num_pages = disksize >> PAGE_SHIFT;
@@ -884,11 +863,20 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index,
                zram_slot_unlock(zram, index);
        }
 
-       if (zram_same_page_read(zram, index, page, 0, PAGE_SIZE))
-               return 0;
-
        zram_slot_lock(zram, index);
        handle = zram_get_handle(zram, index);
+       if (!handle || zram_test_flag(zram, index, ZRAM_SAME)) {
+               unsigned long value;
+               void *mem;
+
+               value = handle ? zram_get_element(zram, index) : 0;
+               mem = kmap_atomic(page);
+               zram_fill_page(mem, PAGE_SIZE, value);
+               kunmap_atomic(mem);
+               zram_slot_unlock(zram, index);
+               return 0;
+       }
+
        size = zram_get_obj_size(zram, index);
 
        src = zs_map_object(zram->mem_pool, handle, ZS_MM_RO);
index c834f5a..4c10456 100644 (file)
@@ -105,6 +105,7 @@ err:
 
        return  ret;
 }
+EXPORT_SYMBOL_GPL(clk_bulk_prepare);
 
 #endif /* CONFIG_HAVE_CLK_PREPARE */
 
index 62d7854..5970a50 100644 (file)
@@ -315,13 +315,13 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
                        RK2928_CLKGATE_CON(10), 8, GFLAGS),
 
        GATE(SCLK_PVTM_CORE, "clk_pvtm_core", "xin24m", 0,
-                       RK2928_CLKGATE_CON(10), 8, GFLAGS),
+                       RK2928_CLKGATE_CON(10), 0, GFLAGS),
        GATE(SCLK_PVTM_GPU, "clk_pvtm_gpu", "xin24m", 0,
-                       RK2928_CLKGATE_CON(10), 8, GFLAGS),
+                       RK2928_CLKGATE_CON(10), 1, GFLAGS),
        GATE(SCLK_PVTM_FUNC, "clk_pvtm_func", "xin24m", 0,
-                       RK2928_CLKGATE_CON(10), 8, GFLAGS),
+                       RK2928_CLKGATE_CON(10), 2, GFLAGS),
        GATE(SCLK_MIPI_24M, "clk_mipi_24m", "xin24m", CLK_IGNORE_UNUSED,
-                       RK2928_CLKGATE_CON(10), 8, GFLAGS),
+                       RK2928_CLKGATE_CON(2), 15, GFLAGS),
 
        COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
                        RK2928_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 6, DFLAGS,
@@ -541,7 +541,7 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
        GATE(0, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS),
        GATE(0, "pclk_mipiphy", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 0, GFLAGS),
 
-       GATE(0, "pclk_pmu", "pclk_pmu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 2, GFLAGS),
+       GATE(0, "pclk_pmu", "pclk_pmu_pre", 0, RK2928_CLKGATE_CON(9), 2, GFLAGS),
        GATE(0, "pclk_pmu_niu", "pclk_pmu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 3, GFLAGS),
 
        /* PD_MMC */
@@ -577,6 +577,8 @@ static const char *const rk3128_critical_clocks[] __initconst = {
        "aclk_peri",
        "hclk_peri",
        "pclk_peri",
+       "pclk_pmu",
+       "sclk_timer5",
 };
 
 static struct rockchip_clk_provider *__init rk3128_common_clk_init(struct device_node *np)
index e40b775..d8d3cb6 100644 (file)
@@ -294,6 +294,18 @@ static const struct samsung_clk_reg_dump src_mask_suspend_e4210[] = {
 #define PLL_ENABLED    (1 << 31)
 #define PLL_LOCKED     (1 << 29)
 
+static void exynos4_clk_enable_pll(u32 reg)
+{
+       u32 pll_con = readl(reg_base + reg);
+       pll_con |= PLL_ENABLED;
+       writel(pll_con, reg_base + reg);
+
+       while (!(pll_con & PLL_LOCKED)) {
+               cpu_relax();
+               pll_con = readl(reg_base + reg);
+       }
+}
+
 static void exynos4_clk_wait_for_pll(u32 reg)
 {
        u32 pll_con;
@@ -315,6 +327,9 @@ static int exynos4_clk_suspend(void)
        samsung_clk_save(reg_base, exynos4_save_pll,
                                ARRAY_SIZE(exynos4_clk_pll_regs));
 
+       exynos4_clk_enable_pll(EPLL_CON0);
+       exynos4_clk_enable_pll(VPLL_CON0);
+
        if (exynos4_soc == EXYNOS4210) {
                samsung_clk_save(reg_base, exynos4_save_soc,
                                        ARRAY_SIZE(exynos4210_clk_save));
index 08629ee..00e73d2 100644 (file)
@@ -361,12 +361,12 @@ static const struct fpga_manager_ops altera_cvp_ops = {
        .write_complete = altera_cvp_write_complete,
 };
 
-static ssize_t show_chkcfg(struct device_driver *dev, char *buf)
+static ssize_t chkcfg_show(struct device_driver *dev, char *buf)
 {
        return snprintf(buf, 3, "%d\n", altera_cvp_chkcfg);
 }
 
-static ssize_t store_chkcfg(struct device_driver *drv, const char *buf,
+static ssize_t chkcfg_store(struct device_driver *drv, const char *buf,
                            size_t count)
 {
        int ret;
@@ -378,7 +378,7 @@ static ssize_t store_chkcfg(struct device_driver *drv, const char *buf,
        return count;
 }
 
-static DRIVER_ATTR(chkcfg, 0600, show_chkcfg, store_chkcfg);
+static DRIVER_ATTR_RW(chkcfg);
 
 static int altera_cvp_probe(struct pci_dev *pdev,
                            const struct pci_device_id *dev_id);
index d805b6e..27743be 100644 (file)
@@ -606,11 +606,6 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder,
                         connector->encoder->base.id,
                         connector->encoder->name);
 
-       /* ELD Conn_Type */
-       connector->eld[5] &= ~(3 << 2);
-       if (intel_crtc_has_dp_encoder(crtc_state))
-               connector->eld[5] |= (1 << 2);
-
        connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
 
        if (dev_priv->display.audio_codec_enable)
index 183e87e..00c6aee 100644 (file)
@@ -1163,6 +1163,13 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
        is_hdmi = is_dvi && (child->common.device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0;
        is_edp = is_dp && (child->common.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR);
 
+       if (port == PORT_A && is_dvi) {
+               DRM_DEBUG_KMS("VBT claims port A supports DVI%s, ignoring\n",
+                             is_hdmi ? "/HDMI" : "");
+               is_dvi = false;
+               is_hdmi = false;
+       }
+
        info->supports_dvi = is_dvi;
        info->supports_hdmi = is_hdmi;
        info->supports_dp = is_dp;
index 965988f..92c1f8e 100644 (file)
@@ -216,7 +216,7 @@ static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv)
 
        mask = DC_STATE_DEBUG_MASK_MEMORY_UP;
 
-       if (IS_BROXTON(dev_priv))
+       if (IS_GEN9_LP(dev_priv))
                mask |= DC_STATE_DEBUG_MASK_CORES;
 
        /* The below bit doesn't need to be cleared ever afterwards */
index 4b4fd1f..476681d 100644 (file)
@@ -1655,7 +1655,8 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
 out:
        if (ret && IS_GEN9_LP(dev_priv)) {
                tmp = I915_READ(BXT_PHY_CTL(port));
-               if ((tmp & (BXT_PHY_LANE_POWERDOWN_ACK |
+               if ((tmp & (BXT_PHY_CMNLANE_POWERDOWN_ACK |
+                           BXT_PHY_LANE_POWERDOWN_ACK |
                            BXT_PHY_LANE_ENABLED)) != BXT_PHY_LANE_ENABLED)
                        DRM_ERROR("Port %c enabled but PHY powered down? "
                                  "(PHY_CTL %08x)\n", port_name(port), tmp);
index 00cd17c..64f7b51 100644 (file)
@@ -12359,7 +12359,6 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
        struct drm_crtc_state *old_crtc_state, *new_crtc_state;
        struct drm_crtc *crtc;
        struct intel_crtc_state *intel_cstate;
-       bool hw_check = intel_state->modeset;
        u64 put_domains[I915_MAX_PIPES] = {};
        unsigned crtc_vblank_mask = 0;
        int i;
@@ -12376,7 +12375,6 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 
                if (needs_modeset(new_crtc_state) ||
                    to_intel_crtc_state(new_crtc_state)->update_pipe) {
-                       hw_check = true;
 
                        put_domains[to_intel_crtc(crtc)->pipe] =
                                modeset_get_crtc_power_domains(crtc,
index 09b6709..de38d01 100644 (file)
@@ -208,12 +208,6 @@ static const struct bxt_ddi_phy_info glk_ddi_phy_info[] = {
        },
 };
 
-static u32 bxt_phy_port_mask(const struct bxt_ddi_phy_info *phy_info)
-{
-       return (phy_info->dual_channel * BIT(phy_info->channel[DPIO_CH1].port)) |
-               BIT(phy_info->channel[DPIO_CH0].port);
-}
-
 static const struct bxt_ddi_phy_info *
 bxt_get_phy_list(struct drm_i915_private *dev_priv, int *count)
 {
@@ -313,7 +307,6 @@ bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
                            enum dpio_phy phy)
 {
        const struct bxt_ddi_phy_info *phy_info;
-       enum port port;
 
        phy_info = bxt_get_phy_info(dev_priv, phy);
 
@@ -335,19 +328,6 @@ bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
                return false;
        }
 
-       for_each_port_masked(port, bxt_phy_port_mask(phy_info)) {
-               u32 tmp = I915_READ(BXT_PHY_CTL(port));
-
-               if (tmp & BXT_PHY_CMNLANE_POWERDOWN_ACK) {
-                       DRM_DEBUG_DRIVER("DDI PHY %d powered, but common lane "
-                                        "for port %c powered down "
-                                        "(PHY_CTL %08x)\n",
-                                        phy, port_name(port), tmp);
-
-                       return false;
-               }
-       }
-
        return true;
 }
 
index 951e834..28a778b 100644 (file)
 #include "intel_drv.h"
 #include "i915_drv.h"
 
+static void intel_connector_update_eld_conn_type(struct drm_connector *connector)
+{
+       u8 conn_type;
+
+       if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+           connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+               conn_type = DRM_ELD_CONN_TYPE_DP;
+       } else {
+               conn_type = DRM_ELD_CONN_TYPE_HDMI;
+       }
+
+       connector->eld[DRM_ELD_SAD_COUNT_CONN_TYPE] &= ~DRM_ELD_CONN_TYPE_MASK;
+       connector->eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= conn_type;
+}
+
 /**
  * intel_connector_update_modes - update connector from edid
  * @connector: DRM connector device to use
@@ -44,6 +59,8 @@ int intel_connector_update_modes(struct drm_connector *connector,
        ret = drm_add_edid_modes(connector, edid);
        drm_edid_to_eld(connector, edid);
 
+       intel_connector_update_eld_conn_type(connector);
+
        return ret;
 }
 
index b66d8e1..b3a087c 100644 (file)
@@ -2782,6 +2782,9 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume
 
        /* 6. Enable DBUF */
        gen9_dbuf_enable(dev_priv);
+
+       if (resume && dev_priv->csr.dmc_payload)
+               intel_csr_load_program(dev_priv);
 }
 
 #undef CNL_PROCMON_IDX
index 9ea6cd5..3cf1a69 100644 (file)
@@ -302,26 +302,29 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master,
        hdmi->mod_clk = devm_clk_get(dev, "mod");
        if (IS_ERR(hdmi->mod_clk)) {
                dev_err(dev, "Couldn't get the HDMI mod clock\n");
-               return PTR_ERR(hdmi->mod_clk);
+               ret = PTR_ERR(hdmi->mod_clk);
+               goto err_disable_bus_clk;
        }
        clk_prepare_enable(hdmi->mod_clk);
 
        hdmi->pll0_clk = devm_clk_get(dev, "pll-0");
        if (IS_ERR(hdmi->pll0_clk)) {
                dev_err(dev, "Couldn't get the HDMI PLL 0 clock\n");
-               return PTR_ERR(hdmi->pll0_clk);
+               ret = PTR_ERR(hdmi->pll0_clk);
+               goto err_disable_mod_clk;
        }
 
        hdmi->pll1_clk = devm_clk_get(dev, "pll-1");
        if (IS_ERR(hdmi->pll1_clk)) {
                dev_err(dev, "Couldn't get the HDMI PLL 1 clock\n");
-               return PTR_ERR(hdmi->pll1_clk);
+               ret = PTR_ERR(hdmi->pll1_clk);
+               goto err_disable_mod_clk;
        }
 
        ret = sun4i_tmds_create(hdmi);
        if (ret) {
                dev_err(dev, "Couldn't create the TMDS clock\n");
-               return ret;
+               goto err_disable_mod_clk;
        }
 
        writel(SUN4I_HDMI_CTRL_ENABLE, hdmi->base + SUN4I_HDMI_CTRL_REG);
@@ -362,7 +365,7 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master,
        ret = sun4i_hdmi_i2c_create(dev, hdmi);
        if (ret) {
                dev_err(dev, "Couldn't create the HDMI I2C adapter\n");
-               return ret;
+               goto err_disable_mod_clk;
        }
 
        drm_encoder_helper_add(&hdmi->encoder,
@@ -422,6 +425,10 @@ err_cleanup_connector:
        drm_encoder_cleanup(&hdmi->encoder);
 err_del_i2c_adapter:
        i2c_del_adapter(hdmi->i2c);
+err_disable_mod_clk:
+       clk_disable_unprepare(hdmi->mod_clk);
+err_disable_bus_clk:
+       clk_disable_unprepare(hdmi->bus_clk);
        return ret;
 }
 
@@ -434,6 +441,8 @@ static void sun4i_hdmi_unbind(struct device *dev, struct device *master,
        drm_connector_cleanup(&hdmi->connector);
        drm_encoder_cleanup(&hdmi->encoder);
        i2c_del_adapter(hdmi->i2c);
+       clk_disable_unprepare(hdmi->mod_clk);
+       clk_disable_unprepare(hdmi->bus_clk);
 }
 
 static const struct component_ops sun4i_hdmi_ops = {
index b397a14..a989191 100644 (file)
 #define USB_VENDOR_ID_IDEACOM          0x1cb6
 #define USB_DEVICE_ID_IDEACOM_IDC6650  0x6650
 #define USB_DEVICE_ID_IDEACOM_IDC6651  0x6651
+#define USB_DEVICE_ID_IDEACOM_IDC6680  0x6680
 
 #define USB_VENDOR_ID_ILITEK           0x222a
 #define USB_DEVICE_ID_ILITEK_MULTITOUCH        0x0001
 #define USB_DEVICE_ID_LENOVO_CBTKBD    0x6048
 #define USB_DEVICE_ID_LENOVO_TPPRODOCK 0x6067
 #define USB_DEVICE_ID_LENOVO_X1_COVER  0x6085
+#define USB_DEVICE_ID_LENOVO_X1_TAB    0x60a3
 
 #define USB_VENDOR_ID_LG               0x1fd2
 #define USB_DEVICE_ID_LG_MULTITOUCH    0x0064
index 440b999..9e8c4d2 100644 (file)
@@ -930,6 +930,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
            field->application != HID_DG_PEN &&
            field->application != HID_DG_TOUCHPAD &&
            field->application != HID_GD_KEYBOARD &&
+           field->application != HID_GD_SYSTEM_CONTROL &&
            field->application != HID_CP_CONSUMER_CONTROL &&
            field->application != HID_GD_WIRELESS_RADIO_CTLS &&
            !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
@@ -1419,6 +1420,12 @@ static const struct hid_device_id mt_devices[] = {
                        USB_VENDOR_ID_ALPS_JP,
                        HID_DEVICE_ID_ALPS_U1_DUAL_3BTN_PTP) },
 
+       /* Lenovo X1 TAB Gen 2 */
+       { .driver_data = MT_CLS_WIN_8_DUAL,
+               HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8,
+                          USB_VENDOR_ID_LENOVO,
+                          USB_DEVICE_ID_LENOVO_X1_TAB) },
+
        /* Anton devices */
        { .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
                MT_USB_DEVICE(USB_VENDOR_ID_ANTON,
index 5b40c26..ef241d6 100644 (file)
@@ -436,17 +436,24 @@ static int rmi_post_resume(struct hid_device *hdev)
        if (!(data->device_flags & RMI_DEVICE))
                return 0;
 
-       ret = rmi_reset_attn_mode(hdev);
+       /* Make sure the HID device is ready to receive events */
+       ret = hid_hw_open(hdev);
        if (ret)
                return ret;
 
+       ret = rmi_reset_attn_mode(hdev);
+       if (ret)
+               goto out;
+
        ret = rmi_driver_resume(rmi_dev, false);
        if (ret) {
                hid_warn(hdev, "Failed to resume device: %d\n", ret);
-               return ret;
+               goto out;
        }
 
-       return 0;
+out:
+       hid_hw_close(hdev);
+       return ret;
 }
 #endif /* CONFIG_PM */
 
index ec53045..5fbe0f8 100644 (file)
@@ -337,8 +337,8 @@ static void drop_ref(struct hidraw *hidraw, int exists_bit)
                        kfree(hidraw);
                } else {
                        /* close device for last reader */
-                       hid_hw_power(hidraw->hid, PM_HINT_NORMAL);
                        hid_hw_close(hidraw->hid);
+                       hid_hw_power(hidraw->hid, PM_HINT_NORMAL);
                }
        }
 }
index 7739614..9145c21 100644 (file)
@@ -543,7 +543,8 @@ static int i2c_hid_alloc_buffers(struct i2c_hid *ihid, size_t report_size)
 {
        /* the worst case is computed from the set_report command with a
         * reportID > 15 and the maximum report length */
-       int args_len = sizeof(__u8) + /* optional ReportID byte */
+       int args_len = sizeof(__u8) + /* ReportID */
+                      sizeof(__u8) + /* optional ReportID byte */
                       sizeof(__u16) + /* data register */
                       sizeof(__u16) + /* size of the report */
                       report_size; /* report */
index a83fa76..f489a5c 100644 (file)
@@ -99,6 +99,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS, HID_QUIRK_NOGET },
index e82a696..906e654 100644 (file)
@@ -668,8 +668,10 @@ static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev)
 
        /* Try to find an already-probed interface from the same device */
        list_for_each_entry(data, &wacom_udev_list, list) {
-               if (compare_device_paths(hdev, data->dev, '/'))
+               if (compare_device_paths(hdev, data->dev, '/')) {
+                       kref_get(&data->kref);
                        return data;
+               }
        }
 
        /* Fallback to finding devices that appear to be "siblings" */
@@ -766,6 +768,9 @@ static int wacom_led_control(struct wacom *wacom)
        if (!wacom->led.groups)
                return -ENOTSUPP;
 
+       if (wacom->wacom_wac.features.type == REMOTE)
+               return -ENOTSUPP;
+
        if (wacom->wacom_wac.pid) { /* wireless connected */
                report_id = WAC_CMD_WL_LED_CONTROL;
                buf_size = 13;
index bb17d7b..aa692e2 100644 (file)
@@ -567,8 +567,8 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
                                keys = data[9] & 0x07;
                        }
                } else {
-                       buttons = ((data[6] & 0x10) << 10) |
-                                 ((data[5] & 0x10) << 9)  |
+                       buttons = ((data[6] & 0x10) << 5)  |
+                                 ((data[5] & 0x10) << 4)  |
                                  ((data[6] & 0x0F) << 4)  |
                                  (data[5] & 0x0F);
                }
@@ -1227,11 +1227,17 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom)
                        continue;
 
                if (range) {
+                       /* Fix rotation alignment: userspace expects zero at left */
+                       int16_t rotation = (int16_t)get_unaligned_le16(&frame[9]);
+                       rotation += 1800/4;
+                       if (rotation > 899)
+                               rotation -= 1800;
+
                        input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1]));
                        input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3]));
-                       input_report_abs(pen_input, ABS_TILT_X, frame[7]);
-                       input_report_abs(pen_input, ABS_TILT_Y, frame[8]);
-                       input_report_abs(pen_input, ABS_Z, get_unaligned_le16(&frame[9]));
+                       input_report_abs(pen_input, ABS_TILT_X, (char)frame[7]);
+                       input_report_abs(pen_input, ABS_TILT_Y, (char)frame[8]);
+                       input_report_abs(pen_input, ABS_Z, rotation);
                        input_report_abs(pen_input, ABS_WHEEL, get_unaligned_le16(&frame[11]));
                }
                input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5]));
@@ -1319,12 +1325,19 @@ static void wacom_intuos_pro2_bt_pad(struct wacom_wac *wacom)
        unsigned char *data = wacom->data;
 
        int buttons = (data[282] << 1) | ((data[281] >> 6) & 0x01);
-       int ring = data[285];
-       int prox = buttons | (ring & 0x80);
+       int ring = data[285] & 0x7F;
+       bool ringstatus = data[285] & 0x80;
+       bool prox = buttons || ringstatus;
+
+       /* Fix touchring data: userspace expects 0 at left and increasing clockwise */
+       ring = 71 - ring;
+       ring += 3*72/16;
+       if (ring > 71)
+               ring -= 72;
 
        wacom_report_numbered_buttons(pad_input, 9, buttons);
 
-       input_report_abs(pad_input, ABS_WHEEL, (ring & 0x80) ? (ring & 0x7f) : 0);
+       input_report_abs(pad_input, ABS_WHEEL, ringstatus ? ring : 0);
 
        input_report_key(pad_input, wacom->tool[1], prox ? 1 : 0);
        input_report_abs(pad_input, ABS_MISC, prox ? PAD_DEVICE_ID : 0);
@@ -1616,6 +1629,20 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
        return 0;
 }
 
+static int wacom_offset_rotation(struct input_dev *input, struct hid_usage *usage,
+                                int value, int num, int denom)
+{
+       struct input_absinfo *abs = &input->absinfo[usage->code];
+       int range = (abs->maximum - abs->minimum + 1);
+
+       value += num*range/denom;
+       if (value > abs->maximum)
+               value -= range;
+       else if (value < abs->minimum)
+               value += range;
+       return value;
+}
+
 int wacom_equivalent_usage(int usage)
 {
        if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMDIGITIZER) {
@@ -1898,6 +1925,7 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
        unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
        int i;
        bool is_touch_on = value;
+       bool do_report = false;
 
        /*
         * Avoid reporting this event and setting inrange_state if this usage
@@ -1912,6 +1940,29 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
        }
 
        switch (equivalent_usage) {
+       case WACOM_HID_WD_TOUCHRING:
+               /*
+                * Userspace expects touchrings to increase in value with
+                * clockwise gestures and have their zero point at the
+                * tablet's left. HID events "should" be clockwise-
+                * increasing and zero at top, though the MobileStudio
+                * Pro and 2nd-gen Intuos Pro don't do this...
+                */
+               if (hdev->vendor == 0x56a &&
+                   (hdev->product == 0x34d || hdev->product == 0x34e ||  /* MobileStudio Pro */
+                    hdev->product == 0x357 || hdev->product == 0x358)) { /* Intuos Pro 2 */
+                       value = (field->logical_maximum - value);
+
+                       if (hdev->product == 0x357 || hdev->product == 0x358)
+                               value = wacom_offset_rotation(input, usage, value, 3, 16);
+                       else if (hdev->product == 0x34d || hdev->product == 0x34e)
+                               value = wacom_offset_rotation(input, usage, value, 1, 2);
+               }
+               else {
+                       value = wacom_offset_rotation(input, usage, value, 1, 4);
+               }
+               do_report = true;
+               break;
        case WACOM_HID_WD_TOUCHRINGSTATUS:
                if (!value)
                        input_event(input, usage->type, usage->code, 0);
@@ -1945,10 +1996,14 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
                                         value, i);
                 /* fall through*/
        default:
+               do_report = true;
+               break;
+       }
+
+       if (do_report) {
                input_event(input, usage->type, usage->code, value);
                if (value)
                        wacom_wac->hid_data.pad_input_event_flag = true;
-               break;
        }
 }
 
@@ -2086,22 +2141,34 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
                wacom_wac->hid_data.tipswitch |= value;
                return;
        case HID_DG_TOOLSERIALNUMBER:
-               wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL);
-               wacom_wac->serial[0] |= (__u32)value;
+               if (value) {
+                       wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL);
+                       wacom_wac->serial[0] |= (__u32)value;
+               }
                return;
+       case HID_DG_TWIST:
+               /*
+                * Userspace expects pen twist to have its zero point when
+                * the buttons/finger is on the tablet's left. HID values
+                * are zero when buttons are toward the top.
+                */
+               value = wacom_offset_rotation(input, usage, value, 1, 4);
+               break;
        case WACOM_HID_WD_SENSE:
                wacom_wac->hid_data.sense_state = value;
                return;
        case WACOM_HID_WD_SERIALHI:
-               wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF);
-               wacom_wac->serial[0] |= ((__u64)value) << 32;
-               /*
-                * Non-USI EMR devices may contain additional tool type
-                * information here. See WACOM_HID_WD_TOOLTYPE case for
-                * more details.
-                */
-               if (value >> 20 == 1) {
-                       wacom_wac->id[0] |= value & 0xFFFFF;
+               if (value) {
+                       wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF);
+                       wacom_wac->serial[0] |= ((__u64)value) << 32;
+                       /*
+                        * Non-USI EMR devices may contain additional tool type
+                        * information here. See WACOM_HID_WD_TOOLTYPE case for
+                        * more details.
+                        */
+                       if (value >> 20 == 1) {
+                               wacom_wac->id[0] |= value & 0xFFFFF;
+                       }
                }
                return;
        case WACOM_HID_WD_TOOLTYPE:
@@ -2205,7 +2272,7 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
                input_report_key(input, wacom_wac->tool[0], prox);
                if (wacom_wac->serial[0]) {
                        input_event(input, EV_MSC, MSC_SERIAL, wacom_wac->serial[0]);
-                       input_report_abs(input, ABS_MISC, id);
+                       input_report_abs(input, ABS_MISC, prox ? id : 0);
                }
 
                wacom_wac->hid_data.tipswitch = false;
@@ -2216,6 +2283,7 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
        if (!prox) {
                wacom_wac->tool[0] = 0;
                wacom_wac->id[0] = 0;
+               wacom_wac->serial[0] = 0;
        }
 }
 
index 060df71..bcbb031 100644 (file)
@@ -936,14 +936,10 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
 
 void vmbus_hvsock_device_unregister(struct vmbus_channel *channel)
 {
-       mutex_lock(&vmbus_connection.channel_mutex);
-
        BUG_ON(!is_hvsock_channel(channel));
 
        channel->rescind = true;
        vmbus_device_unregister(channel->device_obj);
-
-       mutex_unlock(&vmbus_connection.channel_mutex);
 }
 EXPORT_SYMBOL_GPL(vmbus_hvsock_device_unregister);
 
index daa75bd..2364281 100644 (file)
@@ -170,6 +170,10 @@ static void fcopy_send_data(struct work_struct *dummy)
                out_src = smsg_out;
                break;
 
+       case WRITE_TO_FILE:
+               out_src = fcopy_transaction.fcopy_msg;
+               out_len = sizeof(struct hv_do_fcopy);
+               break;
        default:
                out_src = fcopy_transaction.fcopy_msg;
                out_len = fcopy_transaction.recv_len;
index 9c0dbb8..e1be610 100644 (file)
@@ -630,7 +630,7 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
                         sizeof(struct slimpro_resp_msg) * ASYNC_MSG_FIFO_SIZE,
                         GFP_KERNEL);
        if (rc)
-               goto out_mbox_free;
+               return -ENOMEM;
 
        INIT_WORK(&ctx->workq, xgene_hwmon_evt_work);
 
@@ -646,7 +646,8 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
                if (IS_ERR(ctx->mbox_chan)) {
                        dev_err(&pdev->dev,
                                "SLIMpro mailbox channel request failed\n");
-                       return -ENODEV;
+                       rc = -ENODEV;
+                       goto out_mbox_free;
                }
        } else {
                struct acpi_pcct_hw_reduced *cppc_ss;
@@ -654,7 +655,8 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
                if (device_property_read_u32(&pdev->dev, "pcc-channel",
                                             &ctx->mbox_idx)) {
                        dev_err(&pdev->dev, "no pcc-channel property\n");
-                       return -ENODEV;
+                       rc = -ENODEV;
+                       goto out_mbox_free;
                }
 
                cl->rx_callback = xgene_hwmon_pcc_rx_cb;
@@ -662,7 +664,8 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
                if (IS_ERR(ctx->mbox_chan)) {
                        dev_err(&pdev->dev,
                                "PPC channel request failed\n");
-                       return -ENODEV;
+                       rc = -ENODEV;
+                       goto out_mbox_free;
                }
 
                /*
@@ -675,13 +678,13 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
                if (!cppc_ss) {
                        dev_err(&pdev->dev, "PPC subspace not found\n");
                        rc = -ENODEV;
-                       goto out_mbox_free;
+                       goto out;
                }
 
                if (!ctx->mbox_chan->mbox->txdone_irq) {
                        dev_err(&pdev->dev, "PCC IRQ not supported\n");
                        rc = -ENODEV;
-                       goto out_mbox_free;
+                       goto out;
                }
 
                /*
@@ -696,14 +699,14 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
                } else {
                        dev_err(&pdev->dev, "Failed to get PCC comm region\n");
                        rc = -ENODEV;
-                       goto out_mbox_free;
+                       goto out;
                }
 
                if (!ctx->pcc_comm_addr) {
                        dev_err(&pdev->dev,
                                "Failed to ioremap PCC comm region\n");
                        rc = -ENOMEM;
-                       goto out_mbox_free;
+                       goto out;
                }
 
                /*
index bc9cebc..c2a2ce8 100644 (file)
@@ -144,6 +144,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
                .driver_data = (kernel_ulong_t)0,
        },
        {
+               /* Lewisburg PCH */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa1a6),
+               .driver_data = (kernel_ulong_t)0,
+       },
+       {
                /* Gemini Lake */
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x318e),
                .driver_data = (kernel_ulong_t)&intel_th_2x,
@@ -158,6 +163,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9da6),
                .driver_data = (kernel_ulong_t)&intel_th_2x,
        },
+       {
+               /* Cedar Fork PCH */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x18e1),
+               .driver_data = (kernel_ulong_t)&intel_th_2x,
+       },
        { 0 },
 };
 
index 9414900..f129869 100644 (file)
@@ -1119,7 +1119,7 @@ void stm_source_unregister_device(struct stm_source_data *data)
 
        stm_source_link_drop(src);
 
-       device_destroy(&stm_source_class, src->dev.devt);
+       device_unregister(&src->dev);
 }
 EXPORT_SYMBOL_GPL(stm_source_unregister_device);
 
index 84fb35f..eb1d91b 100644 (file)
@@ -1459,6 +1459,6 @@ static struct platform_driver img_scb_i2c_driver = {
 };
 module_platform_driver(img_scb_i2c_driver);
 
-MODULE_AUTHOR("James Hogan <james.hogan@imgtec.com>");
+MODULE_AUTHOR("James Hogan <jhogan@kernel.org>");
 MODULE_DESCRIPTION("IMG host I2C driver");
 MODULE_LICENSE("GPL v2");
index 01b2adf..eaf39e5 100644 (file)
@@ -1451,6 +1451,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d,
                if (hwif_init(hwif) == 0) {
                        printk(KERN_INFO "%s: failed to initialize IDE "
                                         "interface\n", hwif->name);
+                       device_unregister(hwif->portdev);
                        device_unregister(&hwif->gendev);
                        ide_disable_port(hwif);
                        continue;
index 86aa88a..acf8748 100644 (file)
@@ -56,6 +56,7 @@ static int __init ide_scan_pcidev(struct pci_dev *dev)
 {
        struct list_head *l;
        struct pci_driver *d;
+       int ret;
 
        list_for_each(l, &ide_pci_drivers) {
                d = list_entry(l, struct pci_driver, node);
@@ -63,10 +64,14 @@ static int __init ide_scan_pcidev(struct pci_dev *dev)
                        const struct pci_device_id *id =
                                pci_match_id(d->id_table, dev);
 
-                       if (id != NULL && d->probe(dev, id) >= 0) {
-                               dev->driver = d;
-                               pci_dev_get(dev);
-                               return 1;
+                       if (id != NULL) {
+                               pci_assign_irq(dev);
+                               ret = d->probe(dev, id);
+                               if (ret >= 0) {
+                                       dev->driver = d;
+                                       pci_dev_get(dev);
+                                       return 1;
+                               }
                        }
                }
        }
index 112d2fe..fdc8e81 100644 (file)
@@ -179,6 +179,7 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
 /**
  *     ide_pci_enable  -       do PCI enables
  *     @dev: PCI device
+ *     @bars: PCI BARs mask
  *     @d: IDE port info
  *
  *     Enable the IDE PCI device. We attempt to enable the device in full
@@ -189,9 +190,10 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
  *     Returns zero on success or an error code
  */
 
-static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
+static int ide_pci_enable(struct pci_dev *dev, int bars,
+                         const struct ide_port_info *d)
 {
-       int ret, bars;
+       int ret;
 
        if (pci_enable_device(dev)) {
                ret = pci_enable_device_io(dev);
@@ -216,18 +218,6 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
                goto out;
        }
 
-       if (d->host_flags & IDE_HFLAG_SINGLE)
-               bars = (1 << 2) - 1;
-       else
-               bars = (1 << 4) - 1;
-
-       if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) {
-               if (d->host_flags & IDE_HFLAG_CS5520)
-                       bars |= (1 << 2);
-               else
-                       bars |= (1 << 4);
-       }
-
        ret = pci_request_selected_regions(dev, bars, d->name);
        if (ret < 0)
                printk(KERN_ERR "%s %s: can't reserve resources\n",
@@ -403,6 +393,7 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
 /**
  *     ide_setup_pci_controller        -       set up IDE PCI
  *     @dev: PCI device
+ *     @bars: PCI BARs mask
  *     @d: IDE port info
  *     @noisy: verbose flag
  *
@@ -411,7 +402,7 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
  *     and enables it if need be
  */
 
-static int ide_setup_pci_controller(struct pci_dev *dev,
+static int ide_setup_pci_controller(struct pci_dev *dev, int bars,
                                    const struct ide_port_info *d, int noisy)
 {
        int ret;
@@ -420,7 +411,7 @@ static int ide_setup_pci_controller(struct pci_dev *dev,
        if (noisy)
                ide_setup_pci_noise(dev, d);
 
-       ret = ide_pci_enable(dev, d);
+       ret = ide_pci_enable(dev, bars, d);
        if (ret < 0)
                goto out;
 
@@ -428,16 +419,20 @@ static int ide_setup_pci_controller(struct pci_dev *dev,
        if (ret < 0) {
                printk(KERN_ERR "%s %s: error accessing PCI regs\n",
                        d->name, pci_name(dev));
-               goto out;
+               goto out_free_bars;
        }
        if (!(pcicmd & PCI_COMMAND_IO)) {       /* is device disabled? */
                ret = ide_pci_configure(dev, d);
                if (ret < 0)
-                       goto out;
+                       goto out_free_bars;
                printk(KERN_INFO "%s %s: device enabled (Linux)\n",
                        d->name, pci_name(dev));
        }
 
+       goto out;
+
+out_free_bars:
+       pci_release_selected_regions(dev, bars);
 out:
        return ret;
 }
@@ -540,13 +535,28 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
 {
        struct pci_dev *pdev[] = { dev1, dev2 };
        struct ide_host *host;
-       int ret, i, n_ports = dev2 ? 4 : 2;
+       int ret, i, n_ports = dev2 ? 4 : 2, bars;
        struct ide_hw hw[4], *hws[] = { NULL, NULL, NULL, NULL };
 
+       if (d->host_flags & IDE_HFLAG_SINGLE)
+               bars = (1 << 2) - 1;
+       else
+               bars = (1 << 4) - 1;
+
+       if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) {
+               if (d->host_flags & IDE_HFLAG_CS5520)
+                       bars |= (1 << 2);
+               else
+                       bars |= (1 << 4);
+       }
+
        for (i = 0; i < n_ports / 2; i++) {
-               ret = ide_setup_pci_controller(pdev[i], d, !i);
-               if (ret < 0)
+               ret = ide_setup_pci_controller(pdev[i], bars, d, !i);
+               if (ret < 0) {
+                       if (i == 1)
+                               pci_release_selected_regions(pdev[0], bars);
                        goto out;
+               }
 
                ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]);
        }
@@ -554,7 +564,7 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
        host = ide_host_alloc(d, hws, n_ports);
        if (host == NULL) {
                ret = -ENOMEM;
-               goto out;
+               goto out_free_bars;
        }
 
        host->dev[0] = &dev1->dev;
@@ -576,7 +586,7 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
                 * do_ide_setup_pci_device() on the first device!
                 */
                if (ret < 0)
-                       goto out;
+                       goto out_free_bars;
 
                /* fixup IRQ */
                if (ide_pci_is_in_compatibility_mode(pdev[i])) {
@@ -589,6 +599,13 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2,
        ret = ide_host_register(host, d, hws);
        if (ret)
                ide_host_free(host);
+       else
+               goto out;
+
+out_free_bars:
+       i = n_ports / 2;
+       while (i--)
+               pci_release_selected_regions(pdev[i], bars);
 out:
        return ret;
 }
index e6706a0..47c3d7f 100644 (file)
@@ -257,7 +257,7 @@ static int ad7793_setup(struct iio_dev *indio_dev,
        unsigned int vref_mv)
 {
        struct ad7793_state *st = iio_priv(indio_dev);
-       int i, ret = -1;
+       int i, ret;
        unsigned long long scale_uv;
        u32 id;
 
@@ -266,7 +266,7 @@ static int ad7793_setup(struct iio_dev *indio_dev,
                return ret;
 
        /* reset the serial interface */
-       ret = spi_write(st->sd.spi, (u8 *)&ret, sizeof(ret));
+       ret = ad_sd_reset(&st->sd, 32);
        if (ret < 0)
                goto out;
        usleep_range(500, 2000); /* Wait for at least 500us */
index d10bd0c..22c4c17 100644 (file)
@@ -177,6 +177,34 @@ out:
 }
 EXPORT_SYMBOL_GPL(ad_sd_read_reg);
 
+/**
+ * ad_sd_reset() - Reset the serial interface
+ *
+ * @sigma_delta: The sigma delta device
+ * @reset_length: Number of SCLKs with DIN = 1
+ *
+ * Returns 0 on success, an error code otherwise.
+ **/
+int ad_sd_reset(struct ad_sigma_delta *sigma_delta,
+       unsigned int reset_length)
+{
+       uint8_t *buf;
+       unsigned int size;
+       int ret;
+
+       size = DIV_ROUND_UP(reset_length, 8);
+       buf = kcalloc(size, sizeof(*buf), GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       memset(buf, 0xff, size);
+       ret = spi_write(sigma_delta->spi, buf, size);
+       kfree(buf);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(ad_sd_reset);
+
 static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
        unsigned int mode, unsigned int channel)
 {
index 634717a..071dd23 100644 (file)
@@ -17,6 +17,8 @@
  * MCP3204
  * MCP3208
  * ------------
+ * 13 bit converter
+ * MCP3301
  *
  * Datasheet can be found here:
  * http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf  mcp3001
@@ -96,7 +98,7 @@ static int mcp320x_channel_to_tx_data(int device_index,
 }
 
 static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
-                                 bool differential, int device_index)
+                                 bool differential, int device_index, int *val)
 {
        int ret;
 
@@ -117,19 +119,25 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
 
        switch (device_index) {
        case mcp3001:
-               return (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3);
+               *val = (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3);
+               return 0;
        case mcp3002:
        case mcp3004:
        case mcp3008:
-               return (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6);
+               *val = (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6);
+               return 0;
        case mcp3201:
-               return (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1);
+               *val = (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1);
+               return 0;
        case mcp3202:
        case mcp3204:
        case mcp3208:
-               return (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4);
+               *val = (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4);
+               return 0;
        case mcp3301:
-               return sign_extend32((adc->rx_buf[0] & 0x1f) << 8 | adc->rx_buf[1], 12);
+               *val = sign_extend32((adc->rx_buf[0] & 0x1f) << 8
+                                   | adc->rx_buf[1], 12);
+               return 0;
        default:
                return -EINVAL;
        }
@@ -150,12 +158,10 @@ static int mcp320x_read_raw(struct iio_dev *indio_dev,
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
                ret = mcp320x_adc_conversion(adc, channel->address,
-                       channel->differential, device_index);
-
+                       channel->differential, device_index, val);
                if (ret < 0)
                        goto out;
 
-               *val = ret;
                ret = IIO_VAL_INT;
                break;
 
@@ -312,6 +318,7 @@ static int mcp320x_probe(struct spi_device *spi)
        indio_dev->name = spi_get_device_id(spi)->name;
        indio_dev->modes = INDIO_DIRECT_MODE;
        indio_dev->info = &mcp320x_info;
+       spi_set_drvdata(spi, indio_dev);
 
        chip_info = &mcp320x_chip_infos[spi_get_device_id(spi)->driver_data];
        indio_dev->channels = chip_info->channels;
index e3c15f8..4df32cf 100644 (file)
@@ -1666,7 +1666,7 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev)
 
        num_channels = of_property_count_u32_elems(node, "st,adc-channels");
        if (num_channels < 0 ||
-           num_channels >= adc_info->max_channels) {
+           num_channels > adc_info->max_channels) {
                dev_err(&indio_dev->dev, "Bad st,adc-channels?\n");
                return num_channels < 0 ? num_channels : -EINVAL;
        }
index d121002..e0dc204 100644 (file)
@@ -52,7 +52,7 @@
 
 #define ADS1015_CFG_COMP_QUE_MASK      GENMASK(1, 0)
 #define ADS1015_CFG_COMP_LAT_MASK      BIT(2)
-#define ADS1015_CFG_COMP_POL_MASK      BIT(2)
+#define ADS1015_CFG_COMP_POL_MASK      BIT(3)
 #define ADS1015_CFG_COMP_MODE_MASK     BIT(4)
 #define ADS1015_CFG_DR_MASK    GENMASK(7, 5)
 #define ADS1015_CFG_MOD_MASK   BIT(8)
@@ -1017,10 +1017,12 @@ static int ads1015_probe(struct i2c_client *client,
 
                switch (irq_trig) {
                case IRQF_TRIGGER_LOW:
-                       cfg_comp |= ADS1015_CFG_COMP_POL_LOW;
+                       cfg_comp |= ADS1015_CFG_COMP_POL_LOW <<
+                                       ADS1015_CFG_COMP_POL_SHIFT;
                        break;
                case IRQF_TRIGGER_HIGH:
-                       cfg_comp |= ADS1015_CFG_COMP_POL_HIGH;
+                       cfg_comp |= ADS1015_CFG_COMP_POL_HIGH <<
+                                       ADS1015_CFG_COMP_POL_SHIFT;
                        break;
                default:
                        return -EINVAL;
index 1edd99f..e3cfb91 100644 (file)
@@ -887,21 +887,27 @@ static int twl4030_madc_probe(struct platform_device *pdev)
 
        /* Enable 3v1 bias regulator for MADC[3:6] */
        madc->usb3v1 = devm_regulator_get(madc->dev, "vusb3v1");
-       if (IS_ERR(madc->usb3v1))
-               return -ENODEV;
+       if (IS_ERR(madc->usb3v1)) {
+               ret = -ENODEV;
+               goto err_i2c;
+       }
 
        ret = regulator_enable(madc->usb3v1);
-       if (ret)
+       if (ret) {
                dev_err(madc->dev, "could not enable 3v1 bias regulator\n");
+               goto err_i2c;
+       }
 
        ret = iio_device_register(iio_dev);
        if (ret) {
                dev_err(&pdev->dev, "could not register iio device\n");
-               goto err_i2c;
+               goto err_usb3v1;
        }
 
        return 0;
 
+err_usb3v1:
+       regulator_disable(madc->usb3v1);
 err_i2c:
        twl4030_madc_set_current_generator(madc, 0, 0);
 err_current_generator:
index d99bb14..02e833b 100644 (file)
@@ -463,8 +463,17 @@ int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable)
        u8 drdy_mask;
        struct st_sensor_data *sdata = iio_priv(indio_dev);
 
-       if (!sdata->sensor_settings->drdy_irq.addr)
+       if (!sdata->sensor_settings->drdy_irq.addr) {
+               /*
+                * there are some devices (e.g. LIS3MDL) where drdy line is
+                * routed to a given pin and it is not possible to select a
+                * different one. Take into account irq status register
+                * to understand if irq trigger can be properly supported
+                */
+               if (sdata->sensor_settings->drdy_irq.addr_stat_drdy)
+                       sdata->hw_irq_trigger = enable;
                return 0;
+       }
 
        /* Enable/Disable the interrupt generator 1. */
        if (sdata->sensor_settings->drdy_irq.ig1.en_addr > 0) {
index 17ec4ce..a47428b 100644 (file)
@@ -310,8 +310,10 @@ static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf,
        ret = indio_dev->info->debugfs_reg_access(indio_dev,
                                                  indio_dev->cached_reg_addr,
                                                  0, &val);
-       if (ret)
+       if (ret) {
                dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__);
+               return ret;
+       }
 
        len = snprintf(buf, sizeof(buf), "0x%X\n", val);
 
index e68368b..08aafba 100644 (file)
@@ -315,6 +315,10 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = {
                                },
                        },
                },
+               .drdy_irq = {
+                       /* drdy line is routed drdy pin */
+                       .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR,
+               },
                .multi_read_bit = true,
                .bootime = 2,
        },
index 0d2ea3e..8f26428 100644 (file)
@@ -573,7 +573,7 @@ static int bmp280_chip_config(struct bmp280_data *data)
        u8 osrs = BMP280_OSRS_TEMP_X(data->oversampling_temp + 1) |
                  BMP280_OSRS_PRESS_X(data->oversampling_press + 1);
 
-       ret = regmap_update_bits(data->regmap, BMP280_REG_CTRL_MEAS,
+       ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
                                 BMP280_OSRS_TEMP_MASK |
                                 BMP280_OSRS_PRESS_MASK |
                                 BMP280_MODE_MASK,
index 9b90534..eb212f8 100644 (file)
@@ -174,6 +174,7 @@ static void stm32_timer_stop(struct stm32_timer_trigger *priv)
                clk_disable(priv->clk);
 
        /* Stop timer */
+       regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);
        regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
        regmap_write(priv->regmap, TIM_PSC, 0);
        regmap_write(priv->regmap, TIM_ARR, 0);
@@ -715,8 +716,9 @@ static ssize_t stm32_count_set_preset(struct iio_dev *indio_dev,
        if (ret)
                return ret;
 
+       /* TIMx_ARR register shouldn't be buffered (ARPE=0) */
+       regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);
        regmap_write(priv->regmap, TIM_ARR, preset);
-       regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE);
 
        return len;
 }
index 30825bb..8861c05 100644 (file)
@@ -100,6 +100,8 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
        if (ret)
                goto pid_query_error;
 
+       nlmsg_end(skb, nlh);
+
        pr_debug("%s: Multicasting a nlmsg (dev = %s ifname = %s iwpm = %s)\n",
                __func__, pm_msg->dev_name, pm_msg->if_name, iwpm_ulib_name);
 
@@ -170,6 +172,8 @@ int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
                                &pm_msg->loc_addr, IWPM_NLA_MANAGE_ADDR);
        if (ret)
                goto add_mapping_error;
+
+       nlmsg_end(skb, nlh);
        nlmsg_request->req_buffer = pm_msg;
 
        ret = rdma_nl_unicast_wait(skb, iwpm_user_pid);
@@ -246,6 +250,8 @@ int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
                                &pm_msg->rem_addr, IWPM_NLA_QUERY_REMOTE_ADDR);
        if (ret)
                goto query_mapping_error;
+
+       nlmsg_end(skb, nlh);
        nlmsg_request->req_buffer = pm_msg;
 
        ret = rdma_nl_unicast_wait(skb, iwpm_user_pid);
@@ -308,6 +314,8 @@ int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client)
        if (ret)
                goto remove_mapping_error;
 
+       nlmsg_end(skb, nlh);
+
        ret = rdma_nl_unicast_wait(skb, iwpm_user_pid);
        if (ret) {
                skb = NULL; /* skb is freed in the netlink send-op handling */
index c81c559..3c4faad 100644 (file)
@@ -597,6 +597,9 @@ static int send_mapinfo_num(u32 mapping_num, u8 nl_client, int iwpm_pid)
                                &mapping_num, IWPM_NLA_MAPINFO_SEND_NUM);
        if (ret)
                goto mapinfo_num_error;
+
+       nlmsg_end(skb, nlh);
+
        ret = rdma_nl_unicast(skb, iwpm_pid);
        if (ret) {
                skb = NULL;
@@ -678,6 +681,8 @@ int iwpm_send_mapinfo(u8 nl_client, int iwpm_pid)
                        if (ret)
                                goto send_mapping_info_unlock;
 
+                       nlmsg_end(skb, nlh);
+
                        iwpm_print_sockaddr(&map_info->local_sockaddr,
                                "send_mapping_info: Local sockaddr:");
                        iwpm_print_sockaddr(&map_info->mapped_sockaddr,
index d1f5345..42ca534 100644 (file)
@@ -48,7 +48,7 @@
  * @wqe: cqp wqe for header
  * @header: header for the cqp wqe
  */
-static inline void i40iw_insert_wqe_hdr(u64 *wqe, u64 header)
+void i40iw_insert_wqe_hdr(u64 *wqe, u64 header)
 {
        wmb();            /* make sure WQE is populated before polarity is set */
        set_64bit_val(wqe, 24, header);
index e217a12..5498ad0 100644 (file)
@@ -59,6 +59,8 @@ enum i40iw_status_code i40iw_sc_mr_fast_register(struct i40iw_sc_qp *qp,
                                                 struct i40iw_fast_reg_stag_info *info,
                                                 bool post_sq);
 
+void i40iw_insert_wqe_hdr(u64 *wqe, u64 header);
+
 /* HMC/FPM functions */
 enum i40iw_status_code i40iw_sc_init_iw_hmc(struct i40iw_sc_dev *dev,
                                            u8 hmc_fn_id);
index c2cab20..59f7067 100644 (file)
@@ -123,12 +123,11 @@ static void i40iw_puda_post_recvbuf(struct i40iw_puda_rsrc *rsrc, u32 wqe_idx,
                get_64bit_val(wqe, 24, &offset24);
 
        offset24 = (offset24) ? 0 : LS_64(1, I40IWQPSQ_VALID);
-       set_64bit_val(wqe, 24, offset24);
 
        set_64bit_val(wqe, 0, buf->mem.pa);
        set_64bit_val(wqe, 8,
                      LS_64(buf->mem.size, I40IWQPSQ_FRAG_LEN));
-       set_64bit_val(wqe, 24, offset24);
+       i40iw_insert_wqe_hdr(wqe, offset24);
 }
 
 /**
@@ -409,9 +408,7 @@ enum i40iw_status_code i40iw_puda_send(struct i40iw_sc_qp *qp,
        set_64bit_val(wqe, 8, LS_64(info->len, I40IWQPSQ_FRAG_LEN));
        set_64bit_val(wqe, 16, header[0]);
 
-       /* Ensure all data is written before writing valid bit */
-       wmb();
-       set_64bit_val(wqe, 24, header[1]);
+       i40iw_insert_wqe_hdr(wqe, header[1]);
 
        i40iw_debug_buf(qp->dev, I40IW_DEBUG_PUDA, "PUDA SEND WQE", wqe, 32);
        i40iw_qp_post_wr(&qp->qp_uk);
@@ -539,7 +536,7 @@ static enum i40iw_status_code i40iw_puda_qp_wqe(struct i40iw_sc_dev *dev, struct
                 LS_64(2, I40IW_CQPSQ_QP_NEXTIWSTATE) |
                 LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
 
-       set_64bit_val(wqe, 24, header);
+       i40iw_insert_wqe_hdr(wqe, header);
 
        i40iw_debug_buf(cqp->dev, I40IW_DEBUG_PUDA, "PUDA CQE", wqe, 32);
        i40iw_sc_cqp_post_sq(cqp);
@@ -655,7 +652,7 @@ static enum i40iw_status_code i40iw_puda_cq_wqe(struct i40iw_sc_dev *dev, struct
            LS_64(1, I40IW_CQPSQ_CQ_ENCEQEMASK) |
            LS_64(1, I40IW_CQPSQ_CQ_CEQIDVALID) |
            LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID);
-       set_64bit_val(wqe, 24, header);
+       i40iw_insert_wqe_hdr(wqe, header);
 
        i40iw_debug_buf(dev, I40IW_DEBUG_PUDA, "PUDA CQE",
                        wqe, I40IW_CQP_WQE_SIZE * 8);
index 28b3d02..62be0a4 100644 (file)
@@ -826,12 +826,14 @@ static int i40iw_query_qp(struct ib_qp *ibqp,
        attr->cap.max_inline_data = I40IW_MAX_INLINE_DATA_SIZE;
        attr->cap.max_send_sge = I40IW_MAX_WQ_FRAGMENT_COUNT;
        attr->cap.max_recv_sge = I40IW_MAX_WQ_FRAGMENT_COUNT;
+       attr->port_num = 1;
        init_attr->event_handler = iwqp->ibqp.event_handler;
        init_attr->qp_context = iwqp->ibqp.qp_context;
        init_attr->send_cq = iwqp->ibqp.send_cq;
        init_attr->recv_cq = iwqp->ibqp.recv_cq;
        init_attr->srq = iwqp->ibqp.srq;
        init_attr->cap = attr->cap;
+       init_attr->port_num = 1;
        return 0;
 }
 
index d6fbad8..552f7bd 100644 (file)
@@ -4174,9 +4174,9 @@ err_bfreg:
 err_uar_page:
        mlx5_put_uars_page(dev->mdev, dev->mdev->priv.uar);
 
-err_cnt:
-       mlx5_ib_cleanup_cong_debugfs(dev);
 err_cong:
+       mlx5_ib_cleanup_cong_debugfs(dev);
+err_cnt:
        if (MLX5_CAP_GEN(dev->mdev, max_qp_cnt))
                mlx5_ib_dealloc_counters(dev);
 
index b2bb42e..254083b 100644 (file)
@@ -387,7 +387,7 @@ struct qedr_qp {
                u8 wqe_size;
 
                u8 smac[ETH_ALEN];
-               u16 vlan_id;
+               u16 vlan;
                int rc;
        } *rqe_wr_id;
 
index 4689e80..ad89653 100644 (file)
@@ -105,7 +105,7 @@ void qedr_ll2_complete_rx_packet(void *cxt,
 
        qp->rqe_wr_id[qp->rq.gsi_cons].rc = data->u.data_length_error ?
                -EINVAL : 0;
-       qp->rqe_wr_id[qp->rq.gsi_cons].vlan_id = data->vlan;
+       qp->rqe_wr_id[qp->rq.gsi_cons].vlan = data->vlan;
        /* note: length stands for data length i.e. GRH is excluded */
        qp->rqe_wr_id[qp->rq.gsi_cons].sg_list[0].length =
                data->length.data_length;
@@ -694,6 +694,7 @@ int qedr_gsi_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
        struct qedr_cq *cq = get_qedr_cq(ibcq);
        struct qedr_qp *qp = dev->gsi_qp;
        unsigned long flags;
+       u16 vlan_id;
        int i = 0;
 
        spin_lock_irqsave(&cq->cq_lock, flags);
@@ -712,9 +713,14 @@ int qedr_gsi_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
                wc[i].wc_flags |= IB_WC_GRH | IB_WC_IP_CSUM_OK;
                ether_addr_copy(wc[i].smac, qp->rqe_wr_id[qp->rq.cons].smac);
                wc[i].wc_flags |= IB_WC_WITH_SMAC;
-               if (qp->rqe_wr_id[qp->rq.cons].vlan_id) {
+
+               vlan_id = qp->rqe_wr_id[qp->rq.cons].vlan &
+                         VLAN_VID_MASK;
+               if (vlan_id) {
                        wc[i].wc_flags |= IB_WC_WITH_VLAN;
-                       wc[i].vlan_id = qp->rqe_wr_id[qp->rq.cons].vlan_id;
+                       wc[i].vlan_id = vlan_id;
+                       wc[i].sl = (qp->rqe_wr_id[qp->rq.cons].vlan &
+                                   VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
                }
 
                qedr_inc_sw_cons(&qp->rq);
index 7d5286b..1841d03 100644 (file)
@@ -64,7 +64,7 @@ EXPORT_SYMBOL(closure_put);
 void __closure_wake_up(struct closure_waitlist *wait_list)
 {
        struct llist_node *list;
-       struct closure *cl;
+       struct closure *cl, *t;
        struct llist_node *reverse = NULL;
 
        list = llist_del_all(&wait_list->list);
@@ -73,7 +73,7 @@ void __closure_wake_up(struct closure_waitlist *wait_list)
        reverse = llist_reverse_order(list);
 
        /* Then do the wakeups */
-       llist_for_each_entry(cl, reverse, list) {
+       llist_for_each_entry_safe(cl, t, reverse, list) {
                closure_set_waiting(cl, 0);
                closure_sub(cl, CLOSURE_WAITING + 1);
        }
index 24eddbd..2031447 100644 (file)
@@ -149,5 +149,6 @@ static inline bool dm_message_test_buffer_overflow(char *result, unsigned maxlen
 
 extern atomic_t dm_global_event_nr;
 extern wait_queue_head_t dm_global_eventq;
+void dm_issue_global_event(void);
 
 #endif
index a55ffd4..96ab465 100644 (file)
@@ -2466,6 +2466,7 @@ static int crypt_ctr_cipher_old(struct dm_target *ti, char *cipher_in, char *key
                kfree(cipher_api);
                return ret;
        }
+       kfree(cipher_api);
 
        return 0;
 bad_mem:
@@ -2584,6 +2585,10 @@ static int crypt_ctr_optional(struct dm_target *ti, unsigned int argc, char **ar
                                ti->error = "Invalid feature value for sector_size";
                                return -EINVAL;
                        }
+                       if (ti->len & ((cc->sector_size >> SECTOR_SHIFT) - 1)) {
+                               ti->error = "Device size is not multiple of sector_size feature";
+                               return -EINVAL;
+                       }
                        cc->sector_shift = __ffs(cc->sector_size) - SECTOR_SHIFT;
                } else if (!strcasecmp(opt_string, "iv_large_sectors"))
                        set_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags);
index 8756a68..e52676f 100644 (file)
@@ -477,9 +477,13 @@ static int remove_all(struct file *filp, struct dm_ioctl *param, size_t param_si
  * Round up the ptr to an 8-byte boundary.
  */
 #define ALIGN_MASK 7
+static inline size_t align_val(size_t val)
+{
+       return (val + ALIGN_MASK) & ~ALIGN_MASK;
+}
 static inline void *align_ptr(void *ptr)
 {
-       return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK);
+       return (void *)align_val((size_t)ptr);
 }
 
 /*
@@ -505,7 +509,7 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_
        struct hash_cell *hc;
        size_t len, needed = 0;
        struct gendisk *disk;
-       struct dm_name_list *nl, *old_nl = NULL;
+       struct dm_name_list *orig_nl, *nl, *old_nl = NULL;
        uint32_t *event_nr;
 
        down_write(&_hash_lock);
@@ -516,17 +520,15 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_
         */
        for (i = 0; i < NUM_BUCKETS; i++) {
                list_for_each_entry (hc, _name_buckets + i, name_list) {
-                       needed += sizeof(struct dm_name_list);
-                       needed += strlen(hc->name) + 1;
-                       needed += ALIGN_MASK;
-                       needed += (sizeof(uint32_t) + ALIGN_MASK) & ~ALIGN_MASK;
+                       needed += align_val(offsetof(struct dm_name_list, name) + strlen(hc->name) + 1);
+                       needed += align_val(sizeof(uint32_t));
                }
        }
 
        /*
         * Grab our output buffer.
         */
-       nl = get_result_buffer(param, param_size, &len);
+       nl = orig_nl = get_result_buffer(param, param_size, &len);
        if (len < needed) {
                param->flags |= DM_BUFFER_FULL_FLAG;
                goto out;
@@ -549,11 +551,16 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_
                        strcpy(nl->name, hc->name);
 
                        old_nl = nl;
-                       event_nr = align_ptr(((void *) (nl + 1)) + strlen(hc->name) + 1);
+                       event_nr = align_ptr(nl->name + strlen(hc->name) + 1);
                        *event_nr = dm_get_event_nr(hc->md);
                        nl = align_ptr(event_nr + 1);
                }
        }
+       /*
+        * If mismatch happens, security may be compromised due to buffer
+        * overflow, so it's better to crash.
+        */
+       BUG_ON((char *)nl - (char *)orig_nl != needed);
 
  out:
        up_write(&_hash_lock);
@@ -1621,7 +1628,8 @@ static int target_message(struct file *filp, struct dm_ioctl *param, size_t para
  * which has a variable size, is not used by the function processing
  * the ioctl.
  */
-#define IOCTL_FLAGS_NO_PARAMS  1
+#define IOCTL_FLAGS_NO_PARAMS          1
+#define IOCTL_FLAGS_ISSUE_GLOBAL_EVENT 2
 
 /*-----------------------------------------------------------------
  * Implementation of open/close/ioctl on the special char
@@ -1635,12 +1643,12 @@ static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags)
                ioctl_fn fn;
        } _ioctls[] = {
                {DM_VERSION_CMD, 0, NULL}, /* version is dealt with elsewhere */
-               {DM_REMOVE_ALL_CMD, IOCTL_FLAGS_NO_PARAMS, remove_all},
+               {DM_REMOVE_ALL_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, remove_all},
                {DM_LIST_DEVICES_CMD, 0, list_devices},
 
-               {DM_DEV_CREATE_CMD, IOCTL_FLAGS_NO_PARAMS, dev_create},
-               {DM_DEV_REMOVE_CMD, IOCTL_FLAGS_NO_PARAMS, dev_remove},
-               {DM_DEV_RENAME_CMD, 0, dev_rename},
+               {DM_DEV_CREATE_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_create},
+               {DM_DEV_REMOVE_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_remove},
+               {DM_DEV_RENAME_CMD, IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_rename},
                {DM_DEV_SUSPEND_CMD, IOCTL_FLAGS_NO_PARAMS, dev_suspend},
                {DM_DEV_STATUS_CMD, IOCTL_FLAGS_NO_PARAMS, dev_status},
                {DM_DEV_WAIT_CMD, 0, dev_wait},
@@ -1869,6 +1877,9 @@ static int ctl_ioctl(struct file *file, uint command, struct dm_ioctl __user *us
            unlikely(ioctl_flags & IOCTL_FLAGS_NO_PARAMS))
                DMERR("ioctl %d tried to output some data but has IOCTL_FLAGS_NO_PARAMS set", cmd);
 
+       if (!r && ioctl_flags & IOCTL_FLAGS_ISSUE_GLOBAL_EVENT)
+               dm_issue_global_event();
+
        /*
         * Copy the results back to userland.
         */
index 1ac58c5..2245d06 100644 (file)
@@ -3297,11 +3297,10 @@ static const char *__raid_dev_status(struct raid_set *rs, struct md_rdev *rdev,
 static sector_t rs_get_progress(struct raid_set *rs,
                                sector_t resync_max_sectors, bool *array_in_sync)
 {
-       sector_t r, recovery_cp, curr_resync_completed;
+       sector_t r, curr_resync_completed;
        struct mddev *mddev = &rs->md;
 
        curr_resync_completed = mddev->curr_resync_completed ?: mddev->recovery_cp;
-       recovery_cp = mddev->recovery_cp;
        *array_in_sync = false;
 
        if (rs_is_raid0(rs)) {
@@ -3330,9 +3329,11 @@ static sector_t rs_get_progress(struct raid_set *rs,
                } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
                        r = curr_resync_completed;
                else
-                       r = recovery_cp;
+                       r = mddev->recovery_cp;
 
-               if (r == MaxSector) {
+               if ((r == MaxSector) ||
+                   (test_bit(MD_RECOVERY_DONE, &mddev->recovery) &&
+                    (mddev->curr_resync_completed == resync_max_sectors))) {
                        /*
                         * Sync complete.
                         */
@@ -3892,7 +3893,7 @@ static void raid_resume(struct dm_target *ti)
 
 static struct target_type raid_target = {
        .name = "raid",
-       .version = {1, 12, 1},
+       .version = {1, 13, 0},
        .module = THIS_MODULE,
        .ctr = raid_ctr,
        .dtr = raid_dtr,
index 6e54145..4be8532 100644 (file)
@@ -52,6 +52,12 @@ static struct workqueue_struct *deferred_remove_workqueue;
 atomic_t dm_global_event_nr = ATOMIC_INIT(0);
 DECLARE_WAIT_QUEUE_HEAD(dm_global_eventq);
 
+void dm_issue_global_event(void)
+{
+       atomic_inc(&dm_global_event_nr);
+       wake_up(&dm_global_eventq);
+}
+
 /*
  * One of these is allocated per bio.
  */
@@ -1865,9 +1871,8 @@ static void event_callback(void *context)
        dm_send_uevents(&uevents, &disk_to_dev(md->disk)->kobj);
 
        atomic_inc(&md->event_nr);
-       atomic_inc(&dm_global_event_nr);
        wake_up(&md->eventq);
-       wake_up(&dm_global_eventq);
+       dm_issue_global_event();
 }
 
 /*
@@ -2283,6 +2288,7 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
        }
 
        map = __bind(md, table, &limits);
+       dm_issue_global_event();
 
 out:
        mutex_unlock(&md->suspend_lock);
index ed43a42..129b558 100644 (file)
@@ -245,5 +245,5 @@ module_init(ir_sharp_decode_init);
 module_exit(ir_sharp_decode_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("James Hogan <james.hogan@imgtec.com>");
+MODULE_AUTHOR("James Hogan <jhogan@kernel.org>");
 MODULE_DESCRIPTION("Sharp IR protocol decoder");
index 5dba23c..dc9bc18 100644 (file)
@@ -219,8 +219,17 @@ int cxllib_handle_fault(struct mm_struct *mm, u64 addr, u64 size, u64 flags)
 
        down_read(&mm->mmap_sem);
 
-       for (dar = addr; dar < addr + size; dar += page_size) {
-               if (!vma || dar < vma->vm_start || dar > vma->vm_end) {
+       vma = find_vma(mm, addr);
+       if (!vma) {
+               pr_err("Can't find vma for addr %016llx\n", addr);
+               rc = -EFAULT;
+               goto out;
+       }
+       /* get the size of the pages allocated */
+       page_size = vma_kernel_pagesize(vma);
+
+       for (dar = (addr & ~(page_size - 1)); dar < (addr + size); dar += page_size) {
+               if (dar < vma->vm_start || dar >= vma->vm_end) {
                        vma = find_vma(mm, addr);
                        if (!vma) {
                                pr_err("Can't find vma for addr %016llx\n", addr);
index c6678aa..d74c733 100644 (file)
@@ -1100,6 +1100,10 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port,
        };
        int i, err;
 
+       /* DSA and CPU ports have to be members of multiple vlans */
+       if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
+               return 0;
+
        if (!vid_begin)
                return -EOPNOTSUPP;
 
@@ -3947,7 +3951,9 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev)
        if (chip->irq > 0) {
                if (chip->info->g2_irqs > 0)
                        mv88e6xxx_g2_irq_free(chip);
+               mutex_lock(&chip->reg_lock);
                mv88e6xxx_g1_irq_free(chip);
+               mutex_unlock(&chip->reg_lock);
        }
 }
 
index 2149864..0fdaaa6 100644 (file)
 
 #define AQ_CFG_SKB_FRAGS_MAX   32U
 
+/* Number of descriptors available in one ring to resume this ring queue
+ */
+#define AQ_CFG_RESTART_DESC_THRES   (AQ_CFG_SKB_FRAGS_MAX * 2)
+
 #define AQ_CFG_NAPI_WEIGHT     64U
 
 #define AQ_CFG_MULTICAST_ADDRESS_MAX     32U
index 6ac9e26..0a5bb41 100644 (file)
@@ -119,6 +119,35 @@ int aq_nic_cfg_start(struct aq_nic_s *self)
        return 0;
 }
 
+static int aq_nic_update_link_status(struct aq_nic_s *self)
+{
+       int err = self->aq_hw_ops.hw_get_link_status(self->aq_hw);
+
+       if (err)
+               return err;
+
+       if (self->link_status.mbps != self->aq_hw->aq_link_status.mbps)
+               pr_info("%s: link change old %d new %d\n",
+                       AQ_CFG_DRV_NAME, self->link_status.mbps,
+                       self->aq_hw->aq_link_status.mbps);
+
+       self->link_status = self->aq_hw->aq_link_status;
+       if (!netif_carrier_ok(self->ndev) && self->link_status.mbps) {
+               aq_utils_obj_set(&self->header.flags,
+                                AQ_NIC_FLAG_STARTED);
+               aq_utils_obj_clear(&self->header.flags,
+                                  AQ_NIC_LINK_DOWN);
+               netif_carrier_on(self->ndev);
+               netif_tx_wake_all_queues(self->ndev);
+       }
+       if (netif_carrier_ok(self->ndev) && !self->link_status.mbps) {
+               netif_carrier_off(self->ndev);
+               netif_tx_disable(self->ndev);
+               aq_utils_obj_set(&self->header.flags, AQ_NIC_LINK_DOWN);
+       }
+       return 0;
+}
+
 static void aq_nic_service_timer_cb(unsigned long param)
 {
        struct aq_nic_s *self = (struct aq_nic_s *)param;
@@ -131,26 +160,13 @@ static void aq_nic_service_timer_cb(unsigned long param)
        if (aq_utils_obj_test(&self->header.flags, AQ_NIC_FLAGS_IS_NOT_READY))
                goto err_exit;
 
-       err = self->aq_hw_ops.hw_get_link_status(self->aq_hw);
-       if (err < 0)
+       err = aq_nic_update_link_status(self);
+       if (err)
                goto err_exit;
 
-       self->link_status = self->aq_hw->aq_link_status;
-
        self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw,
                    self->aq_nic_cfg.is_interrupt_moderation);
 
-       if (self->link_status.mbps) {
-               aq_utils_obj_set(&self->header.flags,
-                                AQ_NIC_FLAG_STARTED);
-               aq_utils_obj_clear(&self->header.flags,
-                                  AQ_NIC_LINK_DOWN);
-               netif_carrier_on(self->ndev);
-       } else {
-               netif_carrier_off(self->ndev);
-               aq_utils_obj_set(&self->header.flags, AQ_NIC_LINK_DOWN);
-       }
-
        memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s));
        memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s));
        for (i = AQ_DIMOF(self->aq_vec); i--;) {
@@ -214,7 +230,6 @@ struct aq_nic_s *aq_nic_alloc_cold(const struct net_device_ops *ndev_ops,
        SET_NETDEV_DEV(ndev, dev);
 
        ndev->if_port = port;
-       ndev->min_mtu = ETH_MIN_MTU;
        self->ndev = ndev;
 
        self->aq_pci_func = aq_pci_func;
@@ -241,7 +256,6 @@ err_exit:
 int aq_nic_ndev_register(struct aq_nic_s *self)
 {
        int err = 0;
-       unsigned int i = 0U;
 
        if (!self->ndev) {
                err = -EINVAL;
@@ -263,8 +277,7 @@ int aq_nic_ndev_register(struct aq_nic_s *self)
 
        netif_carrier_off(self->ndev);
 
-       for (i = AQ_CFG_VECS_MAX; i--;)
-               aq_nic_ndev_queue_stop(self, i);
+       netif_tx_disable(self->ndev);
 
        err = register_netdev(self->ndev);
        if (err < 0)
@@ -283,6 +296,7 @@ int aq_nic_ndev_init(struct aq_nic_s *self)
        self->ndev->features = aq_hw_caps->hw_features;
        self->ndev->priv_flags = aq_hw_caps->hw_priv_flags;
        self->ndev->mtu = aq_nic_cfg->mtu - ETH_HLEN;
+       self->ndev->max_mtu = self->aq_hw_caps.mtu - ETH_FCS_LEN - ETH_HLEN;
 
        return 0;
 }
@@ -318,12 +332,8 @@ struct aq_nic_s *aq_nic_alloc_hot(struct net_device *ndev)
                err = -EINVAL;
                goto err_exit;
        }
-       if (netif_running(ndev)) {
-               unsigned int i;
-
-               for (i = AQ_CFG_VECS_MAX; i--;)
-                       netif_stop_subqueue(ndev, i);
-       }
+       if (netif_running(ndev))
+               netif_tx_disable(ndev);
 
        for (self->aq_vecs = 0; self->aq_vecs < self->aq_nic_cfg.vecs;
                self->aq_vecs++) {
@@ -383,16 +393,6 @@ err_exit:
        return err;
 }
 
-void aq_nic_ndev_queue_start(struct aq_nic_s *self, unsigned int idx)
-{
-       netif_start_subqueue(self->ndev, idx);
-}
-
-void aq_nic_ndev_queue_stop(struct aq_nic_s *self, unsigned int idx)
-{
-       netif_stop_subqueue(self->ndev, idx);
-}
-
 int aq_nic_start(struct aq_nic_s *self)
 {
        struct aq_vec_s *aq_vec = NULL;
@@ -451,10 +451,6 @@ int aq_nic_start(struct aq_nic_s *self)
                        goto err_exit;
        }
 
-       for (i = 0U, aq_vec = self->aq_vec[0];
-               self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i])
-               aq_nic_ndev_queue_start(self, i);
-
        err = netif_set_real_num_tx_queues(self->ndev, self->aq_vecs);
        if (err < 0)
                goto err_exit;
@@ -463,6 +459,8 @@ int aq_nic_start(struct aq_nic_s *self)
        if (err < 0)
                goto err_exit;
 
+       netif_tx_start_all_queues(self->ndev);
+
 err_exit:
        return err;
 }
@@ -475,6 +473,7 @@ static unsigned int aq_nic_map_skb(struct aq_nic_s *self,
        unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
        unsigned int frag_count = 0U;
        unsigned int dx = ring->sw_tail;
+       struct aq_ring_buff_s *first = NULL;
        struct aq_ring_buff_s *dx_buff = &ring->buff_ring[dx];
 
        if (unlikely(skb_is_gso(skb))) {
@@ -485,6 +484,7 @@ static unsigned int aq_nic_map_skb(struct aq_nic_s *self,
                dx_buff->len_l4 = tcp_hdrlen(skb);
                dx_buff->mss = skb_shinfo(skb)->gso_size;
                dx_buff->is_txc = 1U;
+               dx_buff->eop_index = 0xffffU;
 
                dx_buff->is_ipv6 =
                        (ip_hdr(skb)->version == 6) ? 1U : 0U;
@@ -504,6 +504,7 @@ static unsigned int aq_nic_map_skb(struct aq_nic_s *self,
        if (unlikely(dma_mapping_error(aq_nic_get_dev(self), dx_buff->pa)))
                goto exit;
 
+       first = dx_buff;
        dx_buff->len_pkt = skb->len;
        dx_buff->is_sop = 1U;
        dx_buff->is_mapped = 1U;
@@ -532,40 +533,46 @@ static unsigned int aq_nic_map_skb(struct aq_nic_s *self,
 
        for (; nr_frags--; ++frag_count) {
                unsigned int frag_len = 0U;
+               unsigned int buff_offset = 0U;
+               unsigned int buff_size = 0U;
                dma_addr_t frag_pa;
                skb_frag_t *frag = &skb_shinfo(skb)->frags[frag_count];
 
                frag_len = skb_frag_size(frag);
-               frag_pa = skb_frag_dma_map(aq_nic_get_dev(self), frag, 0,
-                                          frag_len, DMA_TO_DEVICE);
 
-               if (unlikely(dma_mapping_error(aq_nic_get_dev(self), frag_pa)))
-                       goto mapping_error;
+               while (frag_len) {
+                       if (frag_len > AQ_CFG_TX_FRAME_MAX)
+                               buff_size = AQ_CFG_TX_FRAME_MAX;
+                       else
+                               buff_size = frag_len;
+
+                       frag_pa = skb_frag_dma_map(aq_nic_get_dev(self),
+                                                  frag,
+                                                  buff_offset,
+                                                  buff_size,
+                                                  DMA_TO_DEVICE);
+
+                       if (unlikely(dma_mapping_error(aq_nic_get_dev(self),
+                                                      frag_pa)))
+                               goto mapping_error;
 
-               while (frag_len > AQ_CFG_TX_FRAME_MAX) {
                        dx = aq_ring_next_dx(ring, dx);
                        dx_buff = &ring->buff_ring[dx];
 
                        dx_buff->flags = 0U;
-                       dx_buff->len = AQ_CFG_TX_FRAME_MAX;
+                       dx_buff->len = buff_size;
                        dx_buff->pa = frag_pa;
                        dx_buff->is_mapped = 1U;
+                       dx_buff->eop_index = 0xffffU;
+
+                       frag_len -= buff_size;
+                       buff_offset += buff_size;
 
-                       frag_len -= AQ_CFG_TX_FRAME_MAX;
-                       frag_pa += AQ_CFG_TX_FRAME_MAX;
                        ++ret;
                }
-
-               dx = aq_ring_next_dx(ring, dx);
-               dx_buff = &ring->buff_ring[dx];
-
-               dx_buff->flags = 0U;
-               dx_buff->len = frag_len;
-               dx_buff->pa = frag_pa;
-               dx_buff->is_mapped = 1U;
-               ++ret;
        }
 
+       first->eop_index = dx;
        dx_buff->is_eop = 1U;
        dx_buff->skb = skb;
        goto exit;
@@ -602,7 +609,6 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb)
        unsigned int vec = skb->queue_mapping % self->aq_nic_cfg.vecs;
        unsigned int tc = 0U;
        int err = NETDEV_TX_OK;
-       bool is_nic_in_bad_state;
 
        frags = skb_shinfo(skb)->nr_frags + 1;
 
@@ -613,13 +619,10 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb)
                goto err_exit;
        }
 
-       is_nic_in_bad_state = aq_utils_obj_test(&self->header.flags,
-                                               AQ_NIC_FLAGS_IS_NOT_TX_READY) ||
-                                               (aq_ring_avail_dx(ring) <
-                                               AQ_CFG_SKB_FRAGS_MAX);
+       aq_ring_update_queue_state(ring);
 
-       if (is_nic_in_bad_state) {
-               aq_nic_ndev_queue_stop(self, ring->idx);
+       /* Above status update may stop the queue. Check this. */
+       if (__netif_subqueue_stopped(self->ndev, ring->idx)) {
                err = NETDEV_TX_BUSY;
                goto err_exit;
        }
@@ -631,9 +634,6 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb)
                                                      ring,
                                                      frags);
                if (err >= 0) {
-                       if (aq_ring_avail_dx(ring) < AQ_CFG_SKB_FRAGS_MAX + 1)
-                               aq_nic_ndev_queue_stop(self, ring->idx);
-
                        ++ring->stats.tx.packets;
                        ring->stats.tx.bytes += skb->len;
                }
@@ -693,16 +693,9 @@ int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev)
 
 int aq_nic_set_mtu(struct aq_nic_s *self, int new_mtu)
 {
-       int err = 0;
-
-       if (new_mtu > self->aq_hw_caps.mtu) {
-               err = -EINVAL;
-               goto err_exit;
-       }
        self->aq_nic_cfg.mtu = new_mtu;
 
-err_exit:
-       return err;
+       return 0;
 }
 
 int aq_nic_set_mac(struct aq_nic_s *self, struct net_device *ndev)
@@ -905,9 +898,7 @@ int aq_nic_stop(struct aq_nic_s *self)
        struct aq_vec_s *aq_vec = NULL;
        unsigned int i = 0U;
 
-       for (i = 0U, aq_vec = self->aq_vec[0];
-               self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i])
-               aq_nic_ndev_queue_stop(self, i);
+       netif_tx_disable(self->ndev);
 
        del_timer_sync(&self->service_timer);
 
index 7fc2a5e..0ddd556 100644 (file)
@@ -83,8 +83,6 @@ struct net_device *aq_nic_get_ndev(struct aq_nic_s *self);
 int aq_nic_init(struct aq_nic_s *self);
 int aq_nic_cfg_start(struct aq_nic_s *self);
 int aq_nic_ndev_register(struct aq_nic_s *self);
-void aq_nic_ndev_queue_start(struct aq_nic_s *self, unsigned int idx);
-void aq_nic_ndev_queue_stop(struct aq_nic_s *self, unsigned int idx);
 void aq_nic_ndev_free(struct aq_nic_s *self);
 int aq_nic_start(struct aq_nic_s *self);
 int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb);
index 4eee199..0654e0c 100644 (file)
@@ -104,6 +104,38 @@ int aq_ring_init(struct aq_ring_s *self)
        return 0;
 }
 
+static inline bool aq_ring_dx_in_range(unsigned int h, unsigned int i,
+                                      unsigned int t)
+{
+       return (h < t) ? ((h < i) && (i < t)) : ((h < i) || (i < t));
+}
+
+void aq_ring_update_queue_state(struct aq_ring_s *ring)
+{
+       if (aq_ring_avail_dx(ring) <= AQ_CFG_SKB_FRAGS_MAX)
+               aq_ring_queue_stop(ring);
+       else if (aq_ring_avail_dx(ring) > AQ_CFG_RESTART_DESC_THRES)
+               aq_ring_queue_wake(ring);
+}
+
+void aq_ring_queue_wake(struct aq_ring_s *ring)
+{
+       struct net_device *ndev = aq_nic_get_ndev(ring->aq_nic);
+
+       if (__netif_subqueue_stopped(ndev, ring->idx)) {
+               netif_wake_subqueue(ndev, ring->idx);
+               ring->stats.tx.queue_restarts++;
+       }
+}
+
+void aq_ring_queue_stop(struct aq_ring_s *ring)
+{
+       struct net_device *ndev = aq_nic_get_ndev(ring->aq_nic);
+
+       if (!__netif_subqueue_stopped(ndev, ring->idx))
+               netif_stop_subqueue(ndev, ring->idx);
+}
+
 void aq_ring_tx_clean(struct aq_ring_s *self)
 {
        struct device *dev = aq_nic_get_dev(self->aq_nic);
@@ -113,23 +145,28 @@ void aq_ring_tx_clean(struct aq_ring_s *self)
                struct aq_ring_buff_s *buff = &self->buff_ring[self->sw_head];
 
                if (likely(buff->is_mapped)) {
-                       if (unlikely(buff->is_sop))
+                       if (unlikely(buff->is_sop)) {
+                               if (!buff->is_eop &&
+                                   buff->eop_index != 0xffffU &&
+                                   (!aq_ring_dx_in_range(self->sw_head,
+                                               buff->eop_index,
+                                               self->hw_head)))
+                                       break;
+
                                dma_unmap_single(dev, buff->pa, buff->len,
                                                 DMA_TO_DEVICE);
-                       else
+                       } else {
                                dma_unmap_page(dev, buff->pa, buff->len,
                                               DMA_TO_DEVICE);
+                       }
                }
 
                if (unlikely(buff->is_eop))
                        dev_kfree_skb_any(buff->skb);
-       }
-}
 
-static inline unsigned int aq_ring_dx_in_range(unsigned int h, unsigned int i,
-                                              unsigned int t)
-{
-       return (h < t) ? ((h < i) && (i < t)) : ((h < i) || (i < t));
+               buff->pa = 0U;
+               buff->eop_index = 0xffffU;
+       }
 }
 
 #define AQ_SKB_ALIGN SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
index 782176c..5844078 100644 (file)
@@ -65,7 +65,7 @@ struct __packed aq_ring_buff_s {
        };
        union {
                struct {
-                       u32 len:16;
+                       u16 len;
                        u32 is_ip_cso:1;
                        u32 is_udp_cso:1;
                        u32 is_tcp_cso:1;
@@ -77,8 +77,10 @@ struct __packed aq_ring_buff_s {
                        u32 is_cleaned:1;
                        u32 is_error:1;
                        u32 rsvd3:6;
+                       u16 eop_index;
+                       u16 rsvd4;
                };
-               u32 flags;
+               u64 flags;
        };
 };
 
@@ -94,6 +96,7 @@ struct aq_ring_stats_tx_s {
        u64 errors;
        u64 packets;
        u64 bytes;
+       u64 queue_restarts;
 };
 
 union aq_ring_stats_s {
@@ -147,6 +150,9 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
 int aq_ring_init(struct aq_ring_s *self);
 void aq_ring_rx_deinit(struct aq_ring_s *self);
 void aq_ring_free(struct aq_ring_s *self);
+void aq_ring_update_queue_state(struct aq_ring_s *ring);
+void aq_ring_queue_wake(struct aq_ring_s *ring);
+void aq_ring_queue_stop(struct aq_ring_s *ring);
 void aq_ring_tx_clean(struct aq_ring_s *self);
 int aq_ring_rx_clean(struct aq_ring_s *self,
                     struct napi_struct *napi,
index ebf5880..305ff8f 100644 (file)
@@ -59,12 +59,7 @@ static int aq_vec_poll(struct napi_struct *napi, int budget)
                        if (ring[AQ_VEC_TX_ID].sw_head !=
                            ring[AQ_VEC_TX_ID].hw_head) {
                                aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]);
-
-                               if (aq_ring_avail_dx(&ring[AQ_VEC_TX_ID]) >
-                                   AQ_CFG_SKB_FRAGS_MAX) {
-                                       aq_nic_ndev_queue_start(self->aq_nic,
-                                               ring[AQ_VEC_TX_ID].idx);
-                               }
+                               aq_ring_update_queue_state(&ring[AQ_VEC_TX_ID]);
                                was_tx_cleaned = true;
                        }
 
@@ -364,6 +359,7 @@ void aq_vec_add_stats(struct aq_vec_s *self,
                stats_tx->packets += tx->packets;
                stats_tx->bytes += tx->bytes;
                stats_tx->errors += tx->errors;
+               stats_tx->queue_restarts += tx->queue_restarts;
        }
 }
 
index f3957e9..fcf89e2 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "../aq_common.h"
 
-#define HW_ATL_B0_MTU_JUMBO (16000U)
+#define HW_ATL_B0_MTU_JUMBO  16352U
 #define HW_ATL_B0_MTU        1514U
 
 #define HW_ATL_B0_TX_RINGS 4U
index 4f5ec9a..bf734b3 100644 (file)
@@ -351,8 +351,7 @@ int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
                        break;
 
                default:
-                       link_status->mbps = 0U;
-                       break;
+                       return -EBUSY;
                }
        }
 
index cec94bb..8bc126a 100644 (file)
@@ -1278,7 +1278,7 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
 
        ret = cnic_alloc_dma(dev, kwq_16_dma, pages, 0);
        if (ret)
-               return -ENOMEM;
+               goto error;
 
        n = CNIC_PAGE_SIZE / CNIC_KWQ16_DATA_SIZE;
        for (i = 0, j = 0; i < cp->max_cid_space; i++) {
index e0685e6..c1cdbfd 100644 (file)
@@ -2652,7 +2652,8 @@ static int hclge_rss_init_hw(struct hclge_dev *hdev)
                dev_err(&hdev->pdev->dev,
                        "Configure rss tc size failed, invalid TC_SIZE = %d\n",
                        rss_size);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err;
        }
 
        roundup_size = roundup_pow_of_two(rss_size);
index dd0ee26..9c86cb7 100644 (file)
 #define     MVPP2_GMAC_INBAND_AN_MASK          BIT(0)
 #define     MVPP2_GMAC_FLOW_CTRL_MASK          GENMASK(2, 1)
 #define     MVPP2_GMAC_PCS_ENABLE_MASK         BIT(3)
-#define     MVPP2_GMAC_PORT_RGMII_MASK         BIT(4)
+#define     MVPP2_GMAC_INTERNAL_CLK_MASK       BIT(4)
 #define     MVPP2_GMAC_DISABLE_PADDING         BIT(5)
 #define     MVPP2_GMAC_PORT_RESET_MASK         BIT(6)
 #define MVPP2_GMAC_AUTONEG_CONFIG              0xc
@@ -676,6 +676,7 @@ enum mvpp2_tag_type {
 #define MVPP2_PRS_RI_L3_MCAST                  BIT(15)
 #define MVPP2_PRS_RI_L3_BCAST                  (BIT(15) | BIT(16))
 #define MVPP2_PRS_RI_IP_FRAG_MASK              0x20000
+#define MVPP2_PRS_RI_IP_FRAG_TRUE              BIT(17)
 #define MVPP2_PRS_RI_UDF3_MASK                 0x300000
 #define MVPP2_PRS_RI_UDF3_RX_SPECIAL           BIT(21)
 #define MVPP2_PRS_RI_L4_PROTO_MASK             0x1c00000
@@ -792,6 +793,7 @@ struct mvpp2 {
        struct clk *pp_clk;
        struct clk *gop_clk;
        struct clk *mg_clk;
+       struct clk *axi_clk;
 
        /* List of pointers to port structures */
        struct mvpp2_port **port_list;
@@ -2315,7 +2317,7 @@ static int mvpp2_prs_ip4_proto(struct mvpp2 *priv, unsigned short proto,
            (proto != IPPROTO_IGMP))
                return -EINVAL;
 
-       /* Fragmented packet */
+       /* Not fragmented packet */
        tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
                                        MVPP2_PE_LAST_FREE_TID);
        if (tid < 0)
@@ -2334,8 +2336,12 @@ static int mvpp2_prs_ip4_proto(struct mvpp2 *priv, unsigned short proto,
                                  MVPP2_PRS_SRAM_OP_SEL_UDF_ADD);
        mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT,
                                 MVPP2_PRS_IPV4_DIP_AI_BIT);
-       mvpp2_prs_sram_ri_update(&pe, ri | MVPP2_PRS_RI_IP_FRAG_MASK,
-                                ri_mask | MVPP2_PRS_RI_IP_FRAG_MASK);
+       mvpp2_prs_sram_ri_update(&pe, ri, ri_mask | MVPP2_PRS_RI_IP_FRAG_MASK);
+
+       mvpp2_prs_tcam_data_byte_set(&pe, 2, 0x00,
+                                    MVPP2_PRS_TCAM_PROTO_MASK_L);
+       mvpp2_prs_tcam_data_byte_set(&pe, 3, 0x00,
+                                    MVPP2_PRS_TCAM_PROTO_MASK);
 
        mvpp2_prs_tcam_data_byte_set(&pe, 5, proto, MVPP2_PRS_TCAM_PROTO_MASK);
        mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV4_DIP_AI_BIT);
@@ -2346,7 +2352,7 @@ static int mvpp2_prs_ip4_proto(struct mvpp2 *priv, unsigned short proto,
        mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
        mvpp2_prs_hw_write(priv, &pe);
 
-       /* Not fragmented packet */
+       /* Fragmented packet */
        tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
                                        MVPP2_PE_LAST_FREE_TID);
        if (tid < 0)
@@ -2358,8 +2364,11 @@ static int mvpp2_prs_ip4_proto(struct mvpp2 *priv, unsigned short proto,
        pe.sram.word[MVPP2_PRS_SRAM_RI_CTRL_WORD] = 0x0;
        mvpp2_prs_sram_ri_update(&pe, ri, ri_mask);
 
-       mvpp2_prs_tcam_data_byte_set(&pe, 2, 0x00, MVPP2_PRS_TCAM_PROTO_MASK_L);
-       mvpp2_prs_tcam_data_byte_set(&pe, 3, 0x00, MVPP2_PRS_TCAM_PROTO_MASK);
+       mvpp2_prs_sram_ri_update(&pe, ri | MVPP2_PRS_RI_IP_FRAG_TRUE,
+                                ri_mask | MVPP2_PRS_RI_IP_FRAG_MASK);
+
+       mvpp2_prs_tcam_data_byte_set(&pe, 2, 0x00, 0x0);
+       mvpp2_prs_tcam_data_byte_set(&pe, 3, 0x00, 0x0);
 
        /* Update shadow table and hw entry */
        mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4);
@@ -4591,7 +4600,6 @@ static void mvpp2_port_mii_gmac_configure(struct mvpp2_port *port)
                val |= MVPP2_GMAC_INBAND_AN_MASK | MVPP2_GMAC_PCS_ENABLE_MASK;
        } else if (phy_interface_mode_is_rgmii(port->phy_interface)) {
                val &= ~MVPP2_GMAC_PCS_ENABLE_MASK;
-               val |= MVPP2_GMAC_PORT_RGMII_MASK;
        }
        writel(val, port->base + MVPP2_GMAC_CTRL_2_REG);
 
@@ -7496,7 +7504,7 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv,
 /* Ports initialization */
 static int mvpp2_port_probe(struct platform_device *pdev,
                            struct device_node *port_node,
-                           struct mvpp2 *priv)
+                           struct mvpp2 *priv, int index)
 {
        struct device_node *phy_node;
        struct phy *comphy;
@@ -7670,7 +7678,7 @@ static int mvpp2_port_probe(struct platform_device *pdev,
        }
        netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr);
 
-       priv->port_list[id] = port;
+       priv->port_list[index] = port;
        return 0;
 
 err_free_port_pcpu:
@@ -7963,6 +7971,18 @@ static int mvpp2_probe(struct platform_device *pdev)
                err = clk_prepare_enable(priv->mg_clk);
                if (err < 0)
                        goto err_gop_clk;
+
+               priv->axi_clk = devm_clk_get(&pdev->dev, "axi_clk");
+               if (IS_ERR(priv->axi_clk)) {
+                       err = PTR_ERR(priv->axi_clk);
+                       if (err == -EPROBE_DEFER)
+                               goto err_gop_clk;
+                       priv->axi_clk = NULL;
+               } else {
+                       err = clk_prepare_enable(priv->axi_clk);
+                       if (err < 0)
+                               goto err_gop_clk;
+               }
        }
 
        /* Get system's tclk rate */
@@ -8005,16 +8025,19 @@ static int mvpp2_probe(struct platform_device *pdev)
        }
 
        /* Initialize ports */
+       i = 0;
        for_each_available_child_of_node(dn, port_node) {
-               err = mvpp2_port_probe(pdev, port_node, priv);
+               err = mvpp2_port_probe(pdev, port_node, priv, i);
                if (err < 0)
                        goto err_mg_clk;
+               i++;
        }
 
        platform_set_drvdata(pdev, priv);
        return 0;
 
 err_mg_clk:
+       clk_disable_unprepare(priv->axi_clk);
        if (priv->hw_version == MVPP22)
                clk_disable_unprepare(priv->mg_clk);
 err_gop_clk:
@@ -8052,6 +8075,7 @@ static int mvpp2_remove(struct platform_device *pdev)
                                  aggr_txq->descs_dma);
        }
 
+       clk_disable_unprepare(priv->axi_clk);
        clk_disable_unprepare(priv->mg_clk);
        clk_disable_unprepare(priv->pp_clk);
        clk_disable_unprepare(priv->gop_clk);
index 1e3a6c3..80eef41 100644 (file)
@@ -139,7 +139,7 @@ TRACE_EVENT(mlx5_fs_del_fg,
        {MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO, "NEXT_PRIO"}
 
 TRACE_EVENT(mlx5_fs_set_fte,
-           TP_PROTO(const struct fs_fte *fte, bool new_fte),
+           TP_PROTO(const struct fs_fte *fte, int new_fte),
            TP_ARGS(fte, new_fte),
            TP_STRUCT__entry(
                __field(const struct fs_fte *, fte)
@@ -149,7 +149,7 @@ TRACE_EVENT(mlx5_fs_set_fte,
                __field(u32, action)
                __field(u32, flow_tag)
                __field(u8,  mask_enable)
-               __field(bool, new_fte)
+               __field(int, new_fte)
                __array(u32, mask_outer, MLX5_ST_SZ_DW(fte_match_set_lyr_2_4))
                __array(u32, mask_inner, MLX5_ST_SZ_DW(fte_match_set_lyr_2_4))
                __array(u32, mask_misc, MLX5_ST_SZ_DW(fte_match_set_misc))
index f11fd07..850cdc9 100644 (file)
@@ -291,7 +291,7 @@ void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv)
        priv->fs.vlan.filter_disabled = false;
        if (priv->netdev->flags & IFF_PROMISC)
                return;
-       mlx5e_del_any_vid_rules(priv);
+       mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
 }
 
 void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv)
@@ -302,7 +302,7 @@ void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv)
        priv->fs.vlan.filter_disabled = true;
        if (priv->netdev->flags & IFF_PROMISC)
                return;
-       mlx5e_add_any_vid_rules(priv);
+       mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
 }
 
 int mlx5e_vlan_rx_add_vid(struct net_device *dev, __always_unused __be16 proto,
index dfc2972..cc11bbb 100644 (file)
@@ -184,7 +184,6 @@ static void mlx5e_update_sw_counters(struct mlx5e_priv *priv)
        struct mlx5e_sw_stats temp, *s = &temp;
        struct mlx5e_rq_stats *rq_stats;
        struct mlx5e_sq_stats *sq_stats;
-       u64 tx_offload_none = 0;
        int i, j;
 
        memset(s, 0, sizeof(*s));
@@ -199,6 +198,7 @@ static void mlx5e_update_sw_counters(struct mlx5e_priv *priv)
                s->rx_lro_bytes += rq_stats->lro_bytes;
                s->rx_csum_none += rq_stats->csum_none;
                s->rx_csum_complete += rq_stats->csum_complete;
+               s->rx_csum_unnecessary += rq_stats->csum_unnecessary;
                s->rx_csum_unnecessary_inner += rq_stats->csum_unnecessary_inner;
                s->rx_xdp_drop += rq_stats->xdp_drop;
                s->rx_xdp_tx += rq_stats->xdp_tx;
@@ -229,14 +229,11 @@ static void mlx5e_update_sw_counters(struct mlx5e_priv *priv)
                        s->tx_queue_dropped     += sq_stats->dropped;
                        s->tx_xmit_more         += sq_stats->xmit_more;
                        s->tx_csum_partial_inner += sq_stats->csum_partial_inner;
-                       tx_offload_none         += sq_stats->csum_none;
+                       s->tx_csum_none         += sq_stats->csum_none;
+                       s->tx_csum_partial      += sq_stats->csum_partial;
                }
        }
 
-       /* Update calculated offload counters */
-       s->tx_csum_partial = s->tx_packets - tx_offload_none - s->tx_csum_partial_inner;
-       s->rx_csum_unnecessary = s->rx_packets - s->rx_csum_none - s->rx_csum_complete;
-
        s->link_down_events_phy = MLX5_GET(ppcnt_reg,
                                priv->stats.pport.phy_counters,
                                counter_set.phys_layer_cntrs.link_down_events);
@@ -3333,8 +3330,8 @@ static int mlx5e_handle_feature(struct net_device *netdev,
 
        err = feature_handler(netdev, enable);
        if (err) {
-               netdev_err(netdev, "%s feature 0x%llx failed err %d\n",
-                          enable ? "Enable" : "Disable", feature, err);
+               netdev_err(netdev, "%s feature %pNF failed, err %d\n",
+                          enable ? "Enable" : "Disable", &feature, err);
                return err;
        }
 
index f1dd638..15a1687 100644 (file)
@@ -627,6 +627,7 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
 
        if (lro) {
                skb->ip_summed = CHECKSUM_UNNECESSARY;
+               rq->stats.csum_unnecessary++;
                return;
        }
 
@@ -644,7 +645,9 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
                        skb->csum_level = 1;
                        skb->encapsulation = 1;
                        rq->stats.csum_unnecessary_inner++;
+                       return;
                }
+               rq->stats.csum_unnecessary++;
                return;
        }
 csum_none:
index 6d199ff..f863721 100644 (file)
@@ -68,6 +68,7 @@ struct mlx5e_sw_stats {
        u64 rx_xdp_drop;
        u64 rx_xdp_tx;
        u64 rx_xdp_tx_full;
+       u64 tx_csum_none;
        u64 tx_csum_partial;
        u64 tx_csum_partial_inner;
        u64 tx_queue_stopped;
@@ -108,6 +109,7 @@ static const struct counter_desc sw_stats_desc[] = {
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_drop) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_full) },
+       { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_none) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_partial) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_partial_inner) },
        { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_queue_stopped) },
@@ -339,6 +341,7 @@ struct mlx5e_rq_stats {
        u64 packets;
        u64 bytes;
        u64 csum_complete;
+       u64 csum_unnecessary;
        u64 csum_unnecessary_inner;
        u64 csum_none;
        u64 lro_packets;
@@ -363,6 +366,7 @@ static const struct counter_desc rq_stats_desc[] = {
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, packets) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, bytes) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, csum_complete) },
+       { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, csum_unnecessary) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, csum_unnecessary_inner) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, csum_none) },
        { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, xdp_drop) },
@@ -392,6 +396,7 @@ struct mlx5e_sq_stats {
        u64 tso_bytes;
        u64 tso_inner_packets;
        u64 tso_inner_bytes;
+       u64 csum_partial;
        u64 csum_partial_inner;
        u64 nop;
        /* less likely accessed in data path */
@@ -408,6 +413,7 @@ static const struct counter_desc sq_stats_desc[] = {
        { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tso_bytes) },
        { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tso_inner_packets) },
        { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tso_inner_bytes) },
+       { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, csum_partial) },
        { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, csum_partial_inner) },
        { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, nop) },
        { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, csum_none) },
index da503e6..1aa2028 100644 (file)
@@ -1317,6 +1317,69 @@ static bool csum_offload_supported(struct mlx5e_priv *priv, u32 action, u32 upda
        return true;
 }
 
+static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
+                                         struct tcf_exts *exts)
+{
+       const struct tc_action *a;
+       bool modify_ip_header;
+       LIST_HEAD(actions);
+       u8 htype, ip_proto;
+       void *headers_v;
+       u16 ethertype;
+       int nkeys, i;
+
+       headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
+       ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype);
+
+       /* for non-IP we only re-write MACs, so we're okay */
+       if (ethertype != ETH_P_IP && ethertype != ETH_P_IPV6)
+               goto out_ok;
+
+       modify_ip_header = false;
+       tcf_exts_to_list(exts, &actions);
+       list_for_each_entry(a, &actions, list) {
+               if (!is_tcf_pedit(a))
+                       continue;
+
+               nkeys = tcf_pedit_nkeys(a);
+               for (i = 0; i < nkeys; i++) {
+                       htype = tcf_pedit_htype(a, i);
+                       if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 ||
+                           htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP6) {
+                               modify_ip_header = true;
+                               break;
+                       }
+               }
+       }
+
+       ip_proto = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ip_protocol);
+       if (modify_ip_header && ip_proto != IPPROTO_TCP && ip_proto != IPPROTO_UDP) {
+               pr_info("can't offload re-write of ip proto %d\n", ip_proto);
+               return false;
+       }
+
+out_ok:
+       return true;
+}
+
+static bool actions_match_supported(struct mlx5e_priv *priv,
+                                   struct tcf_exts *exts,
+                                   struct mlx5e_tc_flow_parse_attr *parse_attr,
+                                   struct mlx5e_tc_flow *flow)
+{
+       u32 actions;
+
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
+               actions = flow->esw_attr->action;
+       else
+               actions = flow->nic_attr->action;
+
+       if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
+               return modify_header_match_supported(&parse_attr->spec, exts);
+
+       return true;
+}
+
 static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                                struct mlx5e_tc_flow_parse_attr *parse_attr,
                                struct mlx5e_tc_flow *flow)
@@ -1378,6 +1441,9 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                return -EINVAL;
        }
 
+       if (!actions_match_supported(priv, exts, parse_attr, flow))
+               return -EOPNOTSUPP;
+
        return 0;
 }
 
@@ -1564,7 +1630,7 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
                break;
        default:
                err = -EOPNOTSUPP;
-               goto out;
+               goto free_encap;
        }
        fl4.flowi4_tos = tun_key->tos;
        fl4.daddr = tun_key->u.ipv4.dst;
@@ -1573,7 +1639,7 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
        err = mlx5e_route_lookup_ipv4(priv, mirred_dev, &out_dev,
                                      &fl4, &n, &ttl);
        if (err)
-               goto out;
+               goto free_encap;
 
        /* used by mlx5e_detach_encap to lookup a neigh hash table
         * entry in the neigh hash table when a user deletes a rule
@@ -1590,7 +1656,7 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
         */
        err = mlx5e_rep_encap_entry_attach(netdev_priv(out_dev), e);
        if (err)
-               goto out;
+               goto free_encap;
 
        read_lock_bh(&n->lock);
        nud_state = n->nud_state;
@@ -1630,8 +1696,9 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
 
 destroy_neigh_entry:
        mlx5e_rep_encap_entry_detach(netdev_priv(e->out_dev), e);
-out:
+free_encap:
        kfree(encap_header);
+out:
        if (n)
                neigh_release(n);
        return err;
@@ -1668,7 +1735,7 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv,
                break;
        default:
                err = -EOPNOTSUPP;
-               goto out;
+               goto free_encap;
        }
 
        fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tun_key->tos), tun_key->label);
@@ -1678,7 +1745,7 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv,
        err = mlx5e_route_lookup_ipv6(priv, mirred_dev, &out_dev,
                                      &fl6, &n, &ttl);
        if (err)
-               goto out;
+               goto free_encap;
 
        /* used by mlx5e_detach_encap to lookup a neigh hash table
         * entry in the neigh hash table when a user deletes a rule
@@ -1695,7 +1762,7 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv,
         */
        err = mlx5e_rep_encap_entry_attach(netdev_priv(out_dev), e);
        if (err)
-               goto out;
+               goto free_encap;
 
        read_lock_bh(&n->lock);
        nud_state = n->nud_state;
@@ -1736,8 +1803,9 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv,
 
 destroy_neigh_entry:
        mlx5e_rep_encap_entry_detach(netdev_priv(e->out_dev), e);
-out:
+free_encap:
        kfree(encap_header);
+out:
        if (n)
                neigh_release(n);
        return err;
@@ -1791,6 +1859,7 @@ vxlan_encap_offload_err:
                }
        }
 
+       /* must verify if encap is valid or not */
        if (found)
                goto attach_flow;
 
@@ -1817,6 +1886,8 @@ attach_flow:
        *encap_dev = e->out_dev;
        if (e->flags & MLX5_ENCAP_ENTRY_VALID)
                attr->encap_id = e->encap_id;
+       else
+               err = -EAGAIN;
 
        return err;
 
@@ -1934,6 +2005,10 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
 
                return -EINVAL;
        }
+
+       if (!actions_match_supported(priv, exts, parse_attr, flow))
+               return -EOPNOTSUPP;
+
        return err;
 }
 
index fee43e4..1d6925d 100644 (file)
@@ -193,6 +193,7 @@ mlx5e_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb, struct
                        sq->stats.csum_partial_inner++;
                } else {
                        eseg->cs_flags |= MLX5_ETH_WQE_L4_CSUM;
+                       sq->stats.csum_partial++;
                }
        } else
                sq->stats.csum_none++;
index e37453d..c0fd221 100644 (file)
@@ -71,11 +71,11 @@ int mlx5_fpga_access_reg(struct mlx5_core_dev *dev, u8 size, u64 addr,
        return 0;
 }
 
-int mlx5_fpga_caps(struct mlx5_core_dev *dev, u32 *caps)
+int mlx5_fpga_caps(struct mlx5_core_dev *dev)
 {
        u32 in[MLX5_ST_SZ_DW(fpga_cap)] = {0};
 
-       return mlx5_core_access_reg(dev, in, sizeof(in), caps,
+       return mlx5_core_access_reg(dev, in, sizeof(in), dev->caps.fpga,
                                    MLX5_ST_SZ_BYTES(fpga_cap),
                                    MLX5_REG_FPGA_CAP, 0, 0);
 }
index 94bdfd4..d05233c 100644 (file)
@@ -65,7 +65,7 @@ struct mlx5_fpga_qp_counters {
        u64 rx_total_drop;
 };
 
-int mlx5_fpga_caps(struct mlx5_core_dev *dev, u32 *caps);
+int mlx5_fpga_caps(struct mlx5_core_dev *dev);
 int mlx5_fpga_query(struct mlx5_core_dev *dev, struct mlx5_fpga_query *query);
 int mlx5_fpga_ctrl_op(struct mlx5_core_dev *dev, u8 op);
 int mlx5_fpga_access_reg(struct mlx5_core_dev *dev, u8 size, u64 addr,
index 9034e99..dc89703 100644 (file)
@@ -139,8 +139,7 @@ int mlx5_fpga_device_start(struct mlx5_core_dev *mdev)
        if (err)
                goto out;
 
-       err = mlx5_fpga_caps(fdev->mdev,
-                            fdev->mdev->caps.hca_cur[MLX5_CAP_FPGA]);
+       err = mlx5_fpga_caps(fdev->mdev);
        if (err)
                goto out;
 
index e0d0efd..36ecc2b 100644 (file)
@@ -293,6 +293,9 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
        }
 
        if (fte->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
+               int max_list_size = BIT(MLX5_CAP_FLOWTABLE_TYPE(dev,
+                                       log_max_flow_counter,
+                                       ft->type));
                int list_size = 0;
 
                list_for_each_entry(dst, &fte->node.children, node.list) {
@@ -305,12 +308,17 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
                        in_dests += MLX5_ST_SZ_BYTES(dest_format_struct);
                        list_size++;
                }
+               if (list_size > max_list_size) {
+                       err = -EINVAL;
+                       goto err_out;
+               }
 
                MLX5_SET(flow_context, in_flow_context, flow_counter_list_size,
                         list_size);
        }
 
        err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
+err_out:
        kvfree(in);
        return err;
 }
index 5509a75..48dd789 100644 (file)
@@ -52,6 +52,7 @@ enum fs_flow_table_type {
        FS_FT_FDB             = 0X4,
        FS_FT_SNIFFER_RX        = 0X5,
        FS_FT_SNIFFER_TX        = 0X6,
+       FS_FT_MAX_TYPE = FS_FT_SNIFFER_TX,
 };
 
 enum fs_flow_table_op_mod {
@@ -260,4 +261,14 @@ void mlx5_cleanup_fs(struct mlx5_core_dev *dev);
 #define fs_for_each_dst(pos, fte)                      \
        fs_list_for_each_entry(pos, &(fte)->node.children)
 
+#define MLX5_CAP_FLOWTABLE_TYPE(mdev, cap, type) (             \
+       (type == FS_FT_NIC_RX) ? MLX5_CAP_FLOWTABLE_NIC_RX(mdev, cap) :         \
+       (type == FS_FT_ESW_EGRESS_ACL) ? MLX5_CAP_ESW_EGRESS_ACL(mdev, cap) :           \
+       (type == FS_FT_ESW_INGRESS_ACL) ? MLX5_CAP_ESW_INGRESS_ACL(mdev, cap) :         \
+       (type == FS_FT_FDB) ? MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, cap) :           \
+       (type == FS_FT_SNIFFER_RX) ? MLX5_CAP_FLOWTABLE_SNIFFER_RX(mdev, cap) :         \
+       (type == FS_FT_SNIFFER_TX) ? MLX5_CAP_FLOWTABLE_SNIFFER_TX(mdev, cap) :         \
+       (BUILD_BUG_ON_ZERO(FS_FT_SNIFFER_TX != FS_FT_MAX_TYPE))\
+       )
+
 #endif
index 8529805..145e392 100644 (file)
@@ -572,12 +572,13 @@ void mlx5_rdma_netdev_free(struct net_device *netdev)
 {
        struct mlx5e_priv          *priv    = mlx5i_epriv(netdev);
        const struct mlx5e_profile *profile = priv->profile;
+       struct mlx5_core_dev       *mdev    = priv->mdev;
 
        mlx5e_detach_netdev(priv);
        profile->cleanup(priv);
        destroy_workqueue(priv->wq);
        free_netdev(netdev);
 
-       mlx5e_destroy_mdev_resources(priv->mdev);
+       mlx5e_destroy_mdev_resources(mdev);
 }
 EXPORT_SYMBOL(mlx5_rdma_netdev_free);
index 6c48e99..2a8b529 100644 (file)
@@ -109,7 +109,7 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs)
                                mlx5_core_warn(dev,
                                               "failed to restore VF %d settings, err %d\n",
                                               vf, err);
-                       continue;
+                               continue;
                        }
                }
                mlx5_core_dbg(dev, "successfully enabled VF* %d\n", vf);
index 2cfb3f5..032089e 100644 (file)
@@ -2723,6 +2723,7 @@ static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp,
                mlxsw_sp_nexthop_rif_fini(nh);
                break;
        case MLXSW_SP_NEXTHOP_TYPE_IPIP:
+               mlxsw_sp_nexthop_rif_fini(nh);
                mlxsw_sp_nexthop_ipip_fini(mlxsw_sp, nh);
                break;
        }
@@ -2742,7 +2743,11 @@ static int mlxsw_sp_nexthop4_type_init(struct mlxsw_sp *mlxsw_sp,
            router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, dev,
                                                     MLXSW_SP_L3_PROTO_IPV4)) {
                nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP;
-               return mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev);
+               err = mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev);
+               if (err)
+                       return err;
+               mlxsw_sp_nexthop_rif_init(nh, &nh->ipip_entry->ol_lb->common);
+               return 0;
        }
 
        nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
@@ -4009,7 +4014,11 @@ static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp,
            router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, dev,
                                                     MLXSW_SP_L3_PROTO_IPV6)) {
                nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP;
-               return mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev);
+               err = mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev);
+               if (err)
+                       return err;
+               mlxsw_sp_nexthop_rif_init(nh, &nh->ipip_entry->ol_lb->common);
+               return 0;
        }
 
        nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH;
@@ -5068,6 +5077,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
        vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN);
        if (IS_ERR(vr))
                return ERR_CAST(vr);
+       vr->rif_count++;
 
        err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index);
        if (err)
@@ -5099,7 +5109,6 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
 
        mlxsw_sp_rif_counters_alloc(rif);
        mlxsw_sp->router->rifs[rif_index] = rif;
-       vr->rif_count++;
 
        return rif;
 
@@ -5110,6 +5119,7 @@ err_fid_get:
        kfree(rif);
 err_rif_alloc:
 err_rif_index_alloc:
+       vr->rif_count--;
        mlxsw_sp_vr_put(vr);
        return ERR_PTR(err);
 }
@@ -5124,7 +5134,6 @@ void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
        mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
        vr = &mlxsw_sp->router->vrs[rif->vr_id];
 
-       vr->rif_count--;
        mlxsw_sp->router->rifs[rif->rif_index] = NULL;
        mlxsw_sp_rif_counters_free(rif);
        ops->deconfigure(rif);
@@ -5132,6 +5141,7 @@ void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
                /* Loopback RIFs are not associated with a FID. */
                mlxsw_sp_fid_put(fid);
        kfree(rif);
+       vr->rif_count--;
        mlxsw_sp_vr_put(vr);
 }
 
index 0ea3ca0..3ed9033 100644 (file)
@@ -898,7 +898,8 @@ static void emac_mac_rx_descs_refill(struct emac_adapter *adpt,
 
                curr_rxbuf->dma_addr =
                        dma_map_single(adpt->netdev->dev.parent, skb->data,
-                                      curr_rxbuf->length, DMA_FROM_DEVICE);
+                                      adpt->rxbuf_size, DMA_FROM_DEVICE);
+
                ret = dma_mapping_error(adpt->netdev->dev.parent,
                                        curr_rxbuf->dma_addr);
                if (ret) {
index 98f2255..1e33aea 100644 (file)
@@ -51,10 +51,7 @@ struct rmnet_walk_data {
 
 static int rmnet_is_real_dev_registered(const struct net_device *real_dev)
 {
-       rx_handler_func_t *rx_handler;
-
-       rx_handler = rcu_dereference(real_dev->rx_handler);
-       return (rx_handler == rmnet_rx_handler);
+       return rcu_access_pointer(real_dev->rx_handler) == rmnet_rx_handler;
 }
 
 /* Needs rtnl lock */
index a63ef82..dfae3c9 100644 (file)
@@ -139,40 +139,52 @@ rocker_tlv_start(struct rocker_desc_info *desc_info)
 int rocker_tlv_put(struct rocker_desc_info *desc_info,
                   int attrtype, int attrlen, const void *data);
 
-static inline int rocker_tlv_put_u8(struct rocker_desc_info *desc_info,
-                                   int attrtype, u8 value)
+static inline int
+rocker_tlv_put_u8(struct rocker_desc_info *desc_info, int attrtype, u8 value)
 {
-       return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &value);
+       u8 tmp = value; /* work around GCC PR81715 */
+
+       return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &tmp);
 }
 
-static inline int rocker_tlv_put_u16(struct rocker_desc_info *desc_info,
-                                    int attrtype, u16 value)
+static inline int
+rocker_tlv_put_u16(struct rocker_desc_info *desc_info, int attrtype, u16 value)
 {
-       return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &value);
+       u16 tmp = value;
+
+       return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &tmp);
 }
 
-static inline int rocker_tlv_put_be16(struct rocker_desc_info *desc_info,
-                                     int attrtype, __be16 value)
+static inline int
+rocker_tlv_put_be16(struct rocker_desc_info *desc_info, int attrtype, __be16 value)
 {
-       return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &value);
+       __be16 tmp = value;
+
+       return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &tmp);
 }
 
-static inline int rocker_tlv_put_u32(struct rocker_desc_info *desc_info,
-                                    int attrtype, u32 value)
+static inline int
+rocker_tlv_put_u32(struct rocker_desc_info *desc_info, int attrtype, u32 value)
 {
-       return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &value);
+       u32 tmp = value;
+
+       return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &tmp);
 }
 
-static inline int rocker_tlv_put_be32(struct rocker_desc_info *desc_info,
-                                     int attrtype, __be32 value)
+static inline int
+rocker_tlv_put_be32(struct rocker_desc_info *desc_info, int attrtype, __be32 value)
 {
-       return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &value);
+       __be32 tmp = value;
+
+       return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &tmp);
 }
 
-static inline int rocker_tlv_put_u64(struct rocker_desc_info *desc_info,
-                                    int attrtype, u64 value)
+static inline int
+rocker_tlv_put_u64(struct rocker_desc_info *desc_info, int attrtype, u64 value)
 {
-       return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &value);
+       u64 tmp = value;
+
+       return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &tmp);
 }
 
 static inline struct rocker_tlv *
index dd6a2f9..5efef80 100644 (file)
@@ -511,6 +511,7 @@ static struct platform_driver dwc_eth_dwmac_driver = {
        .remove = dwc_eth_dwmac_remove,
        .driver = {
                .name           = "dwc-eth-dwmac",
+               .pm             = &stmmac_pltfr_pm_ops,
                .of_match_table = dwc_eth_dwmac_match,
        },
 };
index 99823f5..13133b3 100644 (file)
@@ -83,6 +83,117 @@ struct rk_priv_data {
        (((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \
         ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE))
 
+#define RK3128_GRF_MAC_CON0    0x0168
+#define RK3128_GRF_MAC_CON1    0x016c
+
+/* RK3128_GRF_MAC_CON0 */
+#define RK3128_GMAC_TXCLK_DLY_ENABLE   GRF_BIT(14)
+#define RK3128_GMAC_TXCLK_DLY_DISABLE  GRF_CLR_BIT(14)
+#define RK3128_GMAC_RXCLK_DLY_ENABLE   GRF_BIT(15)
+#define RK3128_GMAC_RXCLK_DLY_DISABLE  GRF_CLR_BIT(15)
+#define RK3128_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7)
+#define RK3128_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
+
+/* RK3128_GRF_MAC_CON1 */
+#define RK3128_GMAC_PHY_INTF_SEL_RGMII \
+               (GRF_BIT(6) | GRF_CLR_BIT(7) | GRF_CLR_BIT(8))
+#define RK3128_GMAC_PHY_INTF_SEL_RMII  \
+               (GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | GRF_BIT(8))
+#define RK3128_GMAC_FLOW_CTRL          GRF_BIT(9)
+#define RK3128_GMAC_FLOW_CTRL_CLR      GRF_CLR_BIT(9)
+#define RK3128_GMAC_SPEED_10M          GRF_CLR_BIT(10)
+#define RK3128_GMAC_SPEED_100M         GRF_BIT(10)
+#define RK3128_GMAC_RMII_CLK_25M       GRF_BIT(11)
+#define RK3128_GMAC_RMII_CLK_2_5M      GRF_CLR_BIT(11)
+#define RK3128_GMAC_CLK_125M           (GRF_CLR_BIT(12) | GRF_CLR_BIT(13))
+#define RK3128_GMAC_CLK_25M            (GRF_BIT(12) | GRF_BIT(13))
+#define RK3128_GMAC_CLK_2_5M           (GRF_CLR_BIT(12) | GRF_BIT(13))
+#define RK3128_GMAC_RMII_MODE          GRF_BIT(14)
+#define RK3128_GMAC_RMII_MODE_CLR      GRF_CLR_BIT(14)
+
+static void rk3128_set_to_rgmii(struct rk_priv_data *bsp_priv,
+                               int tx_delay, int rx_delay)
+{
+       struct device *dev = &bsp_priv->pdev->dev;
+
+       if (IS_ERR(bsp_priv->grf)) {
+               dev_err(dev, "Missing rockchip,grf property\n");
+               return;
+       }
+
+       regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
+                    RK3128_GMAC_PHY_INTF_SEL_RGMII |
+                    RK3128_GMAC_RMII_MODE_CLR);
+       regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON0,
+                    DELAY_ENABLE(RK3128, tx_delay, rx_delay) |
+                    RK3128_GMAC_CLK_RX_DL_CFG(rx_delay) |
+                    RK3128_GMAC_CLK_TX_DL_CFG(tx_delay));
+}
+
+static void rk3128_set_to_rmii(struct rk_priv_data *bsp_priv)
+{
+       struct device *dev = &bsp_priv->pdev->dev;
+
+       if (IS_ERR(bsp_priv->grf)) {
+               dev_err(dev, "Missing rockchip,grf property\n");
+               return;
+       }
+
+       regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
+                    RK3128_GMAC_PHY_INTF_SEL_RMII | RK3128_GMAC_RMII_MODE);
+}
+
+static void rk3128_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+       struct device *dev = &bsp_priv->pdev->dev;
+
+       if (IS_ERR(bsp_priv->grf)) {
+               dev_err(dev, "Missing rockchip,grf property\n");
+               return;
+       }
+
+       if (speed == 10)
+               regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
+                            RK3128_GMAC_CLK_2_5M);
+       else if (speed == 100)
+               regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
+                            RK3128_GMAC_CLK_25M);
+       else if (speed == 1000)
+               regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
+                            RK3128_GMAC_CLK_125M);
+       else
+               dev_err(dev, "unknown speed value for RGMII! speed=%d", speed);
+}
+
+static void rk3128_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+       struct device *dev = &bsp_priv->pdev->dev;
+
+       if (IS_ERR(bsp_priv->grf)) {
+               dev_err(dev, "Missing rockchip,grf property\n");
+               return;
+       }
+
+       if (speed == 10) {
+               regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
+                            RK3128_GMAC_RMII_CLK_2_5M |
+                            RK3128_GMAC_SPEED_10M);
+       } else if (speed == 100) {
+               regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1,
+                            RK3128_GMAC_RMII_CLK_25M |
+                            RK3128_GMAC_SPEED_100M);
+       } else {
+               dev_err(dev, "unknown speed value for RMII! speed=%d", speed);
+       }
+}
+
+static const struct rk_gmac_ops rk3128_ops = {
+       .set_to_rgmii = rk3128_set_to_rgmii,
+       .set_to_rmii = rk3128_set_to_rmii,
+       .set_rgmii_speed = rk3128_set_rgmii_speed,
+       .set_rmii_speed = rk3128_set_rmii_speed,
+};
+
 #define RK3228_GRF_MAC_CON0    0x0900
 #define RK3228_GRF_MAC_CON1    0x0904
 
@@ -1313,6 +1424,7 @@ static int rk_gmac_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(rk_gmac_pm_ops, rk_gmac_suspend, rk_gmac_resume);
 
 static const struct of_device_id rk_gmac_dwmac_match[] = {
+       { .compatible = "rockchip,rk3128-gmac", .data = &rk3128_ops },
        { .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops },
        { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops },
        { .compatible = "rockchip,rk3328-gmac", .data = &rk3328_ops },
index c4407e8..2f7d7ec 100644 (file)
@@ -296,6 +296,7 @@ static void dwmac4_pmt(struct mac_device_info *hw, unsigned long mode)
 {
        void __iomem *ioaddr = hw->pcsr;
        unsigned int pmt = 0;
+       u32 config;
 
        if (mode & WAKE_MAGIC) {
                pr_debug("GMAC: WOL Magic frame\n");
@@ -306,6 +307,12 @@ static void dwmac4_pmt(struct mac_device_info *hw, unsigned long mode)
                pmt |= power_down | global_unicast | wake_up_frame_en;
        }
 
+       if (pmt) {
+               /* The receiver must be enabled for WOL before powering down */
+               config = readl(ioaddr + GMAC_CONFIG);
+               config |= GMAC_CONFIG_RE;
+               writel(config, ioaddr + GMAC_CONFIG);
+       }
        writel(pmt, ioaddr + GMAC_PMT);
 }
 
index a404552..c3f77e3 100644 (file)
@@ -120,7 +120,7 @@ struct ppp {
        int             n_channels;     /* how many channels are attached 54 */
        spinlock_t      rlock;          /* lock for receive side 58 */
        spinlock_t      wlock;          /* lock for transmit side 5c */
-       int             *xmit_recursion __percpu; /* xmit recursion detect */
+       int __percpu    *xmit_recursion; /* xmit recursion detect */
        int             mru;            /* max receive unit 60 */
        unsigned int    flags;          /* control bits 64 */
        unsigned int    xstate;         /* transmit state bits 68 */
index 3c9985f..5ce580f 100644 (file)
@@ -1496,11 +1496,13 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
        switch (tun->flags & TUN_TYPE_MASK) {
        case IFF_TUN:
                if (tun->flags & IFF_NO_PI) {
-                       switch (skb->data[0] & 0xf0) {
-                       case 0x40:
+                       u8 ip_version = skb->len ? (skb->data[0] >> 4) : 0;
+
+                       switch (ip_version) {
+                       case 4:
                                pi.proto = htons(ETH_P_IP);
                                break;
-                       case 0x60:
+                       case 6:
                                pi.proto = htons(ETH_P_IPV6);
                                break;
                        default:
index 8ab281b..29c7e2e 100644 (file)
@@ -54,11 +54,19 @@ static int is_wireless_rndis(struct usb_interface_descriptor *desc)
                desc->bInterfaceProtocol == 3);
 }
 
+static int is_novatel_rndis(struct usb_interface_descriptor *desc)
+{
+       return (desc->bInterfaceClass == USB_CLASS_MISC &&
+               desc->bInterfaceSubClass == 4 &&
+               desc->bInterfaceProtocol == 1);
+}
+
 #else
 
 #define is_rndis(desc)         0
 #define is_activesync(desc)    0
 #define is_wireless_rndis(desc)        0
+#define is_novatel_rndis(desc) 0
 
 #endif
 
@@ -150,7 +158,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
         */
        rndis = (is_rndis(&intf->cur_altsetting->desc) ||
                 is_activesync(&intf->cur_altsetting->desc) ||
-                is_wireless_rndis(&intf->cur_altsetting->desc));
+                is_wireless_rndis(&intf->cur_altsetting->desc) ||
+                is_novatel_rndis(&intf->cur_altsetting->desc));
 
        memset(info, 0, sizeof(*info));
        info->control = intf;
@@ -547,6 +556,7 @@ static const struct driver_info wwan_info = {
 #define REALTEK_VENDOR_ID      0x0bda
 #define SAMSUNG_VENDOR_ID      0x04e8
 #define LENOVO_VENDOR_ID       0x17ef
+#define LINKSYS_VENDOR_ID      0x13b1
 #define NVIDIA_VENDOR_ID       0x0955
 #define HP_VENDOR_ID           0x03f0
 #define MICROSOFT_VENDOR_ID    0x045e
@@ -737,6 +747,15 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+#if IS_ENABLED(CONFIG_USB_RTL8152)
+/* Linksys USB3GIGV1 Ethernet Adapter */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(LINKSYS_VENDOR_ID, 0x0041, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+#endif
+
 /* ThinkPad USB-C Dock (based on Realtek RTL8153) */
 {
        USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM,
index ceb78e2..941ece0 100644 (file)
@@ -613,6 +613,7 @@ enum rtl8152_flags {
 #define VENDOR_ID_MICROSOFT            0x045e
 #define VENDOR_ID_SAMSUNG              0x04e8
 #define VENDOR_ID_LENOVO               0x17ef
+#define VENDOR_ID_LINKSYS              0x13b1
 #define VENDOR_ID_NVIDIA               0x0955
 
 #define MCU_TYPE_PLA                   0x0100
@@ -5316,6 +5317,7 @@ static const struct usb_device_id rtl8152_table[] = {
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7205)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x720c)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7214)},
+       {REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)},
        {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA,  0x09ff)},
        {}
 };
index a151f26..b807c91 100644 (file)
@@ -632,6 +632,10 @@ static const struct usb_device_id  products [] = {
        /* RNDIS for tethering */
        USB_INTERFACE_INFO(USB_CLASS_WIRELESS_CONTROLLER, 1, 3),
        .driver_info = (unsigned long) &rndis_info,
+}, {
+       /* Novatel Verizon USB730L */
+       USB_INTERFACE_INFO(USB_CLASS_MISC, 4, 1),
+       .driver_info = (unsigned long) &rndis_info,
 },
        { },            // END
 };
index bc16339..195dafb 100644 (file)
@@ -3396,9 +3396,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
 
 MODULE_DEVICE_TABLE(pci, ath10k_pci_id_table);
 
-#ifdef CONFIG_PM
-
-static int ath10k_pci_pm_suspend(struct device *dev)
+static __maybe_unused int ath10k_pci_pm_suspend(struct device *dev)
 {
        struct ath10k *ar = dev_get_drvdata(dev);
        int ret;
@@ -3414,7 +3412,7 @@ static int ath10k_pci_pm_suspend(struct device *dev)
        return ret;
 }
 
-static int ath10k_pci_pm_resume(struct device *dev)
+static __maybe_unused int ath10k_pci_pm_resume(struct device *dev)
 {
        struct ath10k *ar = dev_get_drvdata(dev);
        int ret;
@@ -3433,7 +3431,6 @@ static int ath10k_pci_pm_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(ath10k_pci_pm_ops,
                         ath10k_pci_pm_suspend,
                         ath10k_pci_pm_resume);
-#endif
 
 static struct pci_driver ath10k_pci_driver = {
        .name = "ath10k_pci",
index aaed4ab..4157c90 100644 (file)
@@ -980,7 +980,7 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
 
        eth_broadcast_addr(params_le->bssid);
        params_le->bss_type = DOT11_BSSTYPE_ANY;
-       params_le->scan_type = 0;
+       params_le->scan_type = BRCMF_SCANTYPE_ACTIVE;
        params_le->channel_num = 0;
        params_le->nprobes = cpu_to_le32(-1);
        params_le->active_time = cpu_to_le32(-1);
@@ -988,12 +988,9 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
        params_le->home_time = cpu_to_le32(-1);
        memset(&params_le->ssid_le, 0, sizeof(params_le->ssid_le));
 
-       /* if request is null exit so it will be all channel broadcast scan */
-       if (!request)
-               return;
-
        n_ssids = request->n_ssids;
        n_channels = request->n_channels;
+
        /* Copy channel array if applicable */
        brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n",
                  n_channels);
@@ -1030,16 +1027,8 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
                        ptr += sizeof(ssid_le);
                }
        } else {
-               brcmf_dbg(SCAN, "Broadcast scan %p\n", request->ssids);
-               if ((request->ssids) && request->ssids->ssid_len) {
-                       brcmf_dbg(SCAN, "SSID %s len=%d\n",
-                                 params_le->ssid_le.SSID,
-                                 request->ssids->ssid_len);
-                       params_le->ssid_le.SSID_len =
-                               cpu_to_le32(request->ssids->ssid_len);
-                       memcpy(&params_le->ssid_le.SSID, request->ssids->ssid,
-                               request->ssids->ssid_len);
-               }
+               brcmf_dbg(SCAN, "Performing passive scan\n");
+               params_le->scan_type = BRCMF_SCANTYPE_PASSIVE;
        }
        /* Adding mask to channel numbers */
        params_le->channel_num =
@@ -3162,6 +3151,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
        struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
        s32 status;
        struct brcmf_escan_result_le *escan_result_le;
+       u32 escan_buflen;
        struct brcmf_bss_info_le *bss_info_le;
        struct brcmf_bss_info_le *bss = NULL;
        u32 bi_length;
@@ -3181,11 +3171,23 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
 
        if (status == BRCMF_E_STATUS_PARTIAL) {
                brcmf_dbg(SCAN, "ESCAN Partial result\n");
+               if (e->datalen < sizeof(*escan_result_le)) {
+                       brcmf_err("invalid event data length\n");
+                       goto exit;
+               }
                escan_result_le = (struct brcmf_escan_result_le *) data;
                if (!escan_result_le) {
                        brcmf_err("Invalid escan result (NULL pointer)\n");
                        goto exit;
                }
+               escan_buflen = le32_to_cpu(escan_result_le->buflen);
+               if (escan_buflen > BRCMF_ESCAN_BUF_SIZE ||
+                   escan_buflen > e->datalen ||
+                   escan_buflen < sizeof(*escan_result_le)) {
+                       brcmf_err("Invalid escan buffer length: %d\n",
+                                 escan_buflen);
+                       goto exit;
+               }
                if (le16_to_cpu(escan_result_le->bss_count) != 1) {
                        brcmf_err("Invalid bss_count %d: ignoring\n",
                                  escan_result_le->bss_count);
@@ -3202,9 +3204,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
                }
 
                bi_length = le32_to_cpu(bss_info_le->length);
-               if (bi_length != (le32_to_cpu(escan_result_le->buflen) -
-                                       WL_ESCAN_RESULTS_FIXED_SIZE)) {
-                       brcmf_err("Invalid bss_info length %d: ignoring\n",
+               if (bi_length != escan_buflen - WL_ESCAN_RESULTS_FIXED_SIZE) {
+                       brcmf_err("Ignoring invalid bss_info length: %d\n",
                                  bi_length);
                        goto exit;
                }
index 8391989..e0d22fe 100644 (file)
 #define BRCMF_SCAN_PARAMS_COUNT_MASK   0x0000ffff
 #define BRCMF_SCAN_PARAMS_NSSID_SHIFT  16
 
+/* scan type definitions */
+#define BRCMF_SCANTYPE_DEFAULT         0xFF
+#define BRCMF_SCANTYPE_ACTIVE          0
+#define BRCMF_SCANTYPE_PASSIVE         1
+
 #define BRCMF_WSEC_MAX_PSK_LEN         32
 #define        BRCMF_WSEC_PASSPHRASE           BIT(0)
 
index 5de19ea..b205a7b 100644 (file)
@@ -2167,7 +2167,7 @@ out:
         * 1. We are not using a unified image
         * 2. We are using a unified image but had an error while exiting D3
         */
-       set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
+       set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
        set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status);
        /*
         * When switching images we return 1, which causes mac80211
index 15f2d82..3bcaa82 100644 (file)
@@ -1546,6 +1546,11 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac,
        struct iwl_mvm_mc_iter_data *data = _data;
        struct iwl_mvm *mvm = data->mvm;
        struct iwl_mcast_filter_cmd *cmd = mvm->mcast_filter_cmd;
+       struct iwl_host_cmd hcmd = {
+               .id = MCAST_FILTER_CMD,
+               .flags = CMD_ASYNC,
+               .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
+       };
        int ret, len;
 
        /* if we don't have free ports, mcast frames will be dropped */
@@ -1560,7 +1565,10 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac,
        memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN);
        len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4);
 
-       ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd);
+       hcmd.len[0] = len;
+       hcmd.data[0] = cmd;
+
+       ret = iwl_mvm_send_cmd(mvm, &hcmd);
        if (ret)
                IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret);
 }
@@ -1635,6 +1643,12 @@ static void iwl_mvm_configure_filter(struct ieee80211_hw *hw,
        if (!cmd)
                goto out;
 
+       if (changed_flags & FIF_ALLMULTI)
+               cmd->pass_all = !!(*total_flags & FIF_ALLMULTI);
+
+       if (cmd->pass_all)
+               cmd->count = 0;
+
        iwl_mvm_recalc_multicast(mvm);
 out:
        mutex_unlock(&mvm->mutex);
@@ -2563,7 +2577,7 @@ static void iwl_mvm_purge_deferred_tx_frames(struct iwl_mvm *mvm,
                         * queues, so we should never get a second deferred
                         * frame for the RA/TID.
                         */
-                       iwl_mvm_start_mac_queues(mvm, info->hw_queue);
+                       iwl_mvm_start_mac_queues(mvm, BIT(info->hw_queue));
                        ieee80211_free_txskb(mvm->hw, skb);
                }
        }
@@ -3975,6 +3989,43 @@ out_unlock:
        return ret;
 }
 
+static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop)
+{
+       if (drop) {
+               if (iwl_mvm_has_new_tx_api(mvm))
+                       /* TODO new tx api */
+                       WARN_ONCE(1,
+                                 "Need to implement flush TX queue\n");
+               else
+                       iwl_mvm_flush_tx_path(mvm,
+                               iwl_mvm_flushable_queues(mvm) & queues,
+                               0);
+       } else {
+               if (iwl_mvm_has_new_tx_api(mvm)) {
+                       struct ieee80211_sta *sta;
+                       int i;
+
+                       mutex_lock(&mvm->mutex);
+
+                       for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
+                               sta = rcu_dereference_protected(
+                                               mvm->fw_id_to_mac_id[i],
+                                               lockdep_is_held(&mvm->mutex));
+                               if (IS_ERR_OR_NULL(sta))
+                                       continue;
+
+                               iwl_mvm_wait_sta_queues_empty(mvm,
+                                               iwl_mvm_sta_from_mac80211(sta));
+                       }
+
+                       mutex_unlock(&mvm->mutex);
+               } else {
+                       iwl_trans_wait_tx_queues_empty(mvm->trans,
+                                                      queues);
+               }
+       }
+}
+
 static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
                              struct ieee80211_vif *vif, u32 queues, bool drop)
 {
@@ -3985,7 +4036,12 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
        int i;
        u32 msk = 0;
 
-       if (!vif || vif->type != NL80211_IFTYPE_STATION)
+       if (!vif) {
+               iwl_mvm_flush_no_vif(mvm, queues, drop);
+               return;
+       }
+
+       if (vif->type != NL80211_IFTYPE_STATION)
                return;
 
        /* Make sure we're done with the deferred traffic before flushing */
index ba7bd04..0fe723c 100644 (file)
@@ -661,7 +661,8 @@ static void rs_tl_turn_on_agg(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
            (lq_sta->tx_agg_tid_en & BIT(tid)) &&
            (tid_data->tx_count_last >= IWL_MVM_RS_AGG_START_THRESHOLD)) {
                IWL_DEBUG_RATE(mvm, "try to aggregate tid %d\n", tid);
-               rs_tl_turn_on_agg_for_tid(mvm, lq_sta, tid, sta);
+               if (rs_tl_turn_on_agg_for_tid(mvm, lq_sta, tid, sta) == 0)
+                       tid_data->state = IWL_AGG_QUEUED;
        }
 }
 
index 67ffd97..77f77bc 100644 (file)
@@ -672,11 +672,12 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
         * If there was a significant jump in the nssn - adjust.
         * If the SN is smaller than the NSSN it might need to first go into
         * the reorder buffer, in which case we just release up to it and the
-        * rest of the function will take of storing it and releasing up to the
-        * nssn
+        * rest of the function will take care of storing it and releasing up to
+        * the nssn
         */
        if (!iwl_mvm_is_sn_less(nssn, buffer->head_sn + buffer->buf_size,
-                               buffer->buf_size)) {
+                               buffer->buf_size) ||
+           !ieee80211_sn_less(sn, buffer->head_sn + buffer->buf_size)) {
                u16 min_sn = ieee80211_sn_less(sn, nssn) ? sn : nssn;
 
                iwl_mvm_release_frames(mvm, sta, napi, buffer, min_sn);
index 5098361..774122f 100644 (file)
@@ -555,7 +555,7 @@ static int iwl_mvm_lmac_scan_abort(struct iwl_mvm *mvm)
        struct iwl_host_cmd cmd = {
                .id = SCAN_OFFLOAD_ABORT_CMD,
        };
-       u32 status;
+       u32 status = CAN_ABORT_STATUS;
 
        ret = iwl_mvm_send_cmd_status(mvm, &cmd, &status);
        if (ret)
index 411a205..c4a3435 100644 (file)
@@ -1285,7 +1285,7 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
 {
        struct iwl_mvm_add_sta_cmd cmd;
        int ret;
-       u32 status;
+       u32 status = ADD_STA_SUCCESS;
 
        lockdep_assert_held(&mvm->mutex);
 
@@ -2385,8 +2385,10 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
                return -EINVAL;
 
-       if (mvmsta->tid_data[tid].state != IWL_AGG_OFF) {
-               IWL_ERR(mvm, "Start AGG when state is not IWL_AGG_OFF %d!\n",
+       if (mvmsta->tid_data[tid].state != IWL_AGG_QUEUED &&
+           mvmsta->tid_data[tid].state != IWL_AGG_OFF) {
+               IWL_ERR(mvm,
+                       "Start AGG when state is not IWL_AGG_QUEUED or IWL_AGG_OFF %d!\n",
                        mvmsta->tid_data[tid].state);
                return -ENXIO;
        }
index d138938..aedabe1 100644 (file)
@@ -281,6 +281,7 @@ struct iwl_mvm_vif;
  * These states relate to a specific RA / TID.
  *
  * @IWL_AGG_OFF: aggregation is not used
+ * @IWL_AGG_QUEUED: aggregation start work has been queued
  * @IWL_AGG_STARTING: aggregation are starting (between start and oper)
  * @IWL_AGG_ON: aggregation session is up
  * @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the
@@ -290,6 +291,7 @@ struct iwl_mvm_vif;
  */
 enum iwl_mvm_agg_state {
        IWL_AGG_OFF = 0,
+       IWL_AGG_QUEUED,
        IWL_AGG_STARTING,
        IWL_AGG_ON,
        IWL_EMPTYING_HW_QUEUE_ADDBA,
index 8876c2a..4d907f6 100644 (file)
@@ -529,6 +529,7 @@ int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 state)
 
        lockdep_assert_held(&mvm->mutex);
 
+       status = 0;
        ret = iwl_mvm_send_cmd_pdu_status(mvm, WIDE_ID(PHY_OPS_GROUP,
                                                       CTDP_CONFIG_CMD),
                                          sizeof(cmd), &cmd, &status);
index 172b5e6..6f2e2af 100644 (file)
@@ -564,8 +564,8 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
        case NL80211_IFTYPE_AP:
        case NL80211_IFTYPE_ADHOC:
                /*
-                * Handle legacy hostapd as well, where station will be added
-                * only just before sending the association response.
+                * Non-bufferable frames use the broadcast station, thus they
+                * use the probe queue.
                 * Also take care of the case where we send a deauth to a
                 * station that we don't have, or similarly an association
                 * response (with non-success status) for a station we can't
@@ -573,9 +573,9 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm,
                 * Also, disassociate frames might happen, particular with
                 * reason 7 ("Class 3 frame received from nonassociated STA").
                 */
-               if (ieee80211_is_probe_resp(fc) || ieee80211_is_auth(fc) ||
-                   ieee80211_is_deauth(fc) || ieee80211_is_assoc_resp(fc) ||
-                   ieee80211_is_disassoc(fc))
+               if (ieee80211_is_mgmt(fc) &&
+                   (!ieee80211_is_bufferable_mmpdu(fc) ||
+                    ieee80211_is_deauth(fc) || ieee80211_is_disassoc(fc)))
                        return mvm->probe_queue;
                if (info->hw_queue == info->control.vif->cab_queue)
                        return mvmvif->cab_queue;
index 856fa6e..a450bc6 100644 (file)
@@ -115,6 +115,8 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 
        vif = qtnf_netdev_get_priv(wdev->netdev);
 
+       qtnf_scan_done(vif->mac, true);
+
        if (qtnf_cmd_send_del_intf(vif))
                pr_err("VIF%u.%u: failed to delete VIF\n", vif->mac->macid,
                       vif->vifid);
@@ -335,6 +337,8 @@ static int qtnf_stop_ap(struct wiphy *wiphy, struct net_device *dev)
        struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
        int ret;
 
+       qtnf_scan_done(vif->mac, true);
+
        ret = qtnf_cmd_send_stop_ap(vif);
        if (ret) {
                pr_err("VIF%u.%u: failed to stop AP operation in FW\n",
@@ -570,8 +574,6 @@ qtnf_del_station(struct wiphy *wiphy, struct net_device *dev,
            !qtnf_sta_list_lookup(&vif->sta_list, params->mac))
                return 0;
 
-       qtnf_scan_done(vif->mac, true);
-
        ret = qtnf_cmd_send_del_sta(vif, params);
        if (ret)
                pr_err("VIF%u.%u: failed to delete STA %pM\n",
@@ -1134,8 +1136,9 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev)
                }
 
                vif->sta_state = QTNF_STA_DISCONNECTED;
-               qtnf_scan_done(mac, true);
        }
+
+       qtnf_scan_done(mac, true);
 }
 
 void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif)
index 6a4af52..66db266 100644 (file)
@@ -34,6 +34,9 @@ static inline void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted)
                .aborted = aborted,
        };
 
+       if (timer_pending(&mac->scan_timeout))
+               del_timer_sync(&mac->scan_timeout);
+
        mutex_lock(&mac->mac_lock);
 
        if (mac->scan_req) {
index 0fc2814..43d2e7f 100644 (file)
@@ -345,8 +345,6 @@ qtnf_event_handle_scan_complete(struct qtnf_wmac *mac,
                return -EINVAL;
        }
 
-       if (timer_pending(&mac->scan_timeout))
-               del_timer_sync(&mac->scan_timeout);
        qtnf_scan_done(mac, le32_to_cpu(status->flags) & QLINK_SCAN_ABORTED);
 
        return 0;
index 502e72b..6913196 100644 (file)
@@ -661,14 +661,18 @@ static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb)
        struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus);
        dma_addr_t txbd_paddr, skb_paddr;
        struct qtnf_tx_bd *txbd;
+       unsigned long flags;
        int len, i;
        u32 info;
        int ret = 0;
 
+       spin_lock_irqsave(&priv->tx0_lock, flags);
+
        if (!qtnf_tx_queue_ready(priv)) {
                if (skb->dev)
                        netif_stop_queue(skb->dev);
 
+               spin_unlock_irqrestore(&priv->tx0_lock, flags);
                return NETDEV_TX_BUSY;
        }
 
@@ -717,8 +721,10 @@ tx_done:
                dev_kfree_skb_any(skb);
        }
 
-       qtnf_pcie_data_tx_reclaim(priv);
        priv->tx_done_count++;
+       spin_unlock_irqrestore(&priv->tx0_lock, flags);
+
+       qtnf_pcie_data_tx_reclaim(priv);
 
        return NETDEV_TX_OK;
 }
@@ -1247,6 +1253,7 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        strcpy(bus->fwname, QTN_PCI_PEARL_FW_NAME);
        init_completion(&bus->request_firmware_complete);
        mutex_init(&bus->bus_lock);
+       spin_lock_init(&pcie_priv->tx0_lock);
        spin_lock_init(&pcie_priv->irq_lock);
        spin_lock_init(&pcie_priv->tx_reclaim_lock);
 
index e76a237..86ac1cc 100644 (file)
@@ -34,6 +34,8 @@ struct qtnf_pcie_bus_priv {
 
        /* lock for tx reclaim operations */
        spinlock_t tx_reclaim_lock;
+       /* lock for tx0 operations */
+       spinlock_t tx0_lock;
        u8 msi_enabled;
        int mps;
 
index bb2aad0..5a14cc7 100644 (file)
@@ -2136,7 +2136,7 @@ static umode_t nvme_ns_attrs_are_visible(struct kobject *kobj,
        struct nvme_ns *ns = nvme_get_ns_from_dev(dev);
 
        if (a == &dev_attr_uuid.attr) {
-               if (uuid_is_null(&ns->uuid) ||
+               if (uuid_is_null(&ns->uuid) &&
                    !memchr_inv(ns->nguid, 0, sizeof(ns->nguid)))
                        return 0;
        }
index cb73bc8..3f5a04c 100644 (file)
@@ -94,7 +94,7 @@ struct nvme_dev {
        struct mutex shutdown_lock;
        bool subsystem;
        void __iomem *cmb;
-       dma_addr_t cmb_dma_addr;
+       pci_bus_addr_t cmb_bus_addr;
        u64 cmb_size;
        u32 cmbsz;
        u32 cmbloc;
@@ -1226,7 +1226,7 @@ static int nvme_alloc_sq_cmds(struct nvme_dev *dev, struct nvme_queue *nvmeq,
        if (qid && dev->cmb && use_cmb_sqes && NVME_CMB_SQS(dev->cmbsz)) {
                unsigned offset = (qid - 1) * roundup(SQ_SIZE(depth),
                                                      dev->ctrl.page_size);
-               nvmeq->sq_dma_addr = dev->cmb_dma_addr + offset;
+               nvmeq->sq_dma_addr = dev->cmb_bus_addr + offset;
                nvmeq->sq_cmds_io = dev->cmb + offset;
        } else {
                nvmeq->sq_cmds = dma_alloc_coherent(dev->dev, SQ_SIZE(depth),
@@ -1527,7 +1527,7 @@ static void __iomem *nvme_map_cmb(struct nvme_dev *dev)
        resource_size_t bar_size;
        struct pci_dev *pdev = to_pci_dev(dev->dev);
        void __iomem *cmb;
-       dma_addr_t dma_addr;
+       int bar;
 
        dev->cmbsz = readl(dev->bar + NVME_REG_CMBSZ);
        if (!(NVME_CMB_SZ(dev->cmbsz)))
@@ -1540,7 +1540,8 @@ static void __iomem *nvme_map_cmb(struct nvme_dev *dev)
        szu = (u64)1 << (12 + 4 * NVME_CMB_SZU(dev->cmbsz));
        size = szu * NVME_CMB_SZ(dev->cmbsz);
        offset = szu * NVME_CMB_OFST(dev->cmbloc);
-       bar_size = pci_resource_len(pdev, NVME_CMB_BIR(dev->cmbloc));
+       bar = NVME_CMB_BIR(dev->cmbloc);
+       bar_size = pci_resource_len(pdev, bar);
 
        if (offset > bar_size)
                return NULL;
@@ -1553,12 +1554,11 @@ static void __iomem *nvme_map_cmb(struct nvme_dev *dev)
        if (size > bar_size - offset)
                size = bar_size - offset;
 
-       dma_addr = pci_resource_start(pdev, NVME_CMB_BIR(dev->cmbloc)) + offset;
-       cmb = ioremap_wc(dma_addr, size);
+       cmb = ioremap_wc(pci_resource_start(pdev, bar) + offset, size);
        if (!cmb)
                return NULL;
 
-       dev->cmb_dma_addr = dma_addr;
+       dev->cmb_bus_addr = pci_bus_address(pdev, bar) + offset;
        dev->cmb_size = size;
        return cmb;
 }
index de54c7f..d12e5de 100644 (file)
@@ -135,7 +135,7 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
 
        /* Stop the user from writing */
        if (pos >= nvmem->size)
-               return 0;
+               return -EFBIG;
 
        if (count < nvmem->word_size)
                return -EINVAL;
@@ -789,6 +789,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
                return ERR_PTR(-EINVAL);
 
        nvmem = __nvmem_device_get(nvmem_np, NULL, NULL);
+       of_node_put(nvmem_np);
        if (IS_ERR(nvmem))
                return ERR_CAST(nvmem);
 
index 315a4be..9a68914 100644 (file)
@@ -51,6 +51,8 @@ module_param(mbox_sel, byte, S_IRUGO);
 MODULE_PARM_DESC(mbox_sel,
                 "RIO Messaging MBOX Selection Mask (default: 0x0f = all)");
 
+static DEFINE_SPINLOCK(tsi721_maint_lock);
+
 static void tsi721_omsg_handler(struct tsi721_device *priv, int ch);
 static void tsi721_imsg_handler(struct tsi721_device *priv, int ch);
 
@@ -124,12 +126,15 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size,
        void __iomem *regs = priv->regs + TSI721_DMAC_BASE(priv->mdma.ch_id);
        struct tsi721_dma_desc *bd_ptr;
        u32 rd_count, swr_ptr, ch_stat;
+       unsigned long flags;
        int i, err = 0;
        u32 op = do_wr ? MAINT_WR : MAINT_RD;
 
        if (offset > (RIO_MAINT_SPACE_SZ - len) || (len != sizeof(u32)))
                return -EINVAL;
 
+       spin_lock_irqsave(&tsi721_maint_lock, flags);
+
        bd_ptr = priv->mdma.bd_base;
 
        rd_count = ioread32(regs + TSI721_DMAC_DRDCNT);
@@ -197,7 +202,9 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size,
         */
        swr_ptr = ioread32(regs + TSI721_DMAC_DSWP);
        iowrite32(swr_ptr, regs + TSI721_DMAC_DSRP);
+
 err_out:
+       spin_unlock_irqrestore(&tsi721_maint_lock, flags);
 
        return err;
 }
index a3824ba..3ee9af8 100644 (file)
 #include <linux/module.h>
 
 /*
- * These interrupt-safe spinlocks protect all accesses to RIO
- * configuration space and doorbell access.
- */
-static DEFINE_SPINLOCK(rio_config_lock);
-static DEFINE_SPINLOCK(rio_doorbell_lock);
-
-/*
  *  Wrappers for all RIO configuration access functions.  They just check
- *  alignment, do locking and call the low-level functions pointed to
- *  by rio_mport->ops.
+ *  alignment and call the low-level functions pointed to by rio_mport->ops.
  */
 
 #define RIO_8_BAD 0
@@ -44,13 +36,10 @@ int __rio_local_read_config_##size \
        (struct rio_mport *mport, u32 offset, type *value)              \
 {                                                                      \
        int res;                                                        \
-       unsigned long flags;                                            \
        u32 data = 0;                                                   \
        if (RIO_##size##_BAD) return RIO_BAD_SIZE;                      \
-       spin_lock_irqsave(&rio_config_lock, flags);                     \
        res = mport->ops->lcread(mport, mport->id, offset, len, &data); \
        *value = (type)data;                                            \
-       spin_unlock_irqrestore(&rio_config_lock, flags);                \
        return res;                                                     \
 }
 
@@ -67,13 +56,8 @@ int __rio_local_read_config_##size \
 int __rio_local_write_config_##size \
        (struct rio_mport *mport, u32 offset, type value)               \
 {                                                                      \
-       int res;                                                        \
-       unsigned long flags;                                            \
        if (RIO_##size##_BAD) return RIO_BAD_SIZE;                      \
-       spin_lock_irqsave(&rio_config_lock, flags);                     \
-       res = mport->ops->lcwrite(mport, mport->id, offset, len, value);\
-       spin_unlock_irqrestore(&rio_config_lock, flags);                \
-       return res;                                                     \
+       return mport->ops->lcwrite(mport, mport->id, offset, len, value);\
 }
 
 RIO_LOP_READ(8, u8, 1)
@@ -104,13 +88,10 @@ int rio_mport_read_config_##size \
        (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value)     \
 {                                                                      \
        int res;                                                        \
-       unsigned long flags;                                            \
        u32 data = 0;                                                   \
        if (RIO_##size##_BAD) return RIO_BAD_SIZE;                      \
-       spin_lock_irqsave(&rio_config_lock, flags);                     \
        res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \
        *value = (type)data;                                            \
-       spin_unlock_irqrestore(&rio_config_lock, flags);                \
        return res;                                                     \
 }
 
@@ -127,13 +108,9 @@ int rio_mport_read_config_##size \
 int rio_mport_write_config_##size \
        (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value)      \
 {                                                                      \
-       int res;                                                        \
-       unsigned long flags;                                            \
        if (RIO_##size##_BAD) return RIO_BAD_SIZE;                      \
-       spin_lock_irqsave(&rio_config_lock, flags);                     \
-       res = mport->ops->cwrite(mport, mport->id, destid, hopcount, offset, len, value); \
-       spin_unlock_irqrestore(&rio_config_lock, flags);                \
-       return res;                                                     \
+       return mport->ops->cwrite(mport, mport->id, destid, hopcount,   \
+                       offset, len, value);                            \
 }
 
 RIO_OP_READ(8, u8, 1)
@@ -162,14 +139,7 @@ EXPORT_SYMBOL_GPL(rio_mport_write_config_32);
  */
 int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data)
 {
-       int res;
-       unsigned long flags;
-
-       spin_lock_irqsave(&rio_doorbell_lock, flags);
-       res = mport->ops->dsend(mport, mport->id, destid, data);
-       spin_unlock_irqrestore(&rio_doorbell_lock, flags);
-
-       return res;
+       return mport->ops->dsend(mport, mport->id, destid, data);
 }
 
 EXPORT_SYMBOL_GPL(rio_mport_send_doorbell);
index e0c3932..e2baecb 100644 (file)
@@ -34,11 +34,12 @@ config RESET_BERLIN
        help
          This enables the reset controller driver for Marvell Berlin SoCs.
 
-config RESET_HSDK_V1
-       bool "HSDK v1 Reset Driver"
-       default n
+config RESET_HSDK
+       bool "Synopsys HSDK Reset Driver"
+       depends on HAS_IOMEM
+       depends on ARC_SOC_HSDK || COMPILE_TEST
        help
-         This enables the reset controller driver for HSDK v1.
+         This enables the reset controller driver for HSDK board.
 
 config RESET_IMX7
        bool "i.MX7 Reset Driver" if COMPILE_TEST
index d368367..af1c15c 100644 (file)
@@ -5,7 +5,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
 obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
 obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
 obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
-obj-$(CONFIG_RESET_HSDK_V1) += reset-hsdk-v1.o
+obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o
 obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
 obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o
 obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
similarity index 72%
rename from drivers/reset/reset-hsdk-v1.c
rename to drivers/reset/reset-hsdk.c
index bca13e4..8bce391 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2017 Synopsys.
  *
- * Synopsys HSDKv1 SDP reset driver.
+ * Synopsys HSDK Development platform reset driver.
  *
  * This file is licensed under the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
@@ -18,9 +18,9 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 
-#define to_hsdkv1_rst(p)       container_of((p), struct hsdkv1_rst, rcdev)
+#define to_hsdk_rst(p) container_of((p), struct hsdk_rst, rcdev)
 
-struct hsdkv1_rst {
+struct hsdk_rst {
        void __iomem                    *regs_ctl;
        void __iomem                    *regs_rst;
        spinlock_t                      lock;
@@ -49,12 +49,12 @@ static const u32 rst_map[] = {
 #define CGU_IP_SW_RESET_RESET          BIT(0)
 #define SW_RESET_TIMEOUT               10000
 
-static void hsdkv1_reset_config(struct hsdkv1_rst *rst, unsigned long id)
+static void hsdk_reset_config(struct hsdk_rst *rst, unsigned long id)
 {
        writel(rst_map[id], rst->regs_ctl + CGU_SYS_RST_CTRL);
 }
 
-static int hsdkv1_reset_do(struct hsdkv1_rst *rst)
+static int hsdk_reset_do(struct hsdk_rst *rst)
 {
        u32 reg;
 
@@ -69,28 +69,28 @@ static int hsdkv1_reset_do(struct hsdkv1_rst *rst)
                !(reg & CGU_IP_SW_RESET_RESET), 5, SW_RESET_TIMEOUT);
 }
 
-static int hsdkv1_reset_reset(struct reset_controller_dev *rcdev,
+static int hsdk_reset_reset(struct reset_controller_dev *rcdev,
                              unsigned long id)
 {
-       struct hsdkv1_rst *rst = to_hsdkv1_rst(rcdev);
+       struct hsdk_rst *rst = to_hsdk_rst(rcdev);
        unsigned long flags;
        int ret;
 
        spin_lock_irqsave(&rst->lock, flags);
-       hsdkv1_reset_config(rst, id);
-       ret = hsdkv1_reset_do(rst);
+       hsdk_reset_config(rst, id);
+       ret = hsdk_reset_do(rst);
        spin_unlock_irqrestore(&rst->lock, flags);
 
        return ret;
 }
 
-static const struct reset_control_ops hsdkv1_reset_ops = {
-       .reset  = hsdkv1_reset_reset,
+static const struct reset_control_ops hsdk_reset_ops = {
+       .reset  = hsdk_reset_reset,
 };
 
-static int hsdkv1_reset_probe(struct platform_device *pdev)
+static int hsdk_reset_probe(struct platform_device *pdev)
 {
-       struct hsdkv1_rst *rst;
+       struct hsdk_rst *rst;
        struct resource *mem;
 
        rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL);
@@ -110,7 +110,7 @@ static int hsdkv1_reset_probe(struct platform_device *pdev)
        spin_lock_init(&rst->lock);
 
        rst->rcdev.owner = THIS_MODULE;
-       rst->rcdev.ops = &hsdkv1_reset_ops;
+       rst->rcdev.ops = &hsdk_reset_ops;
        rst->rcdev.of_node = pdev->dev.of_node;
        rst->rcdev.nr_resets = HSDK_MAX_RESETS;
        rst->rcdev.of_reset_n_cells = 1;
@@ -118,20 +118,20 @@ static int hsdkv1_reset_probe(struct platform_device *pdev)
        return reset_controller_register(&rst->rcdev);
 }
 
-static const struct of_device_id hsdkv1_reset_dt_match[] = {
-       { .compatible = "snps,hsdk-v1.0-reset" },
+static const struct of_device_id hsdk_reset_dt_match[] = {
+       { .compatible = "snps,hsdk-reset" },
        { },
 };
 
-static struct platform_driver hsdkv1_reset_driver = {
-       .probe  = hsdkv1_reset_probe,
+static struct platform_driver hsdk_reset_driver = {
+       .probe  = hsdk_reset_probe,
        .driver = {
-               .name = "hsdk-v1.0-reset",
-               .of_match_table = hsdkv1_reset_dt_match,
+               .name = "hsdk-reset",
+               .of_match_table = hsdk_reset_dt_match,
        },
 };
-builtin_platform_driver(hsdkv1_reset_driver);
+builtin_platform_driver(hsdk_reset_driver);
 
 MODULE_AUTHOR("Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>");
-MODULE_DESCRIPTION("Synopsys HSDKv1 SDP reset driver");
+MODULE_DESCRIPTION("Synopsys HSDK SDP reset driver");
 MODULE_LICENSE("GPL v2");
index d11c6de..6150d27 100644 (file)
@@ -223,11 +223,9 @@ static int ad7192_setup(struct ad7192_state *st,
        struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi);
        unsigned long long scale_uv;
        int i, ret, id;
-       u8 ones[6];
 
        /* reset the serial interface */
-       memset(&ones, 0xFF, 6);
-       ret = spi_write(st->sd.spi, &ones, 6);
+       ret = ad_sd_reset(&st->sd, 48);
        if (ret < 0)
                goto out;
        usleep_range(500, 1000); /* Wait for at least 500us */
index 13eaf16..87595c5 100644 (file)
@@ -496,8 +496,12 @@ static int spinand_program_page(struct spi_device *spi_nand,
        if (!wbuf)
                return -ENOMEM;
 
-       enable_read_hw_ecc = 0;
-       spinand_read_page(spi_nand, page_id, 0, CACHE_BUF, wbuf);
+       enable_read_hw_ecc = 1;
+       retval = spinand_read_page(spi_nand, page_id, 0, CACHE_BUF, wbuf);
+       if (retval < 0) {
+               dev_err(&spi_nand->dev, "ecc error on read page!!!\n");
+               return retval;
+       }
 
        for (i = offset, j = 0; i < len; i++, j++)
                wbuf[i] &= buf[j];
index c4b1b21..290b419 100644 (file)
@@ -570,12 +570,6 @@ int rf69_set_dio_mapping(struct spi_device *spi, u8 DIONumber, u8 value)
                dev_dbg(&spi->dev, "set: DIO mapping");
        #endif
 
-       // check DIO number
-       if (DIONumber > 5) {
-               dev_dbg(&spi->dev, "set: illegal input param");
-               return -EINVAL;
-       }
-
        switch (DIONumber) {
        case 0: mask=MASK_DIO0; shift=SHIFT_DIO0; regaddr=REG_DIOMAPPING1; break;
        case 1: mask=MASK_DIO1; shift=SHIFT_DIO1; regaddr=REG_DIOMAPPING1; break;
@@ -583,6 +577,9 @@ int rf69_set_dio_mapping(struct spi_device *spi, u8 DIONumber, u8 value)
        case 3: mask=MASK_DIO3; shift=SHIFT_DIO3; regaddr=REG_DIOMAPPING1; break;
        case 4: mask=MASK_DIO4; shift=SHIFT_DIO4; regaddr=REG_DIOMAPPING2; break;
        case 5: mask=MASK_DIO5; shift=SHIFT_DIO5; regaddr=REG_DIOMAPPING2; break;
+       default:
+               dev_dbg(&spi->dev, "set: illegal input param");
+               return -EINVAL;
        }
 
        // read reg
index 6b77820..cb8a95a 100644 (file)
@@ -119,9 +119,8 @@ void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
 
 void _rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
 {
-       rtw_free_mlme_priv_ie_data(pmlmepriv);
-
        if (pmlmepriv) {
+               rtw_free_mlme_priv_ie_data(pmlmepriv);
                if (pmlmepriv->free_bss_buf) {
                        vfree(pmlmepriv->free_bss_buf);
                }
index 9227745..ce1dd6f 100644 (file)
@@ -311,6 +311,8 @@ static ssize_t proc_set_cam(struct file *file, const char __user *buffer, size_t
 
                if (num < 2)
                        return count;
+               if (id >= TOTAL_CAM_ENTRY)
+                       return -EINVAL;
 
                if (strcmp("c", cmd) == 0) {
                        _clear_cam_entry(adapter, id);
index 5f84526..edbf6af 100644 (file)
@@ -2901,11 +2901,11 @@ halmac_update_datapack_88xx(struct halmac_adapter *halmac_adapter,
        if (halmac_adapter->fw_version.h2c_version < 4)
                return HALMAC_RET_FW_NO_SUPPORT;
 
+       driver_adapter = halmac_adapter->driver_adapter;
+
        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
                        "[TRACE]%s ==========>\n", __func__);
 
-       driver_adapter = halmac_adapter->driver_adapter;
-
        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
                        "[TRACE]%s <==========\n", __func__);
 
index f33024e..544f638 100644 (file)
@@ -1618,10 +1618,11 @@ halmac_send_h2c_set_pwr_mode_88xx(struct halmac_adapter *halmac_adapter,
        void *driver_adapter = NULL;
        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
 
+       driver_adapter = halmac_adapter->driver_adapter;
+
        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
                        "%s!!\n", __func__);
 
-       driver_adapter = halmac_adapter->driver_adapter;
        h2c_header = h2c_buff;
        h2c_cmd = h2c_header + HALMAC_H2C_CMD_HDR_SIZE_88XX;
 
@@ -1713,10 +1714,11 @@ halmac_media_status_rpt_88xx(struct halmac_adapter *halmac_adapter, u8 op_mode,
        void *driver_adapter = NULL;
        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
 
+       driver_adapter = halmac_adapter->driver_adapter;
+
        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
                        "halmac_send_h2c_set_pwr_mode_88xx!!\n");
 
-       driver_adapter = halmac_adapter->driver_adapter;
        h2c_header = H2c_buff;
        h2c_cmd = h2c_header + HALMAC_H2C_CMD_HDR_SIZE_88XX;
 
@@ -2143,10 +2145,11 @@ halmac_func_ctrl_ch_switch_88xx(struct halmac_adapter *halmac_adapter,
        enum halmac_cmd_process_status *process_status =
                &halmac_adapter->halmac_state.scan_state_set.process_status;
 
+       driver_adapter = halmac_adapter->driver_adapter;
+
        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
                        "halmac_ctrl_ch_switch!!\n");
 
-       driver_adapter = halmac_adapter->driver_adapter;
        halmac_api = (struct halmac_api *)halmac_adapter->halmac_api;
 
        if (halmac_transition_scan_state_88xx(
@@ -2276,15 +2279,13 @@ enum halmac_ret_status halmac_send_h2c_update_bcn_parse_info_88xx(
 {
        u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0};
        u16 h2c_seq_mum = 0;
-       void *driver_adapter = NULL;
+       void *driver_adapter = halmac_adapter->driver_adapter;
        struct halmac_h2c_header_info h2c_header_info;
        enum halmac_ret_status status = HALMAC_RET_SUCCESS;
 
        HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG,
                        "%s!!\n", __func__);
 
-       driver_adapter = halmac_adapter->driver_adapter;
-
        UPDATE_BEACON_PARSING_INFO_SET_FUNC_EN(h2c_buff, bcn_ie_info->func_en);
        UPDATE_BEACON_PARSING_INFO_SET_SIZE_TH(h2c_buff, bcn_ie_info->size_th);
        UPDATE_BEACON_PARSING_INFO_SET_TIMEOUT(h2c_buff, bcn_ie_info->timeout);
index 67956e2..56f7be6 100644 (file)
@@ -1376,6 +1376,8 @@ static void reset_highlight_buffers(struct vc_data *);
 
 static int read_all_key;
 
+static int in_keyboard_notifier;
+
 static void start_read_all_timer(struct vc_data *vc, int command);
 
 enum {
@@ -1408,7 +1410,10 @@ static void read_all_doc(struct vc_data *vc)
        cursor_track = read_all_mode;
        spk_reset_index_count(0);
        if (get_sentence_buf(vc, 0) == -1) {
-               kbd_fakekey2(vc, RA_DOWN_ARROW);
+               del_timer(&cursor_timer);
+               if (!in_keyboard_notifier)
+                       speakup_fake_down_arrow();
+               start_read_all_timer(vc, RA_DOWN_ARROW);
        } else {
                say_sentence_num(0, 0);
                synth_insert_next_index(0);
@@ -2212,8 +2217,10 @@ static int keyboard_notifier_call(struct notifier_block *nb,
        int ret = NOTIFY_OK;
        static int keycode;     /* to hold the current keycode */
 
+       in_keyboard_notifier = 1;
+
        if (vc->vc_mode == KD_GRAPHICS)
-               return ret;
+               goto out;
 
        /*
         * First, determine whether we are handling a fake keypress on
@@ -2225,7 +2232,7 @@ static int keyboard_notifier_call(struct notifier_block *nb,
         */
 
        if (speakup_fake_key_pressed())
-               return ret;
+               goto out;
 
        switch (code) {
        case KBD_KEYCODE:
@@ -2266,6 +2273,8 @@ static int keyboard_notifier_call(struct notifier_block *nb,
                        break;
                }
        }
+out:
+       in_keyboard_notifier = 0;
        return ret;
 }
 
index 74cce4f..27ecf6f 100644 (file)
@@ -1826,7 +1826,7 @@ static __init int visorutil_spar_detect(void)
        return 0;
 }
 
-static int init_unisys(void)
+static int __init init_unisys(void)
 {
        int result;
 
@@ -1841,7 +1841,7 @@ static int init_unisys(void)
        return 0;
 };
 
-static void exit_unisys(void)
+static void __exit exit_unisys(void)
 {
        acpi_bus_unregister_driver(&unisys_acpi_driver);
 }
index 0159ca4..be08849 100644 (file)
@@ -612,18 +612,20 @@ free_pagelist(struct vchiq_pagelist_info *pagelistinfo,
                        if (head_bytes > actual)
                                head_bytes = actual;
 
-                       memcpy((char *)page_address(pages[0]) +
+                       memcpy((char *)kmap(pages[0]) +
                                pagelist->offset,
                                fragments,
                                head_bytes);
+                       kunmap(pages[0]);
                }
                if ((actual >= 0) && (head_bytes < actual) &&
                        (tail_bytes != 0)) {
-                       memcpy((char *)page_address(pages[num_pages - 1]) +
+                       memcpy((char *)kmap(pages[num_pages - 1]) +
                                ((pagelist->offset + actual) &
                                (PAGE_SIZE - 1) & ~(g_cache_line_size - 1)),
                                fragments + g_cache_line_size,
                                tail_bytes);
+                       kunmap(pages[num_pages - 1]);
                }
 
                down(&g_free_fragments_mutex);
index 1c0c955..7dd3804 100644 (file)
@@ -246,11 +246,11 @@ struct mxser_port {
        unsigned char err_shadow;
 
        struct async_icount icount; /* kernel counters for 4 input interrupts */
-       int timeout;
+       unsigned int timeout;
 
        int read_status_mask;
        int ignore_status_mask;
-       int xmit_fifo_size;
+       unsigned int xmit_fifo_size;
        int xmit_head;
        int xmit_tail;
        int xmit_cnt;
@@ -572,8 +572,9 @@ static void mxser_dtr_rts(struct tty_port *port, int on)
 static int mxser_set_baud(struct tty_struct *tty, long newspd)
 {
        struct mxser_port *info = tty->driver_data;
-       int quot = 0, baud;
+       unsigned int quot = 0, baud;
        unsigned char cval;
+       u64 timeout;
 
        if (!info->ioaddr)
                return -1;
@@ -594,8 +595,13 @@ static int mxser_set_baud(struct tty_struct *tty, long newspd)
                quot = 0;
        }
 
-       info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base);
-       info->timeout += HZ / 50;       /* Add .02 seconds of slop */
+       /*
+        * worst case (128 * 1000 * 10 * 18432) needs 35 bits, so divide in the
+        * u64 domain
+        */
+       timeout = (u64)info->xmit_fifo_size * HZ * 10 * quot;
+       do_div(timeout, info->baud_base);
+       info->timeout = timeout + HZ / 50; /* Add .02 seconds of slop */
 
        if (quot) {
                info->MCR |= UART_MCR_DTR;
index 583c9a0..8c48c37 100644 (file)
@@ -507,9 +507,14 @@ static void bcm_uart_set_termios(struct uart_port *port,
 {
        unsigned int ctl, baud, quot, ier;
        unsigned long flags;
+       int tries;
 
        spin_lock_irqsave(&port->lock, flags);
 
+       /* Drain the hot tub fully before we power it off for the winter. */
+       for (tries = 3; !bcm_uart_tx_empty(port) && tries; tries--)
+               mdelay(10);
+
        /* disable uart while changing speed */
        bcm_uart_disable(port);
        bcm_uart_flush(port);
index 849c1f9..f025218 100644 (file)
@@ -1276,7 +1276,6 @@ static void rx_dma_timer_init(struct lpuart_port *sport)
 static int lpuart_startup(struct uart_port *port)
 {
        struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
-       int ret;
        unsigned long flags;
        unsigned char temp;
 
@@ -1291,11 +1290,6 @@ static int lpuart_startup(struct uart_port *port)
        sport->rxfifo_size = 0x1 << (((temp >> UARTPFIFO_RXSIZE_OFF) &
                UARTPFIFO_FIFOSIZE_MASK) + 1);
 
-       ret = devm_request_irq(port->dev, port->irq, lpuart_int, 0,
-                               DRIVER_NAME, sport);
-       if (ret)
-               return ret;
-
        spin_lock_irqsave(&sport->port.lock, flags);
 
        lpuart_setup_watermark(sport);
@@ -1333,7 +1327,6 @@ static int lpuart_startup(struct uart_port *port)
 static int lpuart32_startup(struct uart_port *port)
 {
        struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
-       int ret;
        unsigned long flags;
        unsigned long temp;
 
@@ -1346,11 +1339,6 @@ static int lpuart32_startup(struct uart_port *port)
        sport->rxfifo_size = 0x1 << (((temp >> UARTFIFO_RXSIZE_OFF) &
                UARTFIFO_FIFOSIZE_MASK) - 1);
 
-       ret = devm_request_irq(port->dev, port->irq, lpuart32_int, 0,
-                               DRIVER_NAME, sport);
-       if (ret)
-               return ret;
-
        spin_lock_irqsave(&sport->port.lock, flags);
 
        lpuart32_setup_watermark(sport);
@@ -1380,8 +1368,6 @@ static void lpuart_shutdown(struct uart_port *port)
 
        spin_unlock_irqrestore(&port->lock, flags);
 
-       devm_free_irq(port->dev, port->irq, sport);
-
        if (sport->lpuart_dma_rx_use) {
                del_timer_sync(&sport->lpuart_timer);
                lpuart_dma_rx_free(&sport->port);
@@ -1400,7 +1386,6 @@ static void lpuart_shutdown(struct uart_port *port)
 
 static void lpuart32_shutdown(struct uart_port *port)
 {
-       struct lpuart_port *sport = container_of(port, struct lpuart_port, port);
        unsigned long temp;
        unsigned long flags;
 
@@ -1413,8 +1398,6 @@ static void lpuart32_shutdown(struct uart_port *port)
        lpuart32_write(port, temp, UARTCTRL);
 
        spin_unlock_irqrestore(&port->lock, flags);
-
-       devm_free_irq(port->dev, port->irq, sport);
 }
 
 static void
@@ -2212,16 +2195,22 @@ static int lpuart_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, &sport->port);
 
-       if (lpuart_is_32(sport))
+       if (lpuart_is_32(sport)) {
                lpuart_reg.cons = LPUART32_CONSOLE;
-       else
+               ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart32_int, 0,
+                                       DRIVER_NAME, sport);
+       } else {
                lpuart_reg.cons = LPUART_CONSOLE;
+               ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart_int, 0,
+                                       DRIVER_NAME, sport);
+       }
+
+       if (ret)
+               goto failed_irq_request;
 
        ret = uart_add_one_port(&lpuart_reg, &sport->port);
-       if (ret) {
-               clk_disable_unprepare(sport->clk);
-               return ret;
-       }
+       if (ret)
+               goto failed_attach_port;
 
        sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx");
        if (!sport->dma_tx_chan)
@@ -2240,6 +2229,11 @@ static int lpuart_probe(struct platform_device *pdev)
        }
 
        return 0;
+
+failed_attach_port:
+failed_irq_request:
+       clk_disable_unprepare(sport->clk);
+       return ret;
 }
 
 static int lpuart_remove(struct platform_device *pdev)
index cdd2f94..b9c7a90 100644 (file)
@@ -889,7 +889,16 @@ static int sccnxp_probe(struct platform_device *pdev)
                        goto err_out;
                uartclk = 0;
        } else {
-               clk_prepare_enable(clk);
+               ret = clk_prepare_enable(clk);
+               if (ret)
+                       goto err_out;
+
+               ret = devm_add_action_or_reset(&pdev->dev,
+                               (void(*)(void *))clk_disable_unprepare,
+                               clk);
+               if (ret)
+                       goto err_out;
+
                uartclk = clk_get_rate(clk);
        }
 
@@ -988,7 +997,7 @@ static int sccnxp_probe(struct platform_device *pdev)
        uart_unregister_driver(&s->uart);
 err_out:
        if (!IS_ERR(s->regulator))
-               return regulator_disable(s->regulator);
+               regulator_disable(s->regulator);
 
        return ret;
 }
index 5aacea1..3e865db 100644 (file)
@@ -190,8 +190,10 @@ static void wdm_in_callback(struct urb *urb)
        /*
         * only set a new error if there is no previous error.
         * Errors are only cleared during read/open
+        * Avoid propagating -EPIPE (stall) to userspace since it is
+        * better handled as an empty read
         */
-       if (desc->rerr  == 0)
+       if (desc->rerr == 0 && status != -EPIPE)
                desc->rerr = status;
 
        if (length + desc->length > desc->wMaxCommand) {
index 4be52c6..68b54bd 100644 (file)
@@ -643,15 +643,23 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx,
 
                } else if (header->bDescriptorType ==
                                USB_DT_INTERFACE_ASSOCIATION) {
+                       struct usb_interface_assoc_descriptor *d;
+
+                       d = (struct usb_interface_assoc_descriptor *)header;
+                       if (d->bLength < USB_DT_INTERFACE_ASSOCIATION_SIZE) {
+                               dev_warn(ddev,
+                                        "config %d has an invalid interface association descriptor of length %d, skipping\n",
+                                        cfgno, d->bLength);
+                               continue;
+                       }
+
                        if (iad_num == USB_MAXIADS) {
                                dev_warn(ddev, "found more Interface "
                                               "Association Descriptors "
                                               "than allocated for in "
                                               "configuration %d\n", cfgno);
                        } else {
-                               config->intf_assoc[iad_num] =
-                                       (struct usb_interface_assoc_descriptor
-                                       *)header;
+                               config->intf_assoc[iad_num] = d;
                                iad_num++;
                        }
 
@@ -852,7 +860,7 @@ int usb_get_configuration(struct usb_device *dev)
                }
 
                if (dev->quirks & USB_QUIRK_DELAY_INIT)
-                       msleep(100);
+                       msleep(200);
 
                result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno,
                    bigbuffer, length);
index 318bb3b..4664e54 100644 (file)
@@ -140,6 +140,9 @@ module_param(usbfs_memory_mb, uint, 0644);
 MODULE_PARM_DESC(usbfs_memory_mb,
                "maximum MB allowed for usbfs buffers (0 = no limit)");
 
+/* Hard limit, necessary to avoid arithmetic overflow */
+#define USBFS_XFER_MAX         (UINT_MAX / 2 - 1000000)
+
 static atomic64_t usbfs_memory_usage;  /* Total memory currently allocated */
 
 /* Check whether it's okay to allocate more memory for a transfer */
@@ -1460,6 +1463,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
                                USBDEVFS_URB_ZERO_PACKET |
                                USBDEVFS_URB_NO_INTERRUPT))
                return -EINVAL;
+       if ((unsigned int)uurb->buffer_length >= USBFS_XFER_MAX)
+               return -EINVAL;
        if (uurb->buffer_length > 0 && !uurb->buffer)
                return -EINVAL;
        if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL &&
@@ -1571,7 +1576,11 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
                        totlen += isopkt[u].length;
                }
                u *= sizeof(struct usb_iso_packet_descriptor);
-               uurb->buffer_length = totlen;
+               if (totlen <= uurb->buffer_length)
+                       uurb->buffer_length = totlen;
+               else
+                       WARN_ONCE(1, "uurb->buffer_length is too short %d vs %d",
+                                 totlen, uurb->buffer_length);
                break;
 
        default:
index 41eaf0b..b5c7336 100644 (file)
@@ -4838,7 +4838,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
                        goto loop;
 
                if (udev->quirks & USB_QUIRK_DELAY_INIT)
-                       msleep(1000);
+                       msleep(2000);
 
                /* consecutive bus-powered hubs aren't reliable; they can
                 * violate the voltage drop budget.  if the new child has
index 4c38ea4..371a07d 100644 (file)
@@ -2069,6 +2069,10 @@ int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr,
                        elength = 1;
                        goto next_desc;
                }
+               if ((buflen < elength) || (elength < 3)) {
+                       dev_err(&intf->dev, "invalid descriptor buffer length\n");
+                       break;
+               }
                if (buffer[1] != USB_DT_CS_INTERFACE) {
                        dev_err(&intf->dev, "skipping garbage\n");
                        goto next_desc;
index 4cef7d4..a26d1fd 100644 (file)
@@ -177,6 +177,7 @@ static const struct of_device_id of_dwc3_simple_match[] = {
        { .compatible = "rockchip,rk3399-dwc3" },
        { .compatible = "xlnx,zynqmp-dwc3" },
        { .compatible = "cavium,octeon-7130-usb-uctl" },
+       { .compatible = "sprd,sc9860-dwc3" },
        { /* Sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
index 827e376..75e6cb0 100644 (file)
@@ -990,6 +990,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
                                         DWC3_TRBCTL_CONTROL_DATA,
                                         true);
 
+               req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1];
+
                /* Now prepare one extra TRB to align transfer size */
                dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr,
                                         maxpacket - rem,
@@ -1015,6 +1017,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
                                         DWC3_TRBCTL_CONTROL_DATA,
                                         true);
 
+               req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1];
+
                /* Now prepare one extra TRB to align transfer size */
                dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr,
                                         0, DWC3_TRBCTL_CONTROL_DATA,
@@ -1029,6 +1033,9 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
                dwc3_ep0_prepare_one_trb(dep, req->request.dma,
                                req->request.length, DWC3_TRBCTL_CONTROL_DATA,
                                false);
+
+               req->trb = &dwc->ep0_trb[dep->trb_enqueue];
+
                ret = dwc3_ep0_start_trans(dep);
        }
 
index 9990944..8b34258 100644 (file)
@@ -46,7 +46,8 @@
 static void ffs_data_get(struct ffs_data *ffs);
 static void ffs_data_put(struct ffs_data *ffs);
 /* Creates new ffs_data object. */
-static struct ffs_data *__must_check ffs_data_new(void) __attribute__((malloc));
+static struct ffs_data *__must_check ffs_data_new(const char *dev_name)
+       __attribute__((malloc));
 
 /* Opened counter handling. */
 static void ffs_data_opened(struct ffs_data *ffs);
@@ -780,11 +781,12 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
                                         struct usb_request *req)
 {
        struct ffs_io_data *io_data = req->context;
+       struct ffs_data *ffs = io_data->ffs;
 
        ENTER();
 
        INIT_WORK(&io_data->work, ffs_user_copy_worker);
-       schedule_work(&io_data->work);
+       queue_work(ffs->io_completion_wq, &io_data->work);
 }
 
 static void __ffs_epfile_read_buffer_free(struct ffs_epfile *epfile)
@@ -1500,7 +1502,7 @@ ffs_fs_mount(struct file_system_type *t, int flags,
        if (unlikely(ret < 0))
                return ERR_PTR(ret);
 
-       ffs = ffs_data_new();
+       ffs = ffs_data_new(dev_name);
        if (unlikely(!ffs))
                return ERR_PTR(-ENOMEM);
        ffs->file_perms = data.perms;
@@ -1610,6 +1612,7 @@ static void ffs_data_put(struct ffs_data *ffs)
                BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
                       waitqueue_active(&ffs->ep0req_completion.wait) ||
                       waitqueue_active(&ffs->wait));
+               destroy_workqueue(ffs->io_completion_wq);
                kfree(ffs->dev_name);
                kfree(ffs);
        }
@@ -1642,7 +1645,7 @@ static void ffs_data_closed(struct ffs_data *ffs)
        ffs_data_put(ffs);
 }
 
-static struct ffs_data *ffs_data_new(void)
+static struct ffs_data *ffs_data_new(const char *dev_name)
 {
        struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL);
        if (unlikely(!ffs))
@@ -1650,6 +1653,12 @@ static struct ffs_data *ffs_data_new(void)
 
        ENTER();
 
+       ffs->io_completion_wq = alloc_ordered_workqueue("%s", 0, dev_name);
+       if (!ffs->io_completion_wq) {
+               kfree(ffs);
+               return NULL;
+       }
+
        refcount_set(&ffs->ref, 1);
        atomic_set(&ffs->opened, 0);
        ffs->state = FFS_READ_DESCRIPTORS;
index d6bd024..5153e29 100644 (file)
@@ -307,8 +307,6 @@ struct fsg_common {
        struct completion       thread_notifier;
        struct task_struct      *thread_task;
 
-       /* Callback functions. */
-       const struct fsg_operations     *ops;
        /* Gadget's private data. */
        void                    *private_data;
 
@@ -2438,6 +2436,7 @@ static void handle_exception(struct fsg_common *common)
 static int fsg_main_thread(void *common_)
 {
        struct fsg_common       *common = common_;
+       int                     i;
 
        /*
         * Allow the thread to be killed by a signal, but set the signal mask
@@ -2476,21 +2475,16 @@ static int fsg_main_thread(void *common_)
        common->thread_task = NULL;
        spin_unlock_irq(&common->lock);
 
-       if (!common->ops || !common->ops->thread_exits
-        || common->ops->thread_exits(common) < 0) {
-               int i;
+       /* Eject media from all LUNs */
 
-               down_write(&common->filesem);
-               for (i = 0; i < ARRAY_SIZE(common->luns); i++) {
-                       struct fsg_lun *curlun = common->luns[i];
-                       if (!curlun || !fsg_lun_is_open(curlun))
-                               continue;
+       down_write(&common->filesem);
+       for (i = 0; i < ARRAY_SIZE(common->luns); i++) {
+               struct fsg_lun *curlun = common->luns[i];
 
+               if (curlun && fsg_lun_is_open(curlun))
                        fsg_lun_close(curlun);
-                       curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
-               }
-               up_write(&common->filesem);
        }
+       up_write(&common->filesem);
 
        /* Let fsg_unbind() know the thread has exited */
        complete_and_exit(&common->thread_notifier, 0);
@@ -2681,13 +2675,6 @@ void fsg_common_remove_luns(struct fsg_common *common)
 }
 EXPORT_SYMBOL_GPL(fsg_common_remove_luns);
 
-void fsg_common_set_ops(struct fsg_common *common,
-                       const struct fsg_operations *ops)
-{
-       common->ops = ops;
-}
-EXPORT_SYMBOL_GPL(fsg_common_set_ops);
-
 void fsg_common_free_buffers(struct fsg_common *common)
 {
        _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
index d390231..dc05ca0 100644 (file)
@@ -60,17 +60,6 @@ struct fsg_module_parameters {
 struct fsg_common;
 
 /* FSF callback functions */
-struct fsg_operations {
-       /*
-        * Callback function to call when thread exits.  If no
-        * callback is set or it returns value lower then zero MSF
-        * will force eject all LUNs it operates on (including those
-        * marked as non-removable or with prevent_medium_removal flag
-        * set).
-        */
-       int (*thread_exits)(struct fsg_common *common);
-};
-
 struct fsg_lun_opts {
        struct config_group group;
        struct fsg_lun *lun;
@@ -142,9 +131,6 @@ void fsg_common_remove_lun(struct fsg_lun *lun);
 
 void fsg_common_remove_luns(struct fsg_common *common);
 
-void fsg_common_set_ops(struct fsg_common *common,
-                       const struct fsg_operations *ops);
-
 int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg,
                          unsigned int id, const char *name,
                          const char **name_pfx);
index 8df244f..ea0da35 100644 (file)
@@ -555,6 +555,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
        size_t                  size;   /* Amount of data in a TX request. */
        size_t                  bytes_copied = 0;
        struct usb_request      *req;
+       int                     value;
 
        DBG(dev, "printer_write trying to send %d bytes\n", (int)len);
 
@@ -634,7 +635,11 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                        return -EAGAIN;
                }
 
-               if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
+               /* here, we unlock, and only unlock, to avoid deadlock. */
+               spin_unlock(&dev->lock);
+               value = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC);
+               spin_lock(&dev->lock);
+               if (value) {
                        list_add(&req->list, &dev->tx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
                        mutex_unlock(&dev->lock_printer_io);
index 540f1c4..79f70eb 100644 (file)
@@ -279,6 +279,7 @@ struct ffs_data {
        }                               file_perms;
 
        struct eventfd_ctx *ffs_eventfd;
+       struct workqueue_struct *io_completion_wq;
        bool no_disconnect;
        struct work_struct reset_work;
 
index 684900f..5c28bee 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/aio.h>
 #include <linux/uio.h>
 #include <linux/refcount.h>
-
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/moduleparam.h>
 
@@ -116,6 +116,7 @@ enum ep0_state {
 struct dev_data {
        spinlock_t                      lock;
        refcount_t                      count;
+       int                             udc_usage;
        enum ep0_state                  state;          /* P: lock */
        struct usb_gadgetfs_event       event [N_EVENT];
        unsigned                        ev_next;
@@ -513,9 +514,9 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
                INIT_WORK(&priv->work, ep_user_copy_worker);
                schedule_work(&priv->work);
        }
-       spin_unlock(&epdata->dev->lock);
 
        usb_ep_free_request(ep, req);
+       spin_unlock(&epdata->dev->lock);
        put_ep(epdata);
 }
 
@@ -939,9 +940,11 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
                        struct usb_request      *req = dev->req;
 
                        if ((retval = setup_req (ep, req, 0)) == 0) {
+                               ++dev->udc_usage;
                                spin_unlock_irq (&dev->lock);
                                retval = usb_ep_queue (ep, req, GFP_KERNEL);
                                spin_lock_irq (&dev->lock);
+                               --dev->udc_usage;
                        }
                        dev->state = STATE_DEV_CONNECTED;
 
@@ -983,11 +986,14 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
                                retval = -EIO;
                        else {
                                len = min (len, (size_t)dev->req->actual);
-// FIXME don't call this with the spinlock held ...
+                               ++dev->udc_usage;
+                               spin_unlock_irq(&dev->lock);
                                if (copy_to_user (buf, dev->req->buf, len))
                                        retval = -EFAULT;
                                else
                                        retval = len;
+                               spin_lock_irq(&dev->lock);
+                               --dev->udc_usage;
                                clean_req (dev->gadget->ep0, dev->req);
                                /* NOTE userspace can't yet choose to stall */
                        }
@@ -1131,6 +1137,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                        retval = setup_req (dev->gadget->ep0, dev->req, len);
                        if (retval == 0) {
                                dev->state = STATE_DEV_CONNECTED;
+                               ++dev->udc_usage;
                                spin_unlock_irq (&dev->lock);
                                if (copy_from_user (dev->req->buf, buf, len))
                                        retval = -EFAULT;
@@ -1142,6 +1149,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                                                GFP_KERNEL);
                                }
                                spin_lock_irq(&dev->lock);
+                               --dev->udc_usage;
                                if (retval < 0) {
                                        clean_req (dev->gadget->ep0, dev->req);
                                } else
@@ -1243,9 +1251,21 @@ static long dev_ioctl (struct file *fd, unsigned code, unsigned long value)
        struct usb_gadget       *gadget = dev->gadget;
        long ret = -ENOTTY;
 
-       if (gadget->ops->ioctl)
+       spin_lock_irq(&dev->lock);
+       if (dev->state == STATE_DEV_OPENED ||
+                       dev->state == STATE_DEV_UNBOUND) {
+               /* Not bound to a UDC */
+       } else if (gadget->ops->ioctl) {
+               ++dev->udc_usage;
+               spin_unlock_irq(&dev->lock);
+
                ret = gadget->ops->ioctl (gadget, code, value);
 
+               spin_lock_irq(&dev->lock);
+               --dev->udc_usage;
+       }
+       spin_unlock_irq(&dev->lock);
+
        return ret;
 }
 
@@ -1463,10 +1483,12 @@ delegate:
                                if (value < 0)
                                        break;
 
+                               ++dev->udc_usage;
                                spin_unlock (&dev->lock);
                                value = usb_ep_queue (gadget->ep0, dev->req,
                                                        GFP_KERNEL);
                                spin_lock (&dev->lock);
+                               --dev->udc_usage;
                                if (value < 0) {
                                        clean_req (gadget->ep0, dev->req);
                                        break;
@@ -1490,8 +1512,12 @@ delegate:
                req->length = value;
                req->zero = value < w_length;
 
+               ++dev->udc_usage;
                spin_unlock (&dev->lock);
                value = usb_ep_queue (gadget->ep0, req, GFP_KERNEL);
+               spin_lock(&dev->lock);
+               --dev->udc_usage;
+               spin_unlock(&dev->lock);
                if (value < 0) {
                        DBG (dev, "ep_queue --> %d\n", value);
                        req->status = 0;
@@ -1518,21 +1544,24 @@ static void destroy_ep_files (struct dev_data *dev)
                /* break link to FS */
                ep = list_first_entry (&dev->epfiles, struct ep_data, epfiles);
                list_del_init (&ep->epfiles);
+               spin_unlock_irq (&dev->lock);
+
                dentry = ep->dentry;
                ep->dentry = NULL;
                parent = d_inode(dentry->d_parent);
 
                /* break link to controller */
+               mutex_lock(&ep->lock);
                if (ep->state == STATE_EP_ENABLED)
                        (void) usb_ep_disable (ep->ep);
                ep->state = STATE_EP_UNBOUND;
                usb_ep_free_request (ep->ep, ep->req);
                ep->ep = NULL;
+               mutex_unlock(&ep->lock);
+
                wake_up (&ep->wait);
                put_ep (ep);
 
-               spin_unlock_irq (&dev->lock);
-
                /* break link to dcache */
                inode_lock(parent);
                d_delete (dentry);
@@ -1603,6 +1632,11 @@ gadgetfs_unbind (struct usb_gadget *gadget)
 
        spin_lock_irq (&dev->lock);
        dev->state = STATE_DEV_UNBOUND;
+       while (dev->udc_usage > 0) {
+               spin_unlock_irq(&dev->lock);
+               usleep_range(1000, 2000);
+               spin_lock_irq(&dev->lock);
+       }
        spin_unlock_irq (&dev->lock);
 
        destroy_ep_files (dev);
index e99ab57..fcba597 100644 (file)
@@ -107,15 +107,6 @@ static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
 
 FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
 
-static unsigned long msg_registered;
-static void msg_cleanup(void);
-
-static int msg_thread_exits(struct fsg_common *common)
-{
-       msg_cleanup();
-       return 0;
-}
-
 static int msg_do_config(struct usb_configuration *c)
 {
        struct fsg_opts *opts;
@@ -154,9 +145,6 @@ static struct usb_configuration msg_config_driver = {
 
 static int msg_bind(struct usb_composite_dev *cdev)
 {
-       static const struct fsg_operations ops = {
-               .thread_exits = msg_thread_exits,
-       };
        struct fsg_opts *opts;
        struct fsg_config config;
        int status;
@@ -173,8 +161,6 @@ static int msg_bind(struct usb_composite_dev *cdev)
        if (status)
                goto fail;
 
-       fsg_common_set_ops(opts->common, &ops);
-
        status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
        if (status)
                goto fail_set_cdev;
@@ -256,18 +242,12 @@ MODULE_LICENSE("GPL");
 
 static int __init msg_init(void)
 {
-       int ret;
-
-       ret = usb_composite_probe(&msg_driver);
-       set_bit(0, &msg_registered);
-
-       return ret;
+       return usb_composite_probe(&msg_driver);
 }
 module_init(msg_init);
 
-static void msg_cleanup(void)
+static void __exit msg_cleanup(void)
 {
-       if (test_and_clear_bit(0, &msg_registered))
-               usb_composite_unregister(&msg_driver);
+       usb_composite_unregister(&msg_driver);
 }
 module_exit(msg_cleanup);
index 7cd5c96..1e95670 100644 (file)
@@ -273,6 +273,7 @@ config USB_SNP_CORE
 config USB_SNP_UDC_PLAT
        tristate "Synopsys USB 2.0 Device controller"
        depends on USB_GADGET && OF && HAS_DMA
+       depends on EXTCON || EXTCON=n
        select USB_GADGET_DUALSPEED
        select USB_SNP_CORE
        default ARCH_BCM_IPROC
index 98d7140..a884c02 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/of_gpio.h>
 
 #include "atmel_usba_udc.h"
+#define USBA_VBUS_IRQFLAGS (IRQF_ONESHOT \
+                          | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING)
 
 #ifdef CONFIG_USB_GADGET_DEBUG_FS
 #include <linux/debugfs.h>
@@ -2361,7 +2363,7 @@ static int usba_udc_probe(struct platform_device *pdev)
                                        IRQ_NOAUTOEN);
                        ret = devm_request_threaded_irq(&pdev->dev,
                                        gpio_to_irq(udc->vbus_pin), NULL,
-                                       usba_vbus_irq_thread, IRQF_ONESHOT,
+                                       usba_vbus_irq_thread, USBA_VBUS_IRQFLAGS,
                                        "atmel_usba_udc", udc);
                        if (ret) {
                                udc->vbus_pin = -ENODEV;
index 75c51ca..d41d07a 100644 (file)
@@ -1320,8 +1320,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
        udc->dev.driver = &driver->driver;
        udc->gadget->dev.driver = &driver->driver;
 
-       if (driver->max_speed < udc->gadget->max_speed)
-               usb_gadget_udc_set_speed(udc, driver->max_speed);
+       usb_gadget_udc_set_speed(udc, driver->max_speed);
 
        ret = driver->bind(udc->gadget, driver);
        if (ret)
index a030d79..b17618a 100644 (file)
@@ -237,6 +237,8 @@ struct dummy_hcd {
 
        struct usb_device               *udev;
        struct list_head                urbp_list;
+       struct urbp                     *next_frame_urbp;
+
        u32                             stream_en_ep;
        u8                              num_stream[30 / 2];
 
@@ -253,11 +255,13 @@ struct dummy {
         */
        struct dummy_ep                 ep[DUMMY_ENDPOINTS];
        int                             address;
+       int                             callback_usage;
        struct usb_gadget               gadget;
        struct usb_gadget_driver        *driver;
        struct dummy_request            fifo_req;
        u8                              fifo_buf[FIFO_SIZE];
        u16                             devstatus;
+       unsigned                        ints_enabled:1;
        unsigned                        udc_suspended:1;
        unsigned                        pullup:1;
 
@@ -375,11 +379,10 @@ static void set_link_state_by_speed(struct dummy_hcd *dum_hcd)
                             USB_PORT_STAT_CONNECTION) == 0)
                                dum_hcd->port_status |=
                                        (USB_PORT_STAT_C_CONNECTION << 16);
-                       if ((dum_hcd->port_status &
-                            USB_PORT_STAT_ENABLE) == 1 &&
-                               (dum_hcd->port_status &
-                                USB_SS_PORT_LS_U0) == 1 &&
-                               dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
+                       if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) &&
+                           (dum_hcd->port_status &
+                            USB_PORT_STAT_LINK_STATE) == USB_SS_PORT_LS_U0 &&
+                           dum_hcd->rh_state != DUMMY_RH_SUSPENDED)
                                dum_hcd->active = 1;
                }
        } else {
@@ -440,18 +443,27 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
                                (~dum_hcd->old_status) & dum_hcd->port_status;
 
                /* Report reset and disconnect events to the driver */
-               if (dum->driver && (disconnect || reset)) {
+               if (dum->ints_enabled && (disconnect || reset)) {
                        stop_activity(dum);
+                       ++dum->callback_usage;
+                       spin_unlock(&dum->lock);
                        if (reset)
                                usb_gadget_udc_reset(&dum->gadget, dum->driver);
                        else
                                dum->driver->disconnect(&dum->gadget);
+                       spin_lock(&dum->lock);
+                       --dum->callback_usage;
                }
-       } else if (dum_hcd->active != dum_hcd->old_active) {
+       } else if (dum_hcd->active != dum_hcd->old_active &&
+                       dum->ints_enabled) {
+               ++dum->callback_usage;
+               spin_unlock(&dum->lock);
                if (dum_hcd->old_active && dum->driver->suspend)
                        dum->driver->suspend(&dum->gadget);
                else if (!dum_hcd->old_active &&  dum->driver->resume)
                        dum->driver->resume(&dum->gadget);
+               spin_lock(&dum->lock);
+               --dum->callback_usage;
        }
 
        dum_hcd->old_status = dum_hcd->port_status;
@@ -972,8 +984,11 @@ static int dummy_udc_start(struct usb_gadget *g,
         * can't enumerate without help from the driver we're binding.
         */
 
+       spin_lock_irq(&dum->lock);
        dum->devstatus = 0;
        dum->driver = driver;
+       dum->ints_enabled = 1;
+       spin_unlock_irq(&dum->lock);
 
        return 0;
 }
@@ -984,6 +999,16 @@ static int dummy_udc_stop(struct usb_gadget *g)
        struct dummy            *dum = dum_hcd->dum;
 
        spin_lock_irq(&dum->lock);
+       dum->ints_enabled = 0;
+       stop_activity(dum);
+
+       /* emulate synchronize_irq(): wait for callbacks to finish */
+       while (dum->callback_usage > 0) {
+               spin_unlock_irq(&dum->lock);
+               usleep_range(1000, 2000);
+               spin_lock_irq(&dum->lock);
+       }
+
        dum->driver = NULL;
        spin_unlock_irq(&dum->lock);
 
@@ -1037,7 +1062,12 @@ static int dummy_udc_probe(struct platform_device *pdev)
        memzero_explicit(&dum->gadget, sizeof(struct usb_gadget));
        dum->gadget.name = gadget_name;
        dum->gadget.ops = &dummy_ops;
-       dum->gadget.max_speed = USB_SPEED_SUPER;
+       if (mod_data.is_super_speed)
+               dum->gadget.max_speed = USB_SPEED_SUPER;
+       else if (mod_data.is_high_speed)
+               dum->gadget.max_speed = USB_SPEED_HIGH;
+       else
+               dum->gadget.max_speed = USB_SPEED_FULL;
 
        dum->gadget.dev.parent = &pdev->dev;
        init_dummy_udc_hw(dum);
@@ -1246,6 +1276,8 @@ static int dummy_urb_enqueue(
 
        list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list);
        urb->hcpriv = urbp;
+       if (!dum_hcd->next_frame_urbp)
+               dum_hcd->next_frame_urbp = urbp;
        if (usb_pipetype(urb->pipe) == PIPE_CONTROL)
                urb->error_count = 1;           /* mark as a new urb */
 
@@ -1521,6 +1553,8 @@ static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address)
        if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ?
                        dum->ss_hcd : dum->hs_hcd)))
                return NULL;
+       if (!dum->ints_enabled)
+               return NULL;
        if ((address & ~USB_DIR_IN) == 0)
                return &dum->ep[0];
        for (i = 1; i < DUMMY_ENDPOINTS; i++) {
@@ -1762,6 +1796,7 @@ static void dummy_timer(unsigned long _dum_hcd)
                spin_unlock_irqrestore(&dum->lock, flags);
                return;
        }
+       dum_hcd->next_frame_urbp = NULL;
 
        for (i = 0; i < DUMMY_ENDPOINTS; i++) {
                if (!ep_info[i].name)
@@ -1778,6 +1813,10 @@ restart:
                int                     type;
                int                     status = -EINPROGRESS;
 
+               /* stop when we reach URBs queued after the timer interrupt */
+               if (urbp == dum_hcd->next_frame_urbp)
+                       break;
+
                urb = urbp->urb;
                if (urb->unlinked)
                        goto return_urb;
@@ -1857,10 +1896,12 @@ restart:
                         * until setup() returns; no reentrancy issues etc.
                         */
                        if (value > 0) {
+                               ++dum->callback_usage;
                                spin_unlock(&dum->lock);
                                value = dum->driver->setup(&dum->gadget,
                                                &setup);
                                spin_lock(&dum->lock);
+                               --dum->callback_usage;
 
                                if (value >= 0) {
                                        /* no delays (max 64KB data stage) */
@@ -2561,8 +2602,6 @@ static struct hc_driver dummy_hcd = {
        .product_desc =         "Dummy host controller",
        .hcd_priv_size =        sizeof(struct dummy_hcd),
 
-       .flags =                HCD_USB3 | HCD_SHARED,
-
        .reset =                dummy_setup,
        .start =                dummy_start,
        .stop =                 dummy_stop,
@@ -2591,8 +2630,12 @@ static int dummy_hcd_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
        dum = *((void **)dev_get_platdata(&pdev->dev));
 
-       if (!mod_data.is_super_speed)
+       if (mod_data.is_super_speed)
+               dummy_hcd.flags = HCD_USB3 | HCD_SHARED;
+       else if (mod_data.is_high_speed)
                dummy_hcd.flags = HCD_USB2;
+       else
+               dummy_hcd.flags = HCD_USB11;
        hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev));
        if (!hs_hcd)
                return -ENOMEM;
index df37c1e..63a2061 100644 (file)
@@ -1038,7 +1038,7 @@ static int usb3_write_pipe(struct renesas_usb3_ep *usb3_ep,
                        usb3_ep->ep.maxpacket);
        u8 *buf = usb3_req->req.buf + usb3_req->req.actual;
        u32 tmp = 0;
-       bool is_last;
+       bool is_last = !len ? true : false;
 
        if (usb3_wait_pipe_status(usb3_ep, PX_STA_BUFSTS) < 0)
                return -EBUSY;
@@ -1059,7 +1059,8 @@ static int usb3_write_pipe(struct renesas_usb3_ep *usb3_ep,
                usb3_write(usb3, tmp, fifo_reg);
        }
 
-       is_last = usb3_is_transfer_complete(usb3_ep, usb3_req);
+       if (!is_last)
+               is_last = usb3_is_transfer_complete(usb3_ep, usb3_req);
        /* Send the data */
        usb3_set_px_con_send(usb3_ep, len, is_last);
 
@@ -1150,7 +1151,8 @@ static void usb3_start_pipe0(struct renesas_usb3_ep *usb3_ep,
                usb3_set_p0_con_for_ctrl_read_data(usb3);
        } else {
                usb3_clear_bit(usb3, P0_MOD_DIR, USB3_P0_MOD);
-               usb3_set_p0_con_for_ctrl_write_data(usb3);
+               if (usb3_req->req.length)
+                       usb3_set_p0_con_for_ctrl_write_data(usb3);
        }
 
        usb3_p0_xfer(usb3_ep, usb3_req);
@@ -2053,7 +2055,16 @@ static u32 usb3_calc_ramarea(int ram_size)
 static u32 usb3_calc_rammap_val(struct renesas_usb3_ep *usb3_ep,
                                const struct usb_endpoint_descriptor *desc)
 {
-       return usb3_ep->rammap_val | PN_RAMMAP_MPKT(usb_endpoint_maxp(desc));
+       int i;
+       const u32 max_packet_array[] = {8, 16, 32, 64, 512};
+       u32 mpkt = PN_RAMMAP_MPKT(1024);
+
+       for (i = 0; i < ARRAY_SIZE(max_packet_array); i++) {
+               if (usb_endpoint_maxp(desc) <= max_packet_array[i])
+                       mpkt = PN_RAMMAP_MPKT(max_packet_array[i]);
+       }
+
+       return usb3_ep->rammap_val | mpkt;
 }
 
 static int usb3_enable_pipe_n(struct renesas_usb3_ep *usb3_ep,
index 658d9d1..6dda362 100644 (file)
@@ -447,7 +447,7 @@ static int usb_asmedia_wait_write(struct pci_dev *pdev)
                if ((value & ASMT_CONTROL_WRITE_BIT) == 0)
                        return 0;
 
-               usleep_range(40, 60);
+               udelay(50);
        }
 
        dev_warn(&pdev->dev, "%s: check_write_ready timeout", __func__);
@@ -1022,7 +1022,7 @@ EXPORT_SYMBOL_GPL(usb_disable_xhci_ports);
  *
  * Takes care of the handoff between the Pre-OS (i.e. BIOS) and the OS.
  * It signals to the BIOS that the OS wants control of the host controller,
- * and then waits 5 seconds for the BIOS to hand over control.
+ * and then waits 1 second for the BIOS to hand over control.
  * If we timeout, assume the BIOS is broken and take control anyway.
  */
 static void quirk_usb_handoff_xhci(struct pci_dev *pdev)
@@ -1069,9 +1069,9 @@ static void quirk_usb_handoff_xhci(struct pci_dev *pdev)
        if (val & XHCI_HC_BIOS_OWNED) {
                writel(val | XHCI_HC_OS_OWNED, base + ext_cap_offset);
 
-               /* Wait for 5 seconds with 10 microsecond polling interval */
+               /* Wait for 1 second with 10 microsecond polling interval */
                timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED,
-                               0, 5000, 10);
+                               0, 1000000, 10);
 
                /* Assume a buggy BIOS and take HC ownership anyway */
                if (timeout) {
@@ -1100,7 +1100,7 @@ hc_init:
         * operational or runtime registers.  Wait 5 seconds and no more.
         */
        timeout = handshake(op_reg_base + XHCI_STS_OFFSET, XHCI_STS_CNR, 0,
-                       5000, 10);
+                       5000000, 10);
        /* Assume a buggy HC and start HC initialization anyway */
        if (timeout) {
                val = readl(op_reg_base + XHCI_STS_OFFSET);
index ad89a6d..da9158f 100644 (file)
@@ -112,7 +112,7 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
 
        /* If PSI table exists, add the custom speed attributes from it */
        if (usb3_1 && xhci->usb3_rhub.psi_count) {
-               u32 ssp_cap_base, bm_attrib, psi;
+               u32 ssp_cap_base, bm_attrib, psi, psi_mant, psi_exp;
                int offset;
 
                ssp_cap_base = USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE;
@@ -139,6 +139,15 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
                for (i = 0; i < xhci->usb3_rhub.psi_count; i++) {
                        psi = xhci->usb3_rhub.psi[i];
                        psi &= ~USB_SSP_SUBLINK_SPEED_RSVD;
+                       psi_exp = XHCI_EXT_PORT_PSIE(psi);
+                       psi_mant = XHCI_EXT_PORT_PSIM(psi);
+
+                       /* Shift to Gbps and set SSP Link BIT(14) if 10Gpbs */
+                       for (; psi_exp < 3; psi_exp++)
+                               psi_mant /= 1000;
+                       if (psi_mant >= 10)
+                               psi |= BIT(14);
+
                        if ((psi & PLT_MASK) == PLT_SYM) {
                        /* Symmetric, create SSA RX and TX from one PSI entry */
                                put_unaligned_le32(psi, &buf[offset]);
@@ -1506,9 +1515,6 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
                                t2 |= PORT_WKOC_E | PORT_WKCONN_E;
                                t2 &= ~PORT_WKDISC_E;
                        }
-                       if ((xhci->quirks & XHCI_U2_DISABLE_WAKE) &&
-                           (hcd->speed < HCD_USB3))
-                               t2 &= ~PORT_WAKE_BITS;
                } else
                        t2 &= ~PORT_WAKE_BITS;
 
index 8071c8f..76f3929 100644 (file)
 #define PCI_DEVICE_ID_INTEL_APL_XHCI                   0x5aa8
 #define PCI_DEVICE_ID_INTEL_DNV_XHCI                   0x19d0
 
-#define PCI_DEVICE_ID_AMD_PROMONTORYA_4                        0x43b9
-#define PCI_DEVICE_ID_AMD_PROMONTORYA_3                        0x43ba
-#define PCI_DEVICE_ID_AMD_PROMONTORYA_2                        0x43bb
-#define PCI_DEVICE_ID_AMD_PROMONTORYA_1                        0x43bc
-
 #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI               0x1142
 
 static const char hcd_name[] = "xhci_hcd";
@@ -142,13 +137,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        if (pdev->vendor == PCI_VENDOR_ID_AMD)
                xhci->quirks |= XHCI_TRUST_TX_LENGTH;
 
-       if ((pdev->vendor == PCI_VENDOR_ID_AMD) &&
-               ((pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4) ||
-               (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_3) ||
-               (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_2) ||
-               (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_1)))
-               xhci->quirks |= XHCI_U2_DISABLE_WAKE;
-
        if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
                xhci->quirks |= XHCI_LPM_SUPPORT;
                xhci->quirks |= XHCI_INTEL_HOST;
index 163bafd..1cb6eae 100644 (file)
@@ -178,14 +178,18 @@ static int xhci_plat_probe(struct platform_device *pdev)
         * 2. xhci_plat is child of a device from firmware (dwc3-plat)
         * 3. xhci_plat is grandchild of a pci device (dwc3-pci)
         */
-       sysdev = &pdev->dev;
-       if (sysdev->parent && !sysdev->of_node && sysdev->parent->of_node)
-               sysdev = sysdev->parent;
+       for (sysdev = &pdev->dev; sysdev; sysdev = sysdev->parent) {
+               if (is_of_node(sysdev->fwnode) ||
+                       is_acpi_device_node(sysdev->fwnode))
+                       break;
 #ifdef CONFIG_PCI
-       else if (sysdev->parent && sysdev->parent->parent &&
-                sysdev->parent->parent->bus == &pci_bus_type)
-               sysdev = sysdev->parent->parent;
+               else if (sysdev->bus == &pci_bus_type)
+                       break;
 #endif
+       }
+
+       if (!sysdev)
+               sysdev = &pdev->dev;
 
        /* Try to set 64-bit DMA first */
        if (WARN_ON(!sysdev->dma_mask))
index b2ff1ff..ee198ea 100644 (file)
@@ -1703,7 +1703,8 @@ static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        if (xhci->quirks & XHCI_MTK_HOST) {
                ret = xhci_mtk_add_ep_quirk(hcd, udev, ep);
                if (ret < 0) {
-                       xhci_free_endpoint_ring(xhci, virt_dev, ep_index);
+                       xhci_ring_free(xhci, virt_dev->eps[ep_index].new_ring);
+                       virt_dev->eps[ep_index].new_ring = NULL;
                        return ret;
                }
        }
index 2abaa4d..2b48aa4 100644 (file)
@@ -735,6 +735,8 @@ struct xhci_ep_ctx {
 #define EP_MAXPSTREAMS(p)      (((p) << 10) & EP_MAXPSTREAMS_MASK)
 /* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */
 #define        EP_HAS_LSA              (1 << 15)
+/* hosts with LEC=1 use bits 31:24 as ESIT high bits. */
+#define CTX_TO_MAX_ESIT_PAYLOAD_HI(p)  (((p) >> 24) & 0xff)
 
 /* ep_info2 bitmasks */
 /*
@@ -1681,7 +1683,7 @@ struct xhci_bus_state {
 
 static inline unsigned int hcd_index(struct usb_hcd *hcd)
 {
-       if (hcd->speed == HCD_USB3)
+       if (hcd->speed >= HCD_USB3)
                return 0;
        else
                return 1;
@@ -1826,7 +1828,7 @@ struct xhci_hcd {
 /* For controller with a broken Port Disable implementation */
 #define XHCI_BROKEN_PORT_PED   (1 << 25)
 #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26)
-#define XHCI_U2_DISABLE_WAKE   (1 << 27)
+/* Reserved. It was XHCI_U2_DISABLE_WAKE */
 #define XHCI_ASMEDIA_MODIFY_FLOWCONTROL        (1 << 28)
 
        unsigned int            num_active_eps;
@@ -2540,8 +2542,8 @@ static inline const char *xhci_decode_ep_context(u32 info, u32 info2, u64 deq,
        u8 lsa;
        u8 hid;
 
-       esit = EP_MAX_ESIT_PAYLOAD_HI(info) << 16 |
-               EP_MAX_ESIT_PAYLOAD_LO(tx_info);
+       esit = CTX_TO_MAX_ESIT_PAYLOAD_HI(info) << 16 |
+               CTX_TO_MAX_ESIT_PAYLOAD(tx_info);
 
        ep_state = info & EP_STATE_MASK;
        max_pstr = info & EP_MAXPSTREAMS_MASK;
index d1af831..68f2690 100644 (file)
@@ -282,11 +282,26 @@ static void usbhsf_fifo_clear(struct usbhs_pipe *pipe,
                              struct usbhs_fifo *fifo)
 {
        struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+       int ret = 0;
 
-       if (!usbhs_pipe_is_dcp(pipe))
-               usbhsf_fifo_barrier(priv, fifo);
+       if (!usbhs_pipe_is_dcp(pipe)) {
+               /*
+                * This driver checks the pipe condition first to avoid -EBUSY
+                * from usbhsf_fifo_barrier() with about 10 msec delay in
+                * the interrupt handler if the pipe is RX direction and empty.
+                */
+               if (usbhs_pipe_is_dir_in(pipe))
+                       ret = usbhs_pipe_is_accessible(pipe);
+               if (!ret)
+                       ret = usbhsf_fifo_barrier(priv, fifo);
+       }
 
-       usbhs_write(priv, fifo->ctr, BCLR);
+       /*
+        * if non-DCP pipe, this driver should set BCLR when
+        * usbhsf_fifo_barrier() returns 0.
+        */
+       if (!ret)
+               usbhs_write(priv, fifo->ctr, BCLR);
 }
 
 static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv,
index 1a59f33..a3ccb89 100644 (file)
@@ -834,13 +834,25 @@ Retry_Sense:
                        if (result == USB_STOR_TRANSPORT_GOOD) {
                                srb->result = SAM_STAT_GOOD;
                                srb->sense_buffer[0] = 0x0;
+                       }
+
+                       /*
+                        * ATA-passthru commands use sense data to report
+                        * the command completion status, and often devices
+                        * return Check Condition status when nothing is
+                        * wrong.
+                        */
+                       else if (srb->cmnd[0] == ATA_16 ||
+                                       srb->cmnd[0] == ATA_12) {
+                               /* leave the data alone */
+                       }
 
                        /*
                         * If there was a problem, report an unspecified
                         * hardware error to prevent the higher layers from
                         * entering an infinite retry loop.
                         */
-                       else {
+                       else {
                                srb->result = DID_ERROR << 16;
                                if ((sshdr.response_code & 0x72) == 0x72)
                                        srb->sense_buffer[1] = HARDWARE_ERROR;
index f58caa9..a155cd0 100644 (file)
@@ -9,7 +9,8 @@ static int uas_is_interface(struct usb_host_interface *intf)
                intf->desc.bInterfaceProtocol == USB_PR_UAS);
 }
 
-static int uas_find_uas_alt_setting(struct usb_interface *intf)
+static struct usb_host_interface *uas_find_uas_alt_setting(
+               struct usb_interface *intf)
 {
        int i;
 
@@ -17,10 +18,10 @@ static int uas_find_uas_alt_setting(struct usb_interface *intf)
                struct usb_host_interface *alt = &intf->altsetting[i];
 
                if (uas_is_interface(alt))
-                       return alt->desc.bAlternateSetting;
+                       return alt;
        }
 
-       return -ENODEV;
+       return NULL;
 }
 
 static int uas_find_endpoints(struct usb_host_interface *alt,
@@ -58,14 +59,14 @@ static int uas_use_uas_driver(struct usb_interface *intf,
        struct usb_device *udev = interface_to_usbdev(intf);
        struct usb_hcd *hcd = bus_to_hcd(udev->bus);
        unsigned long flags = id->driver_info;
-       int r, alt;
-
+       struct usb_host_interface *alt;
+       int r;
 
        alt = uas_find_uas_alt_setting(intf);
-       if (alt < 0)
+       if (!alt)
                return 0;
 
-       r = uas_find_endpoints(&intf->altsetting[alt], eps);
+       r = uas_find_endpoints(alt, eps);
        if (r < 0)
                return 0;
 
index cfb1e3b..63cf981 100644 (file)
@@ -873,14 +873,14 @@ MODULE_DEVICE_TABLE(usb, uas_usb_ids);
 static int uas_switch_interface(struct usb_device *udev,
                                struct usb_interface *intf)
 {
-       int alt;
+       struct usb_host_interface *alt;
 
        alt = uas_find_uas_alt_setting(intf);
-       if (alt < 0)
-               return alt;
+       if (!alt)
+               return -ENODEV;
 
-       return usb_set_interface(udev,
-                       intf->altsetting[0].desc.bInterfaceNumber, alt);
+       return usb_set_interface(udev, alt->desc.bInterfaceNumber,
+                       alt->desc.bAlternateSetting);
 }
 
 static int uas_configure_endpoints(struct uas_dev_info *devinfo)
index 5a70c33..eb06d88 100644 (file)
@@ -1459,6 +1459,13 @@ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_SANE_SENSE ),
 
+/* Reported by Kris Lindgren <kris.lindgren@gmail.com> */
+UNUSUAL_DEV( 0x0bc2, 0x3332, 0x0000, 0x9999,
+               "Seagate",
+               "External",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_NO_WP_DETECT ),
+
 UNUSUAL_DEV(  0x0d49, 0x7310, 0x0000, 0x9999,
                "Maxtor",
                "USB to SATA",
index 35a1e77..9a53912 100644 (file)
@@ -825,6 +825,8 @@ static int hwarc_probe(struct usb_interface *iface,
 
        if (iface->cur_altsetting->desc.bNumEndpoints < 1)
                return -ENODEV;
+       if (!usb_endpoint_xfer_int(&iface->cur_altsetting->endpoint[0].desc))
+               return -ENODEV;
 
        result = -ENOMEM;
        uwb_rc = uwb_rc_alloc();
index 01c20a2..39dd4ef 100644 (file)
@@ -302,18 +302,22 @@ static int uwbd(void *param)
 /** Start the UWB daemon */
 void uwbd_start(struct uwb_rc *rc)
 {
-       rc->uwbd.task = kthread_run(uwbd, rc, "uwbd");
-       if (rc->uwbd.task == NULL)
+       struct task_struct *task = kthread_run(uwbd, rc, "uwbd");
+       if (IS_ERR(task)) {
+               rc->uwbd.task = NULL;
                printk(KERN_ERR "UWB: Cannot start management daemon; "
                       "UWB won't work\n");
-       else
+       } else {
+               rc->uwbd.task = task;
                rc->uwbd.pid = rc->uwbd.task->pid;
+       }
 }
 
 /* Stop the UWB daemon and free any unprocessed events */
 void uwbd_stop(struct uwb_rc *rc)
 {
-       kthread_stop(rc->uwbd.task);
+       if (rc->uwbd.task)
+               kthread_stop(rc->uwbd.task);
        uwbd_flush(rc);
 }
 
index ce7181e..2a46762 100644 (file)
@@ -54,7 +54,7 @@ typedef struct {
        int size;                       /* size of magic/mask */
        char *magic;                    /* magic or filename extension */
        char *mask;                     /* mask, NULL for exact match */
-       char *interpreter;              /* filename of interpreter */
+       const char *interpreter;        /* filename of interpreter */
        char *name;
        struct dentry *dentry;
        struct file *interp_file;
@@ -131,27 +131,26 @@ static int load_misc_binary(struct linux_binprm *bprm)
 {
        Node *fmt;
        struct file *interp_file = NULL;
-       char iname[BINPRM_BUF_SIZE];
-       const char *iname_addr = iname;
        int retval;
        int fd_binary = -1;
 
        retval = -ENOEXEC;
        if (!enabled)
-               goto ret;
+               return retval;
 
        /* to keep locking time low, we copy the interpreter string */
        read_lock(&entries_lock);
        fmt = check_file(bprm);
        if (fmt)
-               strlcpy(iname, fmt->interpreter, BINPRM_BUF_SIZE);
+               dget(fmt->dentry);
        read_unlock(&entries_lock);
        if (!fmt)
-               goto ret;
+               return retval;
 
        /* Need to be able to load the file after exec */
+       retval = -ENOENT;
        if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE)
-               return -ENOENT;
+               goto ret;
 
        if (!(fmt->flags & MISC_FMT_PRESERVE_ARGV0)) {
                retval = remove_arg_zero(bprm);
@@ -195,22 +194,22 @@ static int load_misc_binary(struct linux_binprm *bprm)
        bprm->argc++;
 
        /* add the interp as argv[0] */
-       retval = copy_strings_kernel(1, &iname_addr, bprm);
+       retval = copy_strings_kernel(1, &fmt->interpreter, bprm);
        if (retval < 0)
                goto error;
        bprm->argc++;
 
        /* Update interp in case binfmt_script needs it. */
-       retval = bprm_change_interp(iname, bprm);
+       retval = bprm_change_interp(fmt->interpreter, bprm);
        if (retval < 0)
                goto error;
 
-       if (fmt->flags & MISC_FMT_OPEN_FILE && fmt->interp_file) {
+       if (fmt->flags & MISC_FMT_OPEN_FILE) {
                interp_file = filp_clone_open(fmt->interp_file);
                if (!IS_ERR(interp_file))
                        deny_write_access(interp_file);
        } else {
-               interp_file = open_exec(iname);
+               interp_file = open_exec(fmt->interpreter);
        }
        retval = PTR_ERR(interp_file);
        if (IS_ERR(interp_file))
@@ -238,6 +237,7 @@ static int load_misc_binary(struct linux_binprm *bprm)
                goto error;
 
 ret:
+       dput(fmt->dentry);
        return retval;
 error:
        if (fd_binary > 0)
@@ -594,8 +594,13 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
 
 static void bm_evict_inode(struct inode *inode)
 {
+       Node *e = inode->i_private;
+
+       if (e->flags & MISC_FMT_OPEN_FILE)
+               filp_close(e->interp_file, NULL);
+
        clear_inode(inode);
-       kfree(inode->i_private);
+       kfree(e);
 }
 
 static void kill_node(Node *e)
@@ -603,24 +608,14 @@ static void kill_node(Node *e)
        struct dentry *dentry;
 
        write_lock(&entries_lock);
-       dentry = e->dentry;
-       if (dentry) {
-               list_del_init(&e->list);
-               e->dentry = NULL;
-       }
+       list_del_init(&e->list);
        write_unlock(&entries_lock);
 
-       if ((e->flags & MISC_FMT_OPEN_FILE) && e->interp_file) {
-               filp_close(e->interp_file, NULL);
-               e->interp_file = NULL;
-       }
-
-       if (dentry) {
-               drop_nlink(d_inode(dentry));
-               d_drop(dentry);
-               dput(dentry);
-               simple_release_fs(&bm_mnt, &entry_count);
-       }
+       dentry = e->dentry;
+       drop_nlink(d_inode(dentry));
+       d_drop(dentry);
+       dput(dentry);
+       simple_release_fs(&bm_mnt, &entry_count);
 }
 
 /* /<entry> */
@@ -665,7 +660,8 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
                root = file_inode(file)->i_sb->s_root;
                inode_lock(d_inode(root));
 
-               kill_node(e);
+               if (!list_empty(&e->list))
+                       kill_node(e);
 
                inode_unlock(d_inode(root));
                break;
@@ -794,7 +790,7 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer,
                inode_lock(d_inode(root));
 
                while (!list_empty(&entries))
-                       kill_node(list_entry(entries.next, Node, list));
+                       kill_node(list_first_entry(&entries, Node, list));
 
                inode_unlock(d_inode(root));
                break;
index afdf4e3..7cde3f4 100644 (file)
@@ -19,7 +19,6 @@ static int load_script(struct linux_binprm *bprm)
        const char *i_arg, *i_name;
        char *cp;
        struct file *file;
-       char interp[BINPRM_BUF_SIZE];
        int retval;
 
        if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
@@ -55,7 +54,7 @@ static int load_script(struct linux_binprm *bprm)
                        break;
        }
        for (cp = bprm->buf+2; (*cp == ' ') || (*cp == '\t'); cp++);
-       if (*cp == '\0') 
+       if (*cp == '\0')
                return -ENOEXEC; /* No interpreter name found */
        i_name = cp;
        i_arg = NULL;
@@ -65,7 +64,6 @@ static int load_script(struct linux_binprm *bprm)
                *cp++ = '\0';
        if (*cp)
                i_arg = cp;
-       strcpy (interp, i_name);
        /*
         * OK, we've parsed out the interpreter name and
         * (optional) argument.
@@ -80,24 +78,27 @@ static int load_script(struct linux_binprm *bprm)
        if (retval)
                return retval;
        retval = copy_strings_kernel(1, &bprm->interp, bprm);
-       if (retval < 0) return retval; 
+       if (retval < 0)
+               return retval;
        bprm->argc++;
        if (i_arg) {
                retval = copy_strings_kernel(1, &i_arg, bprm);
-               if (retval < 0) return retval; 
+               if (retval < 0)
+                       return retval;
                bprm->argc++;
        }
        retval = copy_strings_kernel(1, &i_name, bprm);
-       if (retval) return retval; 
+       if (retval)
+               return retval;
        bprm->argc++;
-       retval = bprm_change_interp(interp, bprm);
+       retval = bprm_change_interp(i_name, bprm);
        if (retval < 0)
                return retval;
 
        /*
         * OK, now restart the process with the interpreter's dentry.
         */
-       file = open_exec(interp);
+       file = open_exec(i_name);
        if (IS_ERR(file))
                return PTR_ERR(file);
 
index 899ddae..8fc6903 100644 (file)
@@ -722,7 +722,7 @@ struct btrfs_delayed_root;
  * Indicate that a whole-filesystem exclusive operation is running
  * (device replace, resize, device add/delete, balance)
  */
-#define BTRFS_FS_EXCL_OP                       14
+#define BTRFS_FS_EXCL_OP                       16
 
 struct btrfs_fs_info {
        u8 fsid[BTRFS_FSID_SIZE];
index 12ab19a..970190c 100644 (file)
@@ -2801,7 +2801,7 @@ static int submit_extent_page(unsigned int opf, struct extent_io_tree *tree,
                }
        }
 
-       bio = btrfs_bio_alloc(bdev, sector << 9);
+       bio = btrfs_bio_alloc(bdev, (u64)sector << 9);
        bio_add_page(bio, page, page_size, offset);
        bio->bi_end_io = end_io_func;
        bio->bi_private = tree;
index 84edfc6..f23c820 100644 (file)
@@ -734,12 +734,13 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
                        inode = req->r_inode;
                        ihold(inode);
                } else {
-                       /* req->r_dentry is non-null for LSSNAP request.
-                        * fall-thru */
-                       WARN_ON_ONCE(!req->r_dentry);
+                       /* req->r_dentry is non-null for LSSNAP request */
+                       rcu_read_lock();
+                       inode = get_nonsnap_parent(req->r_dentry);
+                       rcu_read_unlock();
+                       dout("__choose_mds using snapdir's parent %p\n", inode);
                }
-       }
-       if (!inode && req->r_dentry) {
+       } else if (req->r_dentry) {
                /* ignore race with rename; old or new d_parent is okay */
                struct dentry *parent;
                struct inode *dir;
index 1ffc8b4..7fc0b85 100644 (file)
@@ -374,12 +374,10 @@ static int build_snap_context(struct ceph_snap_realm *realm,
             realm->ino, realm, snapc, snapc->seq,
             (unsigned int) snapc->num_snaps);
 
-       if (realm->cached_context) {
-               ceph_put_snap_context(realm->cached_context);
-               /* queue realm for cap_snap creation */
-               list_add_tail(&realm->dirty_item, dirty_realms);
-       }
+       ceph_put_snap_context(realm->cached_context);
        realm->cached_context = snapc;
+       /* queue realm for cap_snap creation */
+       list_add_tail(&realm->dirty_item, dirty_realms);
        return 0;
 
 fail:
index ac34d97..5470d3c 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1410,7 +1410,7 @@ static void free_bprm(struct linux_binprm *bprm)
        kfree(bprm);
 }
 
-int bprm_change_interp(char *interp, struct linux_binprm *bprm)
+int bprm_change_interp(const char *interp, struct linux_binprm *bprm)
 {
        /* If a binfmt changed the interp, free it first. */
        if (bprm->interp != bprm->filename)
index 54059b1..3b601f1 100644 (file)
@@ -468,7 +468,9 @@ static inline int may_write_real(struct file *file)
 
        /* File refers to upper, writable layer? */
        upperdentry = d_real(dentry, NULL, 0, D_REAL_UPPER);
-       if (upperdentry && file_inode(file) == d_inode(upperdentry))
+       if (upperdentry &&
+           (file_inode(file) == d_inode(upperdentry) ||
+            file_inode(file) == d_inode(dentry)))
                return 0;
 
        /* Lower layer: can't write to real file, sorry... */
index aad97b3..c441f93 100644 (file)
@@ -561,10 +561,8 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c)
                c->tmpfile = true;
                err = ovl_copy_up_locked(c);
        } else {
-               err = -EIO;
-               if (lock_rename(c->workdir, c->destdir) != NULL) {
-                       pr_err("overlayfs: failed to lock workdir+upperdir\n");
-               } else {
+               err = ovl_lock_rename_workdir(c->workdir, c->destdir);
+               if (!err) {
                        err = ovl_copy_up_locked(c);
                        unlock_rename(c->workdir, c->destdir);
                }
index 3309b19..cc961a3 100644 (file)
@@ -216,26 +216,6 @@ out_unlock:
        return err;
 }
 
-static int ovl_lock_rename_workdir(struct dentry *workdir,
-                                  struct dentry *upperdir)
-{
-       /* Workdir should not be the same as upperdir */
-       if (workdir == upperdir)
-               goto err;
-
-       /* Workdir should not be subdir of upperdir and vice versa */
-       if (lock_rename(workdir, upperdir) != NULL)
-               goto err_unlock;
-
-       return 0;
-
-err_unlock:
-       unlock_rename(workdir, upperdir);
-err:
-       pr_err("overlayfs: failed to lock workdir+upperdir\n");
-       return -EIO;
-}
-
 static struct dentry *ovl_clear_empty(struct dentry *dentry,
                                      struct list_head *list)
 {
index c3addd1..654bea1 100644 (file)
@@ -506,6 +506,7 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry,
 
        index = lookup_one_len_unlocked(name.name, ofs->indexdir, name.len);
        if (IS_ERR(index)) {
+               err = PTR_ERR(index);
                pr_warn_ratelimited("overlayfs: failed inode index lookup (ino=%lu, key=%*s, err=%i);\n"
                                    "overlayfs: mount with '-o index=off' to disable inodes index.\n",
                                    d_inode(origin)->i_ino, name.len, name.name,
index d4e8c1a..c706a6f 100644 (file)
@@ -235,6 +235,7 @@ bool ovl_inuse_trylock(struct dentry *dentry);
 void ovl_inuse_unlock(struct dentry *dentry);
 int ovl_nlink_start(struct dentry *dentry, bool *locked);
 void ovl_nlink_end(struct dentry *dentry, bool locked);
+int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir);
 
 static inline bool ovl_is_impuredir(struct dentry *dentry)
 {
index 878a750..25d9b5a 100644 (file)
@@ -37,6 +37,9 @@ struct ovl_fs {
        bool noxattr;
        /* sb common to all layers */
        struct super_block *same_sb;
+       /* Did we take the inuse lock? */
+       bool upperdir_locked;
+       bool workdir_locked;
 };
 
 /* private information held for every overlayfs dentry */
index 62e9b22..0f85ee9 100644 (file)
@@ -988,6 +988,7 @@ int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt,
                         struct path *lowerstack, unsigned int numlower)
 {
        int err;
+       struct dentry *index = NULL;
        struct inode *dir = dentry->d_inode;
        struct path path = { .mnt = mnt, .dentry = dentry };
        LIST_HEAD(list);
@@ -1007,8 +1008,6 @@ int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt,
 
        inode_lock_nested(dir, I_MUTEX_PARENT);
        list_for_each_entry(p, &list, l_node) {
-               struct dentry *index;
-
                if (p->name[0] == '.') {
                        if (p->len == 1)
                                continue;
@@ -1018,6 +1017,7 @@ int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt,
                index = lookup_one_len(p->name, dentry, p->len);
                if (IS_ERR(index)) {
                        err = PTR_ERR(index);
+                       index = NULL;
                        break;
                }
                err = ovl_verify_index(index, lowerstack, numlower);
@@ -1029,7 +1029,9 @@ int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt,
                                break;
                }
                dput(index);
+               index = NULL;
        }
+       dput(index);
        inode_unlock(dir);
 out:
        ovl_cache_free(&list);
index fd5ea4f..092d150 100644 (file)
@@ -211,9 +211,10 @@ static void ovl_put_super(struct super_block *sb)
 
        dput(ufs->indexdir);
        dput(ufs->workdir);
-       ovl_inuse_unlock(ufs->workbasedir);
+       if (ufs->workdir_locked)
+               ovl_inuse_unlock(ufs->workbasedir);
        dput(ufs->workbasedir);
-       if (ufs->upper_mnt)
+       if (ufs->upper_mnt && ufs->upperdir_locked)
                ovl_inuse_unlock(ufs->upper_mnt->mnt_root);
        mntput(ufs->upper_mnt);
        for (i = 0; i < ufs->numlower; i++)
@@ -881,9 +882,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
                        goto out_put_upperpath;
 
                err = -EBUSY;
-               if (!ovl_inuse_trylock(upperpath.dentry)) {
-                       pr_err("overlayfs: upperdir is in-use by another mount\n");
+               if (ovl_inuse_trylock(upperpath.dentry)) {
+                       ufs->upperdir_locked = true;
+               } else if (ufs->config.index) {
+                       pr_err("overlayfs: upperdir is in-use by another mount, mount with '-o index=off' to override exclusive upperdir protection.\n");
                        goto out_put_upperpath;
+               } else {
+                       pr_warn("overlayfs: upperdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n");
                }
 
                err = ovl_mount_dir(ufs->config.workdir, &workpath);
@@ -901,9 +906,13 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
                }
 
                err = -EBUSY;
-               if (!ovl_inuse_trylock(workpath.dentry)) {
-                       pr_err("overlayfs: workdir is in-use by another mount\n");
+               if (ovl_inuse_trylock(workpath.dentry)) {
+                       ufs->workdir_locked = true;
+               } else if (ufs->config.index) {
+                       pr_err("overlayfs: workdir is in-use by another mount, mount with '-o index=off' to override exclusive workdir protection.\n");
                        goto out_put_workpath;
+               } else {
+                       pr_warn("overlayfs: workdir is in-use by another mount, accessing files from both mounts will result in undefined behavior.\n");
                }
 
                ufs->workbasedir = workpath.dentry;
@@ -1156,11 +1165,13 @@ out_put_lowerpath:
 out_free_lowertmp:
        kfree(lowertmp);
 out_unlock_workdentry:
-       ovl_inuse_unlock(workpath.dentry);
+       if (ufs->workdir_locked)
+               ovl_inuse_unlock(workpath.dentry);
 out_put_workpath:
        path_put(&workpath);
 out_unlock_upperdentry:
-       ovl_inuse_unlock(upperpath.dentry);
+       if (ufs->upperdir_locked)
+               ovl_inuse_unlock(upperpath.dentry);
 out_put_upperpath:
        path_put(&upperpath);
 out_free_config:
index 1177945..b9b239f 100644 (file)
@@ -430,7 +430,7 @@ void ovl_inuse_unlock(struct dentry *dentry)
        }
 }
 
-/* Called must hold OVL_I(inode)->oi_lock */
+/* Caller must hold OVL_I(inode)->lock */
 static void ovl_cleanup_index(struct dentry *dentry)
 {
        struct inode *dir = ovl_indexdir(dentry->d_sb)->d_inode;
@@ -469,6 +469,9 @@ static void ovl_cleanup_index(struct dentry *dentry)
        err = PTR_ERR(index);
        if (!IS_ERR(index))
                err = ovl_cleanup(dir, index);
+       else
+               index = NULL;
+
        inode_unlock(dir);
        if (err)
                goto fail;
@@ -557,3 +560,22 @@ void ovl_nlink_end(struct dentry *dentry, bool locked)
                mutex_unlock(&OVL_I(d_inode(dentry))->lock);
        }
 }
+
+int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir)
+{
+       /* Workdir should not be the same as upperdir */
+       if (workdir == upperdir)
+               goto err;
+
+       /* Workdir should not be subdir of upperdir and vice versa */
+       if (lock_rename(workdir, upperdir) != NULL)
+               goto err_unlock;
+
+       return 0;
+
+err_unlock:
+       unlock_rename(workdir, upperdir);
+err:
+       pr_err("overlayfs: failed to lock workdir+upperdir\n");
+       return -EIO;
+}
index ef4b48d..1c713fd 100644 (file)
@@ -588,6 +588,12 @@ static void userfaultfd_event_wait_completion(struct userfaultfd_ctx *ctx,
                        break;
                if (ACCESS_ONCE(ctx->released) ||
                    fatal_signal_pending(current)) {
+                       /*
+                        * &ewq->wq may be queued in fork_event, but
+                        * __remove_wait_queue ignores the head
+                        * parameter. It would be a problem if it
+                        * didn't.
+                        */
                        __remove_wait_queue(&ctx->event_wqh, &ewq->wq);
                        if (ewq->msg.event == UFFD_EVENT_FORK) {
                                struct userfaultfd_ctx *new;
@@ -1061,6 +1067,12 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait,
                                        (unsigned long)
                                        uwq->msg.arg.reserved.reserved1;
                                list_move(&uwq->wq.entry, &fork_event);
+                               /*
+                                * fork_nctx can be freed as soon as
+                                * we drop the lock, unless we take a
+                                * reference on it.
+                                */
+                               userfaultfd_ctx_get(fork_nctx);
                                spin_unlock(&ctx->event_wqh.lock);
                                ret = 0;
                                break;
@@ -1091,19 +1103,53 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait,
 
        if (!ret && msg->event == UFFD_EVENT_FORK) {
                ret = resolve_userfault_fork(ctx, fork_nctx, msg);
+               spin_lock(&ctx->event_wqh.lock);
+               if (!list_empty(&fork_event)) {
+                       /*
+                        * The fork thread didn't abort, so we can
+                        * drop the temporary refcount.
+                        */
+                       userfaultfd_ctx_put(fork_nctx);
+
+                       uwq = list_first_entry(&fork_event,
+                                              typeof(*uwq),
+                                              wq.entry);
+                       /*
+                        * If fork_event list wasn't empty and in turn
+                        * the event wasn't already released by fork
+                        * (the event is allocated on fork kernel
+                        * stack), put the event back to its place in
+                        * the event_wq. fork_event head will be freed
+                        * as soon as we return so the event cannot
+                        * stay queued there no matter the current
+                        * "ret" value.
+                        */
+                       list_del(&uwq->wq.entry);
+                       __add_wait_queue(&ctx->event_wqh, &uwq->wq);
 
-               if (!ret) {
-                       spin_lock(&ctx->event_wqh.lock);
-                       if (!list_empty(&fork_event)) {
-                               uwq = list_first_entry(&fork_event,
-                                                      typeof(*uwq),
-                                                      wq.entry);
-                               list_del(&uwq->wq.entry);
-                               __add_wait_queue(&ctx->event_wqh, &uwq->wq);
+                       /*
+                        * Leave the event in the waitqueue and report
+                        * error to userland if we failed to resolve
+                        * the userfault fork.
+                        */
+                       if (likely(!ret))
                                userfaultfd_event_complete(ctx, uwq);
-                       }
-                       spin_unlock(&ctx->event_wqh.lock);
+               } else {
+                       /*
+                        * Here the fork thread aborted and the
+                        * refcount from the fork thread on fork_nctx
+                        * has already been released. We still hold
+                        * the reference we took before releasing the
+                        * lock above. If resolve_userfault_fork
+                        * failed we've to drop it because the
+                        * fork_nctx has to be freed in such case. If
+                        * it succeeded we'll hold it because the new
+                        * uffd references it.
+                        */
+                       if (ret)
+                               userfaultfd_ctx_put(fork_nctx);
                }
+               spin_unlock(&ctx->event_wqh.lock);
        }
 
        return ret;
index 4424f7f..61cd28b 100644 (file)
@@ -250,7 +250,7 @@ xattr_getsecurity(struct inode *inode, const char *name, void *value,
        }
        memcpy(value, buffer, len);
 out:
-       security_release_secctx(buffer, len);
+       kfree(buffer);
 out_noalloc:
        return len;
 }
index bc6c6e1..e9db7fc 100644 (file)
@@ -2122,11 +2122,31 @@ xfs_swap_extents(
                ip->i_d.di_flags2 |= tip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK;
                tip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
                tip->i_d.di_flags2 |= f & XFS_DIFLAG2_REFLINK;
+       }
+
+       /* Swap the cow forks. */
+       if (xfs_sb_version_hasreflink(&mp->m_sb)) {
+               xfs_extnum_t    extnum;
+
+               ASSERT(ip->i_cformat == XFS_DINODE_FMT_EXTENTS);
+               ASSERT(tip->i_cformat == XFS_DINODE_FMT_EXTENTS);
+
+               extnum = ip->i_cnextents;
+               ip->i_cnextents = tip->i_cnextents;
+               tip->i_cnextents = extnum;
+
                cowfp = ip->i_cowfp;
                ip->i_cowfp = tip->i_cowfp;
                tip->i_cowfp = cowfp;
-               xfs_inode_set_cowblocks_tag(ip);
-               xfs_inode_set_cowblocks_tag(tip);
+
+               if (ip->i_cowfp && ip->i_cnextents)
+                       xfs_inode_set_cowblocks_tag(ip);
+               else
+                       xfs_inode_clear_cowblocks_tag(ip);
+               if (tip->i_cowfp && tip->i_cnextents)
+                       xfs_inode_set_cowblocks_tag(tip);
+               else
+                       xfs_inode_clear_cowblocks_tag(tip);
        }
 
        xfs_trans_log_inode(tp, ip,  src_log_flags);
index 3246815..37e603b 100644 (file)
@@ -736,7 +736,13 @@ xfs_reflink_end_cow(
        /* If there is a hole at end_fsb - 1 go to the previous extent */
        if (!xfs_iext_lookup_extent(ip, ifp, end_fsb - 1, &idx, &got) ||
            got.br_startoff > end_fsb) {
-               ASSERT(idx > 0);
+               /*
+                * In case of racing, overlapping AIO writes no COW extents
+                * might be left by the time I/O completes for the loser of
+                * the race.  In that case we are done.
+                */
+               if (idx <= 0)
+                       goto out_cancel;
                xfs_iext_get_extent(ifp, --idx, &got);
        }
 
@@ -809,6 +815,7 @@ next_extent:
 
 out_defer:
        xfs_defer_cancel(&dfops);
+out_cancel:
        xfs_trans_cancel(tp);
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 out:
index 0504ef8..976f8ac 100644 (file)
@@ -115,15 +115,35 @@ do {                                                                      \
        (__ret);                                                        \
 })
 
-#define this_cpu_generic_read(pcp)                                     \
+#define __this_cpu_generic_read_nopreempt(pcp)                         \
 ({                                                                     \
        typeof(pcp) __ret;                                              \
        preempt_disable_notrace();                                      \
-       __ret = raw_cpu_generic_read(pcp);                              \
+       __ret = READ_ONCE(*raw_cpu_ptr(&(pcp)));                        \
        preempt_enable_notrace();                                       \
        __ret;                                                          \
 })
 
+#define __this_cpu_generic_read_noirq(pcp)                             \
+({                                                                     \
+       typeof(pcp) __ret;                                              \
+       unsigned long __flags;                                          \
+       raw_local_irq_save(__flags);                                    \
+       __ret = raw_cpu_generic_read(pcp);                              \
+       raw_local_irq_restore(__flags);                                 \
+       __ret;                                                          \
+})
+
+#define this_cpu_generic_read(pcp)                                     \
+({                                                                     \
+       typeof(pcp) __ret;                                              \
+       if (__native_word(pcp))                                         \
+               __ret = __this_cpu_generic_read_nopreempt(pcp);         \
+       else                                                            \
+               __ret = __this_cpu_generic_read_noirq(pcp);             \
+       __ret;                                                          \
+})
+
 #define this_cpu_generic_to_op(pcp, val, op)                           \
 do {                                                                   \
        unsigned long __flags;                                          \
diff --git a/include/dt-bindings/reset/snps,hsdk-reset.h b/include/dt-bindings/reset/snps,hsdk-reset.h
new file mode 100644 (file)
index 0000000..e1a643e
--- /dev/null
@@ -0,0 +1,17 @@
+/**
+ * This header provides index for the HSDK reset controller.
+ */
+#ifndef _DT_BINDINGS_RESET_CONTROLLER_SNPS_HSDK
+#define _DT_BINDINGS_RESET_CONTROLLER_SNPS_HSDK
+
+#define HSDK_APB_RESET 0
+#define HSDK_AXI_RESET 1
+#define HSDK_ETH_RESET 2
+#define HSDK_USB_RESET 3
+#define HSDK_SDIO_RESET        4
+#define HSDK_HDMI_RESET        5
+#define HSDK_GFX_RESET 6
+#define HSDK_DMAC_RESET        7
+#define HSDK_EBI_RESET 8
+
+#endif /*_DT_BINDINGS_RESET_CONTROLLER_SNPS_HSDK*/
diff --git a/include/dt-bindings/reset/snps,hsdk-v1-reset.h b/include/dt-bindings/reset/snps,hsdk-v1-reset.h
deleted file mode 100644 (file)
index d898c89..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * This header provides index for the HSDK v1 reset controller.
- */
-#ifndef _DT_BINDINGS_RESET_CONTROLLER_HSDK_V1
-#define _DT_BINDINGS_RESET_CONTROLLER_HSDK_V1
-
-#define HSDK_V1_APB_RESET      0
-#define HSDK_V1_AXI_RESET      1
-#define HSDK_V1_ETH_RESET      2
-#define HSDK_V1_USB_RESET      3
-#define HSDK_V1_SDIO_RESET     4
-#define HSDK_V1_HDMI_RESET     5
-#define HSDK_V1_GFX_RESET      6
-#define HSDK_V1_DMAC_RESET     7
-#define HSDK_V1_EBI_RESET      8
-
-#endif /*_DT_BINDINGS_RESET_CONTROLLER_HSDK_V1*/
index fb44d61..18d05b5 100644 (file)
@@ -131,7 +131,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm,
                           int executable_stack);
 extern int transfer_args_to_stack(struct linux_binprm *bprm,
                                  unsigned long *sp_location);
-extern int bprm_change_interp(char *interp, struct linux_binprm *bprm);
+extern int bprm_change_interp(const char *interp, struct linux_binprm *bprm);
 extern int copy_strings_kernel(int argc, const char *const *argv,
                               struct linux_binprm *bprm);
 extern int prepare_bprm_creds(struct linux_binprm *bprm);
index 8b9d6ff..f2deb71 100644 (file)
@@ -92,7 +92,7 @@
 /**
  * FIELD_GET() - extract a bitfield element
  * @_mask: shifted mask defining the field's length and position
- * @_reg:  32bit value of entire bitfield
+ * @_reg:  value of entire bitfield
  *
  * FIELD_GET() extracts the field specified by @_mask from the
  * bitfield passed in as @_reg by masking and shifting it down.
index 1d26079..66fe271 100644 (file)
@@ -307,8 +307,6 @@ struct driver_attribute {
                         size_t count);
 };
 
-#define DRIVER_ATTR(_name, _mode, _show, _store) \
-       struct driver_attribute driver_attr_##_name = __ATTR(_name, _mode, _show, _store)
 #define DRIVER_ATTR_RW(_name) \
        struct driver_attribute driver_attr_##_name = __ATTR_RW(_name)
 #define DRIVER_ATTR_RO(_name) \
index 339e737..13dab19 100644 (file)
@@ -403,7 +403,7 @@ struct address_space {
        unsigned long           flags;          /* error bits */
        spinlock_t              private_lock;   /* for use by the address_space */
        gfp_t                   gfp_mask;       /* implicit gfp mask for allocations */
-       struct list_head        private_list;   /* ditto */
+       struct list_head        private_list;   /* for use by the address_space */
        void                    *private_data;  /* ditto */
        errseq_t                wb_err;
 } __attribute__((aligned(sizeof(long)))) __randomize_layout;
index 5ba430c..1fc7abd 100644 (file)
@@ -111,6 +111,9 @@ int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
 int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
        unsigned int size, unsigned int *val);
 
+int ad_sd_reset(struct ad_sigma_delta *sigma_delta,
+       unsigned int reset_length);
+
 int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
        const struct iio_chan_spec *chan, int *val);
 int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta,
index eaf4ad2..e32dbc4 100644 (file)
@@ -980,7 +980,6 @@ enum mlx5_cap_type {
        MLX5_CAP_RESERVED,
        MLX5_CAP_VECTOR_CALC,
        MLX5_CAP_QOS,
-       MLX5_CAP_FPGA,
        /* NUM OF CAP Types */
        MLX5_CAP_NUM
 };
@@ -1110,10 +1109,10 @@ enum mlx5_mcam_feature_groups {
        MLX5_GET(mcam_reg, (mdev)->caps.mcam, mng_feature_cap_mask.enhanced_features.fld)
 
 #define MLX5_CAP_FPGA(mdev, cap) \
-       MLX5_GET(fpga_cap, (mdev)->caps.hca_cur[MLX5_CAP_FPGA], cap)
+       MLX5_GET(fpga_cap, (mdev)->caps.fpga, cap)
 
 #define MLX5_CAP64_FPGA(mdev, cap) \
-       MLX5_GET64(fpga_cap, (mdev)->caps.hca_cur[MLX5_CAP_FPGA], cap)
+       MLX5_GET64(fpga_cap, (mdev)->caps.fpga, cap)
 
 enum {
        MLX5_CMD_STAT_OK                        = 0x0,
index 02ff700..401c897 100644 (file)
@@ -774,6 +774,7 @@ struct mlx5_core_dev {
                u32 hca_max[MLX5_CAP_NUM][MLX5_UN_SZ_DW(hca_cap_union)];
                u32 pcam[MLX5_ST_SZ_DW(pcam_reg)];
                u32 mcam[MLX5_ST_SZ_DW(mcam_reg)];
+               u32 fpga[MLX5_ST_SZ_DW(fpga_cap)];
        } caps;
        phys_addr_t             iseg_base;
        struct mlx5_init_seg __iomem *iseg;
index a528b35..6977234 100644 (file)
@@ -327,7 +327,8 @@ struct mlx5_ifc_flow_table_prop_layout_bits {
        u8         reserved_at_80[0x18];
        u8         log_max_destination[0x8];
 
-       u8         reserved_at_a0[0x18];
+       u8         log_max_flow_counter[0x8];
+       u8         reserved_at_a8[0x10];
        u8         log_max_flow[0x8];
 
        u8         reserved_at_c0[0x40];
index f8c10d3..065d99d 100644 (file)
@@ -240,7 +240,7 @@ extern unsigned int kobjsize(const void *objp);
 
 #if defined(CONFIG_X86_INTEL_MPX)
 /* MPX specific bounds table or bounds directory */
-# define VM_MPX                VM_HIGH_ARCH_BIT_4
+# define VM_MPX                VM_HIGH_ARCH_4
 #else
 # define VM_MPX                VM_NONE
 #endif
index 7b2e31b..6866e81 100644 (file)
@@ -400,6 +400,11 @@ extern void mmu_notifier_synchronize(void);
 
 #else /* CONFIG_MMU_NOTIFIER */
 
+static inline int mm_has_notifiers(struct mm_struct *mm)
+{
+       return 0;
+}
+
 static inline void mmu_notifier_release(struct mm_struct *mm)
 {
 }
index 356a814..c8f8941 100644 (file)
@@ -1094,8 +1094,14 @@ static inline unsigned long early_pfn_to_nid(unsigned long pfn)
 #error Allocator MAX_ORDER exceeds SECTION_SIZE
 #endif
 
-#define pfn_to_section_nr(pfn) ((pfn) >> PFN_SECTION_SHIFT)
-#define section_nr_to_pfn(sec) ((sec) << PFN_SECTION_SHIFT)
+static inline unsigned long pfn_to_section_nr(unsigned long pfn)
+{
+       return pfn >> PFN_SECTION_SHIFT;
+}
+static inline unsigned long section_nr_to_pfn(unsigned long sec)
+{
+       return sec << PFN_SECTION_SHIFT;
+}
 
 #define SECTION_ALIGN_UP(pfn)  (((pfn) + PAGES_PER_SECTION - 1) & PAGE_SECTION_MASK)
 #define SECTION_ALIGN_DOWN(pfn)        ((pfn) & PAGE_SECTION_MASK)
index a36abe2..27e249e 100644 (file)
 
 #ifdef CONFIG_LOCKUP_DETECTOR
 void lockup_detector_init(void);
+void lockup_detector_soft_poweroff(void);
+void lockup_detector_cleanup(void);
+bool is_hardlockup(void);
+
+extern int watchdog_user_enabled;
+extern int nmi_watchdog_user_enabled;
+extern int soft_watchdog_user_enabled;
+extern int watchdog_thresh;
+extern unsigned long watchdog_enabled;
+
+extern struct cpumask watchdog_cpumask;
+extern unsigned long *watchdog_cpumask_bits;
+#ifdef CONFIG_SMP
+extern int sysctl_softlockup_all_cpu_backtrace;
+extern int sysctl_hardlockup_all_cpu_backtrace;
 #else
-static inline void lockup_detector_init(void)
-{
-}
-#endif
+#define sysctl_softlockup_all_cpu_backtrace 0
+#define sysctl_hardlockup_all_cpu_backtrace 0
+#endif /* !CONFIG_SMP */
+
+#else /* CONFIG_LOCKUP_DETECTOR */
+static inline void lockup_detector_init(void) { }
+static inline void lockup_detector_soft_poweroff(void) { }
+static inline void lockup_detector_cleanup(void) { }
+#endif /* !CONFIG_LOCKUP_DETECTOR */
 
 #ifdef CONFIG_SOFTLOCKUP_DETECTOR
 extern void touch_softlockup_watchdog_sched(void);
@@ -24,29 +44,17 @@ extern void touch_softlockup_watchdog(void);
 extern void touch_softlockup_watchdog_sync(void);
 extern void touch_all_softlockup_watchdogs(void);
 extern unsigned int  softlockup_panic;
-extern int soft_watchdog_enabled;
-extern atomic_t watchdog_park_in_progress;
 #else
-static inline void touch_softlockup_watchdog_sched(void)
-{
-}
-static inline void touch_softlockup_watchdog(void)
-{
-}
-static inline void touch_softlockup_watchdog_sync(void)
-{
-}
-static inline void touch_all_softlockup_watchdogs(void)
-{
-}
+static inline void touch_softlockup_watchdog_sched(void) { }
+static inline void touch_softlockup_watchdog(void) { }
+static inline void touch_softlockup_watchdog_sync(void) { }
+static inline void touch_all_softlockup_watchdogs(void) { }
 #endif
 
 #ifdef CONFIG_DETECT_HUNG_TASK
 void reset_hung_task_detector(void);
 #else
-static inline void reset_hung_task_detector(void)
-{
-}
+static inline void reset_hung_task_detector(void) { }
 #endif
 
 /*
@@ -54,12 +62,12 @@ static inline void reset_hung_task_detector(void)
  * 'watchdog_enabled' variable. Each lockup detector has its dedicated bit -
  * bit 0 for the hard lockup detector and bit 1 for the soft lockup detector.
  *
- * 'watchdog_user_enabled', 'nmi_watchdog_enabled' and 'soft_watchdog_enabled'
- * are variables that are only used as an 'interface' between the parameters
- * in /proc/sys/kernel and the internal state bits in 'watchdog_enabled'. The
- * 'watchdog_thresh' variable is handled differently because its value is not
- * boolean, and the lockup detectors are 'suspended' while 'watchdog_thresh'
- * is equal zero.
+ * 'watchdog_user_enabled', 'nmi_watchdog_user_enabled' and
+ * 'soft_watchdog_user_enabled' are variables that are only used as an
+ * 'interface' between the parameters in /proc/sys/kernel and the internal
+ * state bits in 'watchdog_enabled'. The 'watchdog_thresh' variable is
+ * handled differently because its value is not boolean, and the lockup
+ * detectors are 'suspended' while 'watchdog_thresh' is equal zero.
  */
 #define NMI_WATCHDOG_ENABLED_BIT   0
 #define SOFT_WATCHDOG_ENABLED_BIT  1
@@ -73,17 +81,41 @@ extern unsigned int hardlockup_panic;
 static inline void hardlockup_detector_disable(void) {}
 #endif
 
+#if defined(CONFIG_HAVE_NMI_WATCHDOG) || defined(CONFIG_HARDLOCKUP_DETECTOR)
+# define NMI_WATCHDOG_SYSCTL_PERM      0644
+#else
+# define NMI_WATCHDOG_SYSCTL_PERM      0444
+#endif
+
 #if defined(CONFIG_HARDLOCKUP_DETECTOR_PERF)
 extern void arch_touch_nmi_watchdog(void);
+extern void hardlockup_detector_perf_stop(void);
+extern void hardlockup_detector_perf_restart(void);
+extern void hardlockup_detector_perf_disable(void);
+extern void hardlockup_detector_perf_enable(void);
+extern void hardlockup_detector_perf_cleanup(void);
+extern int hardlockup_detector_perf_init(void);
 #else
-#if !defined(CONFIG_HAVE_NMI_WATCHDOG)
+static inline void hardlockup_detector_perf_stop(void) { }
+static inline void hardlockup_detector_perf_restart(void) { }
+static inline void hardlockup_detector_perf_disable(void) { }
+static inline void hardlockup_detector_perf_enable(void) { }
+static inline void hardlockup_detector_perf_cleanup(void) { }
+# if !defined(CONFIG_HAVE_NMI_WATCHDOG)
+static inline int hardlockup_detector_perf_init(void) { return -ENODEV; }
 static inline void arch_touch_nmi_watchdog(void) {}
+# else
+static inline int hardlockup_detector_perf_init(void) { return 0; }
+# endif
 #endif
-#endif
+
+void watchdog_nmi_stop(void);
+void watchdog_nmi_start(void);
+int watchdog_nmi_probe(void);
 
 /**
  * touch_nmi_watchdog - restart NMI watchdog timeout.
- * 
+ *
  * If the architecture supports the NMI watchdog, touch_nmi_watchdog()
  * may be used to reset the timeout - for code which intentionally
  * disables interrupts for a long time. This call is stateless.
@@ -153,22 +185,6 @@ static inline bool trigger_single_cpu_backtrace(int cpu)
 u64 hw_nmi_get_sample_period(int watchdog_thresh);
 #endif
 
-#ifdef CONFIG_LOCKUP_DETECTOR
-extern int nmi_watchdog_enabled;
-extern int watchdog_user_enabled;
-extern int watchdog_thresh;
-extern unsigned long watchdog_enabled;
-extern struct cpumask watchdog_cpumask;
-extern unsigned long *watchdog_cpumask_bits;
-extern int __read_mostly watchdog_suspended;
-#ifdef CONFIG_SMP
-extern int sysctl_softlockup_all_cpu_backtrace;
-extern int sysctl_hardlockup_all_cpu_backtrace;
-#else
-#define sysctl_softlockup_all_cpu_backtrace 0
-#define sysctl_hardlockup_all_cpu_backtrace 0
-#endif
-
 #if defined(CONFIG_HARDLOCKUP_CHECK_TIMESTAMP) && \
     defined(CONFIG_HARDLOCKUP_DETECTOR)
 void watchdog_update_hrtimer_threshold(u64 period);
@@ -176,7 +192,6 @@ void watchdog_update_hrtimer_threshold(u64 period);
 static inline void watchdog_update_hrtimer_threshold(u64 period) { }
 #endif
 
-extern bool is_hardlockup(void);
 struct ctl_table;
 extern int proc_watchdog(struct ctl_table *, int ,
                         void __user *, size_t *, loff_t *);
@@ -188,18 +203,6 @@ extern int proc_watchdog_thresh(struct ctl_table *, int ,
                                void __user *, size_t *, loff_t *);
 extern int proc_watchdog_cpumask(struct ctl_table *, int,
                                 void __user *, size_t *, loff_t *);
-extern int lockup_detector_suspend(void);
-extern void lockup_detector_resume(void);
-#else
-static inline int lockup_detector_suspend(void)
-{
-       return 0;
-}
-
-static inline void lockup_detector_resume(void)
-{
-}
-#endif
 
 #ifdef CONFIG_HAVE_ACPI_APEI_NMI
 #include <asm/nmi.h>
index 3a19c25..ae53e41 100644 (file)
@@ -84,6 +84,12 @@ static inline bool mmget_not_zero(struct mm_struct *mm)
 
 /* mmput gets rid of the mappings and all user-space */
 extern void mmput(struct mm_struct *);
+#ifdef CONFIG_MMU
+/* same as above but performs the slow path from the async context. Can
+ * be called from the atomic context as well
+ */
+void mmput_async(struct mm_struct *);
+#endif
 
 /* Grab a reference to a task's mm, if it is not already going away */
 extern struct mm_struct *get_task_mm(struct task_struct *task);
index 12910cf..c149aa7 100644 (file)
@@ -55,7 +55,7 @@ smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread)
 }
 
 void smpboot_unregister_percpu_thread(struct smp_hotplug_thread *plug_thread);
-int smpboot_update_cpumask_percpu_thread(struct smp_hotplug_thread *plug_thread,
-                                        const struct cpumask *);
+void smpboot_update_cpumask_percpu_thread(struct smp_hotplug_thread *plug_thread,
+                                         const struct cpumask *);
 
 #endif
index e51cf5f..14c2893 100644 (file)
@@ -773,7 +773,10 @@ static inline int nla_parse_nested(struct nlattr *tb[], int maxtype,
  */
 static inline int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value)
 {
-       return nla_put(skb, attrtype, sizeof(u8), &value);
+       /* temporary variables to work around GCC PR81715 with asan-stack=1 */
+       u8 tmp = value;
+
+       return nla_put(skb, attrtype, sizeof(u8), &tmp);
 }
 
 /**
@@ -784,7 +787,9 @@ static inline int nla_put_u8(struct sk_buff *skb, int attrtype, u8 value)
  */
 static inline int nla_put_u16(struct sk_buff *skb, int attrtype, u16 value)
 {
-       return nla_put(skb, attrtype, sizeof(u16), &value);
+       u16 tmp = value;
+
+       return nla_put(skb, attrtype, sizeof(u16), &tmp);
 }
 
 /**
@@ -795,7 +800,9 @@ static inline int nla_put_u16(struct sk_buff *skb, int attrtype, u16 value)
  */
 static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value)
 {
-       return nla_put(skb, attrtype, sizeof(__be16), &value);
+       __be16 tmp = value;
+
+       return nla_put(skb, attrtype, sizeof(__be16), &tmp);
 }
 
 /**
@@ -806,7 +813,9 @@ static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value)
  */
 static inline int nla_put_net16(struct sk_buff *skb, int attrtype, __be16 value)
 {
-       return nla_put_be16(skb, attrtype | NLA_F_NET_BYTEORDER, value);
+       __be16 tmp = value;
+
+       return nla_put_be16(skb, attrtype | NLA_F_NET_BYTEORDER, tmp);
 }
 
 /**
@@ -817,7 +826,9 @@ static inline int nla_put_net16(struct sk_buff *skb, int attrtype, __be16 value)
  */
 static inline int nla_put_le16(struct sk_buff *skb, int attrtype, __le16 value)
 {
-       return nla_put(skb, attrtype, sizeof(__le16), &value);
+       __le16 tmp = value;
+
+       return nla_put(skb, attrtype, sizeof(__le16), &tmp);
 }
 
 /**
@@ -828,7 +839,9 @@ static inline int nla_put_le16(struct sk_buff *skb, int attrtype, __le16 value)
  */
 static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value)
 {
-       return nla_put(skb, attrtype, sizeof(u32), &value);
+       u32 tmp = value;
+
+       return nla_put(skb, attrtype, sizeof(u32), &tmp);
 }
 
 /**
@@ -839,7 +852,9 @@ static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value)
  */
 static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value)
 {
-       return nla_put(skb, attrtype, sizeof(__be32), &value);
+       __be32 tmp = value;
+
+       return nla_put(skb, attrtype, sizeof(__be32), &tmp);
 }
 
 /**
@@ -850,7 +865,9 @@ static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value)
  */
 static inline int nla_put_net32(struct sk_buff *skb, int attrtype, __be32 value)
 {
-       return nla_put_be32(skb, attrtype | NLA_F_NET_BYTEORDER, value);
+       __be32 tmp = value;
+
+       return nla_put_be32(skb, attrtype | NLA_F_NET_BYTEORDER, tmp);
 }
 
 /**
@@ -861,7 +878,9 @@ static inline int nla_put_net32(struct sk_buff *skb, int attrtype, __be32 value)
  */
 static inline int nla_put_le32(struct sk_buff *skb, int attrtype, __le32 value)
 {
-       return nla_put(skb, attrtype, sizeof(__le32), &value);
+       __le32 tmp = value;
+
+       return nla_put(skb, attrtype, sizeof(__le32), &tmp);
 }
 
 /**
@@ -874,7 +893,9 @@ static inline int nla_put_le32(struct sk_buff *skb, int attrtype, __le32 value)
 static inline int nla_put_u64_64bit(struct sk_buff *skb, int attrtype,
                                    u64 value, int padattr)
 {
-       return nla_put_64bit(skb, attrtype, sizeof(u64), &value, padattr);
+       u64 tmp = value;
+
+       return nla_put_64bit(skb, attrtype, sizeof(u64), &tmp, padattr);
 }
 
 /**
@@ -887,7 +908,9 @@ static inline int nla_put_u64_64bit(struct sk_buff *skb, int attrtype,
 static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value,
                               int padattr)
 {
-       return nla_put_64bit(skb, attrtype, sizeof(__be64), &value, padattr);
+       __be64 tmp = value;
+
+       return nla_put_64bit(skb, attrtype, sizeof(__be64), &tmp, padattr);
 }
 
 /**
@@ -900,7 +923,9 @@ static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value,
 static inline int nla_put_net64(struct sk_buff *skb, int attrtype, __be64 value,
                                int padattr)
 {
-       return nla_put_be64(skb, attrtype | NLA_F_NET_BYTEORDER, value,
+       __be64 tmp = value;
+
+       return nla_put_be64(skb, attrtype | NLA_F_NET_BYTEORDER, tmp,
                            padattr);
 }
 
@@ -914,7 +939,9 @@ static inline int nla_put_net64(struct sk_buff *skb, int attrtype, __be64 value,
 static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value,
                               int padattr)
 {
-       return nla_put_64bit(skb, attrtype, sizeof(__le64), &value, padattr);
+       __le64 tmp = value;
+
+       return nla_put_64bit(skb, attrtype, sizeof(__le64), &tmp, padattr);
 }
 
 /**
@@ -925,7 +952,9 @@ static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value,
  */
 static inline int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value)
 {
-       return nla_put(skb, attrtype, sizeof(s8), &value);
+       s8 tmp = value;
+
+       return nla_put(skb, attrtype, sizeof(s8), &tmp);
 }
 
 /**
@@ -936,7 +965,9 @@ static inline int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value)
  */
 static inline int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value)
 {
-       return nla_put(skb, attrtype, sizeof(s16), &value);
+       s16 tmp = value;
+
+       return nla_put(skb, attrtype, sizeof(s16), &tmp);
 }
 
 /**
@@ -947,7 +978,9 @@ static inline int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value)
  */
 static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value)
 {
-       return nla_put(skb, attrtype, sizeof(s32), &value);
+       s32 tmp = value;
+
+       return nla_put(skb, attrtype, sizeof(s32), &tmp);
 }
 
 /**
@@ -960,7 +993,9 @@ static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value)
 static inline int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value,
                              int padattr)
 {
-       return nla_put_64bit(skb, attrtype, sizeof(s64), &value, padattr);
+       s64 tmp = value;
+
+       return nla_put_64bit(skb, attrtype, sizeof(s64), &tmp, padattr);
 }
 
 /**
@@ -1010,7 +1045,9 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype,
 static inline int nla_put_in_addr(struct sk_buff *skb, int attrtype,
                                  __be32 addr)
 {
-       return nla_put_be32(skb, attrtype, addr);
+       __be32 tmp = addr;
+
+       return nla_put_be32(skb, attrtype, tmp);
 }
 
 /**
index 65ba335..4fc75f7 100644 (file)
@@ -39,8 +39,8 @@
 
 /* This is used to register protocols. */
 struct net_protocol {
-       void                    (*early_demux)(struct sk_buff *skb);
-       void                    (*early_demux_handler)(struct sk_buff *skb);
+       int                     (*early_demux)(struct sk_buff *skb);
+       int                     (*early_demux_handler)(struct sk_buff *skb);
        int                     (*handler)(struct sk_buff *skb);
        void                    (*err_handler)(struct sk_buff *skb, u32 info);
        unsigned int            no_policy:1,
index 57dfc68..d538e6d 100644 (file)
@@ -175,7 +175,9 @@ static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4
        fl4->fl4_gre_key = gre_key;
        return ip_route_output_key(net, fl4);
 }
-
+int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+                         u8 tos, struct net_device *dev,
+                         struct in_device *in_dev, u32 *itag);
 int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src,
                         u8 tos, struct net_device *devin);
 int ip_route_input_rcu(struct sk_buff *skb, __be32 dst, __be32 src,
index 3bc910a..89974c5 100644 (file)
@@ -345,7 +345,7 @@ void tcp_v4_err(struct sk_buff *skb, u32);
 
 void tcp_shutdown(struct sock *sk, int how);
 
-void tcp_v4_early_demux(struct sk_buff *skb);
+int tcp_v4_early_demux(struct sk_buff *skb);
 int tcp_v4_rcv(struct sk_buff *skb);
 
 int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
index 12dfbfe..6c759c8 100644 (file)
@@ -259,7 +259,7 @@ static inline struct sk_buff *skb_recv_udp(struct sock *sk, unsigned int flags,
        return __skb_recv_udp(sk, flags, noblock, &peeked, &off, err);
 }
 
-void udp_v4_early_demux(struct sk_buff *skb);
+int udp_v4_early_demux(struct sk_buff *skb);
 bool udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst);
 int udp_get_port(struct sock *sk, unsigned short snum,
                 int (*saddr_cmp)(const struct sock *,
index d0509db..f89cd5e 100644 (file)
@@ -95,6 +95,7 @@ enum {
 #define AC_VERB_SET_EAPD_BTLENABLE             0x70c
 #define AC_VERB_SET_DIGI_CONVERT_1             0x70d
 #define AC_VERB_SET_DIGI_CONVERT_2             0x70e
+#define AC_VERB_SET_DIGI_CONVERT_3             0x73e
 #define AC_VERB_SET_VOLUME_KNOB_CONTROL                0x70f
 #define AC_VERB_SET_GPIO_DATA                  0x715
 #define AC_VERB_SET_GPIO_MASK                  0x716
index 43ab5c4..f90860d 100644 (file)
@@ -312,7 +312,7 @@ union bpf_attr {
  *     jump into another BPF program
  *     @ctx: context pointer passed to next program
  *     @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY
- *     @index: index inside array that selects specific program to run
+ *     @index: 32-bit index inside array that selects specific program to run
  *     Return: 0 on success or negative error
  *
  * int bpf_clone_redirect(skb, ifindex, flags)
index 412c06a..ccaea52 100644 (file)
@@ -269,9 +269,9 @@ enum {
 #define DM_DEV_SET_GEOMETRY    _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 
 #define DM_VERSION_MAJOR       4
-#define DM_VERSION_MINOR       36
+#define DM_VERSION_MINOR       37
 #define DM_VERSION_PATCHLEVEL  0
-#define DM_VERSION_EXTRA       "-ioctl (2017-06-09)"
+#define DM_VERSION_EXTRA       "-ioctl (2017-09-20)"
 
 /* Status bits */
 #define DM_READONLY_FLAG       (1 << 0) /* In/Out */
index ce1169a..2a5d630 100644 (file)
@@ -780,6 +780,7 @@ struct usb_interface_assoc_descriptor {
        __u8  iFunction;
 } __attribute__ ((packed));
 
+#define USB_DT_INTERFACE_ASSOCIATION_SIZE      8
 
 /*-------------------------------------------------------------------------*/
 
index 917cc04..7b62df8 100644 (file)
@@ -1022,7 +1022,7 @@ select_insn:
                struct bpf_map *map = (struct bpf_map *) (unsigned long) BPF_R2;
                struct bpf_array *array = container_of(map, struct bpf_array, map);
                struct bpf_prog *prog;
-               u64 index = BPF_R3;
+               u32 index = BPF_R3;
 
                if (unlikely(index >= array->map.max_entries))
                        goto out;
index d6551cd..4485727 100644 (file)
@@ -2311,6 +2311,14 @@ out_release_tset:
                list_del_init(&cset->mg_node);
        }
        spin_unlock_irq(&css_set_lock);
+
+       /*
+        * Re-initialize the cgroup_taskset structure in case it is reused
+        * again in another cgroup_migrate_add_task()/cgroup_migrate_execute()
+        * iteration.
+        */
+       tset->nr_tasks = 0;
+       tset->csets    = &tset->src_csets;
        return ret;
 }
 
index 8de11a2..d851df2 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/lockdep.h>
 #include <linux/tick.h>
 #include <linux/irq.h>
+#include <linux/nmi.h>
 #include <linux/smpboot.h>
 #include <linux/relay.h>
 #include <linux/slab.h>
@@ -897,6 +898,11 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
 
 out:
        cpus_write_unlock();
+       /*
+        * Do post unplug cleanup. This is still protected against
+        * concurrent CPU hotplug via cpu_add_remove_lock.
+        */
+       lockup_detector_cleanup();
        return ret;
 }
 
index 1064618..e702cb9 100644 (file)
@@ -946,6 +946,24 @@ void mmput(struct mm_struct *mm)
 }
 EXPORT_SYMBOL_GPL(mmput);
 
+#ifdef CONFIG_MMU
+static void mmput_async_fn(struct work_struct *work)
+{
+       struct mm_struct *mm = container_of(work, struct mm_struct,
+                                           async_put_work);
+
+       __mmput(mm);
+}
+
+void mmput_async(struct mm_struct *mm)
+{
+       if (atomic_dec_and_test(&mm->mm_users)) {
+               INIT_WORK(&mm->async_put_work, mmput_async_fn);
+               schedule_work(&mm->async_put_work);
+       }
+}
+#endif
+
 /**
  * set_mm_exe_file - change a reference to the mm's executable file
  *
index ea34ed8..055bb29 100644 (file)
@@ -131,7 +131,7 @@ static int kcmp_epoll_target(struct task_struct *task1,
        if (filp_epoll) {
                filp_tgt = get_epoll_tfile_raw_ptr(filp_epoll, slot.tfd, slot.toff);
                fput(filp_epoll);
-       } else
+       }
 
        if (IS_ERR(filp_tgt))
                return PTR_ERR(filp_tgt);
index 6bcbfbf..403ab9c 100644 (file)
@@ -350,7 +350,7 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
        pgprot_t pgprot = PAGE_KERNEL;
        struct dev_pagemap *pgmap;
        struct page_map *page_map;
-       int error, nid, is_ram;
+       int error, nid, is_ram, i = 0;
 
        align_start = res->start & ~(SECTION_SIZE - 1);
        align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE)
@@ -448,6 +448,8 @@ void *devm_memremap_pages(struct device *dev, struct resource *res,
                list_del(&page->lru);
                page->pgmap = pgmap;
                percpu_ref_get(ref);
+               if (!(++i % 1024))
+                       cond_resched();
        }
        devres_add(dev, page_map);
        return __va(res->start);
index 60b2d81..cc9108c 100644 (file)
@@ -224,7 +224,7 @@ char *parse_args(const char *doing,
        }                                                               \
        int param_get_##name(char *buffer, const struct kernel_param *kp) \
        {                                                               \
-               return scnprintf(buffer, PAGE_SIZE, format,             \
+               return scnprintf(buffer, PAGE_SIZE, format "\n",        \
                                *((type *)kp->arg));                    \
        }                                                               \
        const struct kernel_param_ops param_ops_##name = {                      \
@@ -236,14 +236,14 @@ char *parse_args(const char *doing,
        EXPORT_SYMBOL(param_ops_##name)
 
 
-STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8);
-STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16);
-STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16);
-STANDARD_PARAM_DEF(int, int, "%i", kstrtoint);
-STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint);
-STANDARD_PARAM_DEF(long, long, "%li", kstrtol);
-STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul);
-STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull);
+STANDARD_PARAM_DEF(byte,       unsigned char,          "%hhu", kstrtou8);
+STANDARD_PARAM_DEF(short,      short,                  "%hi",  kstrtos16);
+STANDARD_PARAM_DEF(ushort,     unsigned short,         "%hu",  kstrtou16);
+STANDARD_PARAM_DEF(int,                int,                    "%i",   kstrtoint);
+STANDARD_PARAM_DEF(uint,       unsigned int,           "%u",   kstrtouint);
+STANDARD_PARAM_DEF(long,       long,                   "%li",  kstrtol);
+STANDARD_PARAM_DEF(ulong,      unsigned long,          "%lu",  kstrtoul);
+STANDARD_PARAM_DEF(ullong,     unsigned long long,     "%llu", kstrtoull);
 
 int param_set_charp(const char *val, const struct kernel_param *kp)
 {
@@ -270,7 +270,7 @@ EXPORT_SYMBOL(param_set_charp);
 
 int param_get_charp(char *buffer, const struct kernel_param *kp)
 {
-       return scnprintf(buffer, PAGE_SIZE, "%s", *((char **)kp->arg));
+       return scnprintf(buffer, PAGE_SIZE, "%s\n", *((char **)kp->arg));
 }
 EXPORT_SYMBOL(param_get_charp);
 
@@ -301,7 +301,7 @@ EXPORT_SYMBOL(param_set_bool);
 int param_get_bool(char *buffer, const struct kernel_param *kp)
 {
        /* Y and N chosen as being relatively non-coder friendly */
-       return sprintf(buffer, "%c", *(bool *)kp->arg ? 'Y' : 'N');
+       return sprintf(buffer, "%c\n", *(bool *)kp->arg ? 'Y' : 'N');
 }
 EXPORT_SYMBOL(param_get_bool);
 
@@ -360,7 +360,7 @@ EXPORT_SYMBOL(param_set_invbool);
 
 int param_get_invbool(char *buffer, const struct kernel_param *kp)
 {
-       return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y');
+       return sprintf(buffer, "%c\n", (*(bool *)kp->arg) ? 'N' : 'Y');
 }
 EXPORT_SYMBOL(param_get_invbool);
 
@@ -460,8 +460,9 @@ static int param_array_get(char *buffer, const struct kernel_param *kp)
        struct kernel_param p = *kp;
 
        for (i = off = 0; i < (arr->num ? *arr->num : arr->max); i++) {
+               /* Replace \n with comma */
                if (i)
-                       buffer[off++] = ',';
+                       buffer[off - 1] = ',';
                p.arg = arr->elem + arr->elemsize * i;
                check_kparam_locked(p.mod);
                ret = arr->ops->get(buffer + off, &p);
@@ -507,7 +508,7 @@ EXPORT_SYMBOL(param_set_copystring);
 int param_get_string(char *buffer, const struct kernel_param *kp)
 {
        const struct kparam_string *kps = kp->str;
-       return strlcpy(buffer, kps->string, kps->maxlen);
+       return scnprintf(buffer, PAGE_SIZE, "%s\n", kps->string);
 }
 EXPORT_SYMBOL(param_get_string);
 
@@ -549,10 +550,6 @@ static ssize_t param_attr_show(struct module_attribute *mattr,
        kernel_param_lock(mk->mod);
        count = attribute->param->ops->get(buf, attribute->param);
        kernel_param_unlock(mk->mod);
-       if (count > 0) {
-               strcat(buf, "\n");
-               ++count;
-       }
        return count;
 }
 
@@ -600,7 +597,7 @@ EXPORT_SYMBOL(kernel_param_unlock);
 /*
  * add_sysfs_param - add a parameter to sysfs
  * @mk: struct module_kobject
- * @kparam: the actual parameter definition to add to sysfs
+ * @kp: the actual parameter definition to add to sysfs
  * @name: name of parameter
  *
  * Create a kobject if for a (per-module) parameter if mp NULL, and
index 3e2b4f5..ccd2d20 100644 (file)
@@ -120,22 +120,26 @@ static void s2idle_loop(void)
                 * frozen processes + suspended devices + idle processors.
                 * Thus s2idle_enter() should be called right after
                 * all devices have been suspended.
+                *
+                * Wakeups during the noirq suspend of devices may be spurious,
+                * so prevent them from terminating the loop right away.
                 */
                error = dpm_noirq_suspend_devices(PMSG_SUSPEND);
                if (!error)
                        s2idle_enter();
+               else if (error == -EBUSY && pm_wakeup_pending())
+                       error = 0;
 
-               dpm_noirq_resume_devices(PMSG_RESUME);
-               if (error && (error != -EBUSY || !pm_wakeup_pending())) {
-                       dpm_noirq_end();
-                       break;
-               }
-
-               if (s2idle_ops && s2idle_ops->wake)
+               if (!error && s2idle_ops && s2idle_ops->wake)
                        s2idle_ops->wake();
 
+               dpm_noirq_resume_devices(PMSG_RESUME);
+
                dpm_noirq_end();
 
+               if (error)
+                       break;
+
                if (s2idle_ops && s2idle_ops->sync)
                        s2idle_ops->sync();
 
index 0c44c7b..b0ad62b 100644 (file)
@@ -884,7 +884,7 @@ void rcu_irq_exit(void)
        rdtp = this_cpu_ptr(&rcu_dynticks);
 
        /* Page faults can happen in NMI handlers, so check... */
-       if (READ_ONCE(rdtp->dynticks_nmi_nesting))
+       if (rdtp->dynticks_nmi_nesting)
                return;
 
        WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) &&
@@ -1022,7 +1022,7 @@ void rcu_irq_enter(void)
        rdtp = this_cpu_ptr(&rcu_dynticks);
 
        /* Page faults can happen in NMI handlers, so check... */
-       if (READ_ONCE(rdtp->dynticks_nmi_nesting))
+       if (rdtp->dynticks_nmi_nesting)
                return;
 
        oldval = rdtp->dynticks_nesting;
index 1d71c05..5043e74 100644 (file)
@@ -344,39 +344,30 @@ EXPORT_SYMBOL_GPL(smpboot_unregister_percpu_thread);
  * by the client, but only by calling this function.
  * This function can only be called on a registered smp_hotplug_thread.
  */
-int smpboot_update_cpumask_percpu_thread(struct smp_hotplug_thread *plug_thread,
-                                        const struct cpumask *new)
+void smpboot_update_cpumask_percpu_thread(struct smp_hotplug_thread *plug_thread,
+                                         const struct cpumask *new)
 {
        struct cpumask *old = plug_thread->cpumask;
-       cpumask_var_t tmp;
+       static struct cpumask tmp;
        unsigned int cpu;
 
-       if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
-               return -ENOMEM;
-
-       get_online_cpus();
+       lockdep_assert_cpus_held();
        mutex_lock(&smpboot_threads_lock);
 
        /* Park threads that were exclusively enabled on the old mask. */
-       cpumask_andnot(tmp, old, new);
-       for_each_cpu_and(cpu, tmp, cpu_online_mask)
+       cpumask_andnot(&tmp, old, new);
+       for_each_cpu_and(cpu, &tmp, cpu_online_mask)
                smpboot_park_thread(plug_thread, cpu);
 
        /* Unpark threads that are exclusively enabled on the new mask. */
-       cpumask_andnot(tmp, new, old);
-       for_each_cpu_and(cpu, tmp, cpu_online_mask)
+       cpumask_andnot(&tmp, new, old);
+       for_each_cpu_and(cpu, &tmp, cpu_online_mask)
                smpboot_unpark_thread(plug_thread, cpu);
 
        cpumask_copy(old, new);
 
        mutex_unlock(&smpboot_threads_lock);
-       put_online_cpus();
-
-       free_cpumask_var(tmp);
-
-       return 0;
 }
-EXPORT_SYMBOL_GPL(smpboot_update_cpumask_percpu_thread);
 
 static DEFINE_PER_CPU(atomic_t, cpu_hotplug_state) = ATOMIC_INIT(CPU_POST_DEAD);
 
index 423554a..d9c31bc 100644 (file)
@@ -872,9 +872,9 @@ static struct ctl_table kern_table[] = {
 #if defined(CONFIG_LOCKUP_DETECTOR)
        {
                .procname       = "watchdog",
-               .data           = &watchdog_user_enabled,
-               .maxlen         = sizeof (int),
-               .mode           = 0644,
+               .data           = &watchdog_user_enabled,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
                .proc_handler   = proc_watchdog,
                .extra1         = &zero,
                .extra2         = &one,
@@ -890,16 +890,12 @@ static struct ctl_table kern_table[] = {
        },
        {
                .procname       = "nmi_watchdog",
-               .data           = &nmi_watchdog_enabled,
-               .maxlen         = sizeof (int),
-               .mode           = 0644,
+               .data           = &nmi_watchdog_user_enabled,
+               .maxlen         = sizeof(int),
+               .mode           = NMI_WATCHDOG_SYSCTL_PERM,
                .proc_handler   = proc_nmi_watchdog,
                .extra1         = &zero,
-#if defined(CONFIG_HAVE_NMI_WATCHDOG) || defined(CONFIG_HARDLOCKUP_DETECTOR)
                .extra2         = &one,
-#else
-               .extra2         = &zero,
-#endif
        },
        {
                .procname       = "watchdog_cpumask",
@@ -911,9 +907,9 @@ static struct ctl_table kern_table[] = {
 #ifdef CONFIG_SOFTLOCKUP_DETECTOR
        {
                .procname       = "soft_watchdog",
-               .data           = &soft_watchdog_enabled,
-               .maxlen         = sizeof (int),
-               .mode           = 0644,
+               .data           = &soft_watchdog_user_enabled,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
                .proc_handler   = proc_soft_watchdog,
                .extra1         = &zero,
                .extra2         = &one,
@@ -2188,8 +2184,6 @@ static int do_proc_douintvec_conv(unsigned long *lvalp,
        if (write) {
                if (*lvalp > UINT_MAX)
                        return -EINVAL;
-               if (*lvalp > UINT_MAX)
-                       return -EINVAL;
                *valp = *lvalp;
        } else {
                unsigned int val = *valp;
index 6abfafd..8319e09 100644 (file)
@@ -4954,9 +4954,6 @@ static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata;
 static char ftrace_graph_notrace_buf[FTRACE_FILTER_SIZE] __initdata;
 static int ftrace_graph_set_hash(struct ftrace_hash *hash, char *buffer);
 
-static unsigned long save_global_trampoline;
-static unsigned long save_global_flags;
-
 static int __init set_graph_function(char *str)
 {
        strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE);
@@ -6808,17 +6805,6 @@ void unregister_ftrace_graph(void)
        unregister_pm_notifier(&ftrace_suspend_notifier);
        unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
 
-#ifdef CONFIG_DYNAMIC_FTRACE
-       /*
-        * Function graph does not allocate the trampoline, but
-        * other global_ops do. We need to reset the ALLOC_TRAMP flag
-        * if one was used.
-        */
-       global_ops.trampoline = save_global_trampoline;
-       if (save_global_flags & FTRACE_OPS_FL_ALLOC_TRAMP)
-               global_ops.flags |= FTRACE_OPS_FL_ALLOC_TRAMP;
-#endif
-
  out:
        mutex_unlock(&ftrace_lock);
 }
index f5d5202..6bcb854 100644 (file)
 #include <linux/kvm_para.h>
 #include <linux/kthread.h>
 
-/* Watchdog configuration */
-static DEFINE_MUTEX(watchdog_proc_mutex);
-
-int __read_mostly nmi_watchdog_enabled;
+static DEFINE_MUTEX(watchdog_mutex);
 
 #if defined(CONFIG_HARDLOCKUP_DETECTOR) || defined(CONFIG_HAVE_NMI_WATCHDOG)
-unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED |
-                                               NMI_WATCHDOG_ENABLED;
+# define WATCHDOG_DEFAULT      (SOFT_WATCHDOG_ENABLED | NMI_WATCHDOG_ENABLED)
+# define NMI_WATCHDOG_DEFAULT  1
 #else
-unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED;
+# define WATCHDOG_DEFAULT      (SOFT_WATCHDOG_ENABLED)
+# define NMI_WATCHDOG_DEFAULT  0
 #endif
 
+unsigned long __read_mostly watchdog_enabled;
+int __read_mostly watchdog_user_enabled = 1;
+int __read_mostly nmi_watchdog_user_enabled = NMI_WATCHDOG_DEFAULT;
+int __read_mostly soft_watchdog_user_enabled = 1;
+int __read_mostly watchdog_thresh = 10;
+int __read_mostly nmi_watchdog_available;
+
+struct cpumask watchdog_allowed_mask __read_mostly;
+
+struct cpumask watchdog_cpumask __read_mostly;
+unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
+
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
-/* boot commands */
 /*
  * Should we panic when a soft-lockup or hard-lockup occurs:
  */
@@ -56,9 +65,9 @@ unsigned int __read_mostly hardlockup_panic =
  * kernel command line parameters are parsed, because otherwise it is not
  * possible to override this in hardlockup_panic_setup().
  */
-void hardlockup_detector_disable(void)
+void __init hardlockup_detector_disable(void)
 {
-       watchdog_enabled &= ~NMI_WATCHDOG_ENABLED;
+       nmi_watchdog_user_enabled = 0;
 }
 
 static int __init hardlockup_panic_setup(char *str)
@@ -68,48 +77,24 @@ static int __init hardlockup_panic_setup(char *str)
        else if (!strncmp(str, "nopanic", 7))
                hardlockup_panic = 0;
        else if (!strncmp(str, "0", 1))
-               watchdog_enabled &= ~NMI_WATCHDOG_ENABLED;
+               nmi_watchdog_user_enabled = 0;
        else if (!strncmp(str, "1", 1))
-               watchdog_enabled |= NMI_WATCHDOG_ENABLED;
+               nmi_watchdog_user_enabled = 1;
        return 1;
 }
 __setup("nmi_watchdog=", hardlockup_panic_setup);
 
-#endif
-
-#ifdef CONFIG_SOFTLOCKUP_DETECTOR
-int __read_mostly soft_watchdog_enabled;
-#endif
-
-int __read_mostly watchdog_user_enabled;
-int __read_mostly watchdog_thresh = 10;
-
-#ifdef CONFIG_SMP
-int __read_mostly sysctl_softlockup_all_cpu_backtrace;
+# ifdef CONFIG_SMP
 int __read_mostly sysctl_hardlockup_all_cpu_backtrace;
-#endif
-struct cpumask watchdog_cpumask __read_mostly;
-unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
 
-/*
- * The 'watchdog_running' variable is set to 1 when the watchdog threads
- * are registered/started and is set to 0 when the watchdog threads are
- * unregistered/stopped, so it is an indicator whether the threads exist.
- */
-static int __read_mostly watchdog_running;
-/*
- * If a subsystem has a need to deactivate the watchdog temporarily, it
- * can use the suspend/resume interface to achieve this. The content of
- * the 'watchdog_suspended' variable reflects this state. Existing threads
- * are parked/unparked by the lockup_detector_{suspend|resume} functions
- * (see comment blocks pertaining to those functions for further details).
- *
- * 'watchdog_suspended' also prevents threads from being registered/started
- * or unregistered/stopped via parameters in /proc/sys/kernel, so the state
- * of 'watchdog_running' cannot change while the watchdog is deactivated
- * temporarily (see related code in 'proc' handlers).
- */
-int __read_mostly watchdog_suspended;
+static int __init hardlockup_all_cpu_backtrace_setup(char *str)
+{
+       sysctl_hardlockup_all_cpu_backtrace = !!simple_strtol(str, NULL, 0);
+       return 1;
+}
+__setup("hardlockup_all_cpu_backtrace=", hardlockup_all_cpu_backtrace_setup);
+# endif /* CONFIG_SMP */
+#endif /* CONFIG_HARDLOCKUP_DETECTOR */
 
 /*
  * These functions can be overridden if an architecture implements its
@@ -121,36 +106,68 @@ int __read_mostly watchdog_suspended;
  */
 int __weak watchdog_nmi_enable(unsigned int cpu)
 {
+       hardlockup_detector_perf_enable();
        return 0;
 }
+
 void __weak watchdog_nmi_disable(unsigned int cpu)
 {
+       hardlockup_detector_perf_disable();
 }
 
-/*
- * watchdog_nmi_reconfigure can be implemented to be notified after any
- * watchdog configuration change. The arch hardlockup watchdog should
- * respond to the following variables:
- * - nmi_watchdog_enabled
+/* Return 0, if a NMI watchdog is available. Error code otherwise */
+int __weak __init watchdog_nmi_probe(void)
+{
+       return hardlockup_detector_perf_init();
+}
+
+/**
+ * watchdog_nmi_stop - Stop the watchdog for reconfiguration
+ *
+ * The reconfiguration steps are:
+ * watchdog_nmi_stop();
+ * update_variables();
+ * watchdog_nmi_start();
+ */
+void __weak watchdog_nmi_stop(void) { }
+
+/**
+ * watchdog_nmi_start - Start the watchdog after reconfiguration
+ *
+ * Counterpart to watchdog_nmi_stop().
+ *
+ * The following variables have been updated in update_variables() and
+ * contain the currently valid configuration:
+ * - watchdog_enabled
  * - watchdog_thresh
  * - watchdog_cpumask
- * - sysctl_hardlockup_all_cpu_backtrace
- * - hardlockup_panic
- * - watchdog_suspended
  */
-void __weak watchdog_nmi_reconfigure(void)
+void __weak watchdog_nmi_start(void) { }
+
+/**
+ * lockup_detector_update_enable - Update the sysctl enable bit
+ *
+ * Caller needs to make sure that the NMI/perf watchdogs are off, so this
+ * can't race with watchdog_nmi_disable().
+ */
+static void lockup_detector_update_enable(void)
 {
+       watchdog_enabled = 0;
+       if (!watchdog_user_enabled)
+               return;
+       if (nmi_watchdog_available && nmi_watchdog_user_enabled)
+               watchdog_enabled |= NMI_WATCHDOG_ENABLED;
+       if (soft_watchdog_user_enabled)
+               watchdog_enabled |= SOFT_WATCHDOG_ENABLED;
 }
 
-
 #ifdef CONFIG_SOFTLOCKUP_DETECTOR
 
-/* Helper for online, unparked cpus. */
-#define for_each_watchdog_cpu(cpu) \
-       for_each_cpu_and((cpu), cpu_online_mask, &watchdog_cpumask)
-
-atomic_t watchdog_park_in_progress = ATOMIC_INIT(0);
+/* Global variables, exported for sysctl */
+unsigned int __read_mostly softlockup_panic =
+                       CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
 
+static bool softlockup_threads_initialized __read_mostly;
 static u64 __read_mostly sample_period;
 
 static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts);
@@ -164,50 +181,40 @@ static DEFINE_PER_CPU(struct task_struct *, softlockup_task_ptr_saved);
 static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved);
 static unsigned long soft_lockup_nmi_warn;
 
-unsigned int __read_mostly softlockup_panic =
-                       CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
-
 static int __init softlockup_panic_setup(char *str)
 {
        softlockup_panic = simple_strtoul(str, NULL, 0);
-
        return 1;
 }
 __setup("softlockup_panic=", softlockup_panic_setup);
 
 static int __init nowatchdog_setup(char *str)
 {
-       watchdog_enabled = 0;
+       watchdog_user_enabled = 0;
        return 1;
 }
 __setup("nowatchdog", nowatchdog_setup);
 
 static int __init nosoftlockup_setup(char *str)
 {
-       watchdog_enabled &= ~SOFT_WATCHDOG_ENABLED;
+       soft_watchdog_user_enabled = 0;
        return 1;
 }
 __setup("nosoftlockup", nosoftlockup_setup);
 
 #ifdef CONFIG_SMP
+int __read_mostly sysctl_softlockup_all_cpu_backtrace;
+
 static int __init softlockup_all_cpu_backtrace_setup(char *str)
 {
-       sysctl_softlockup_all_cpu_backtrace =
-               !!simple_strtol(str, NULL, 0);
+       sysctl_softlockup_all_cpu_backtrace = !!simple_strtol(str, NULL, 0);
        return 1;
 }
 __setup("softlockup_all_cpu_backtrace=", softlockup_all_cpu_backtrace_setup);
-#ifdef CONFIG_HARDLOCKUP_DETECTOR
-static int __init hardlockup_all_cpu_backtrace_setup(char *str)
-{
-       sysctl_hardlockup_all_cpu_backtrace =
-               !!simple_strtol(str, NULL, 0);
-       return 1;
-}
-__setup("hardlockup_all_cpu_backtrace=", hardlockup_all_cpu_backtrace_setup);
-#endif
 #endif
 
+static void __lockup_detector_cleanup(void);
+
 /*
  * Hard-lockup warnings should be triggered after just a few seconds. Soft-
  * lockups can have false positives under extreme conditions. So we generally
@@ -278,11 +285,15 @@ void touch_all_softlockup_watchdogs(void)
        int cpu;
 
        /*
-        * this is done lockless
-        * do we care if a 0 races with a timestamp?
-        * all it means is the softlock check starts one cycle later
+        * watchdog_mutex cannpt be taken here, as this might be called
+        * from (soft)interrupt context, so the access to
+        * watchdog_allowed_cpumask might race with a concurrent update.
+        *
+        * The watchdog time stamp can race against a concurrent real
+        * update as well, the only side effect might be a cycle delay for
+        * the softlockup check.
         */
-       for_each_watchdog_cpu(cpu)
+       for_each_cpu(cpu, &watchdog_allowed_mask)
                per_cpu(watchdog_touch_ts, cpu) = 0;
        wq_watchdog_touch(-1);
 }
@@ -322,9 +333,6 @@ static void watchdog_interrupt_count(void)
        __this_cpu_inc(hrtimer_interrupts);
 }
 
-static int watchdog_enable_all_cpus(void);
-static void watchdog_disable_all_cpus(void);
-
 /* watchdog kicker functions */
 static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
 {
@@ -333,7 +341,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
        int duration;
        int softlockup_all_cpu_backtrace = sysctl_softlockup_all_cpu_backtrace;
 
-       if (atomic_read(&watchdog_park_in_progress) != 0)
+       if (!watchdog_enabled)
                return HRTIMER_NORESTART;
 
        /* kick the hardlockup detector */
@@ -447,32 +455,38 @@ static void watchdog_set_prio(unsigned int policy, unsigned int prio)
 
 static void watchdog_enable(unsigned int cpu)
 {
-       struct hrtimer *hrtimer = raw_cpu_ptr(&watchdog_hrtimer);
+       struct hrtimer *hrtimer = this_cpu_ptr(&watchdog_hrtimer);
 
-       /* kick off the timer for the hardlockup detector */
+       /*
+        * Start the timer first to prevent the NMI watchdog triggering
+        * before the timer has a chance to fire.
+        */
        hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        hrtimer->function = watchdog_timer_fn;
-
-       /* Enable the perf event */
-       watchdog_nmi_enable(cpu);
-
-       /* done here because hrtimer_start can only pin to smp_processor_id() */
        hrtimer_start(hrtimer, ns_to_ktime(sample_period),
                      HRTIMER_MODE_REL_PINNED);
 
-       /* initialize timestamp */
-       watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - 1);
+       /* Initialize timestamp */
        __touch_watchdog();
+       /* Enable the perf event */
+       if (watchdog_enabled & NMI_WATCHDOG_ENABLED)
+               watchdog_nmi_enable(cpu);
+
+       watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - 1);
 }
 
 static void watchdog_disable(unsigned int cpu)
 {
-       struct hrtimer *hrtimer = raw_cpu_ptr(&watchdog_hrtimer);
+       struct hrtimer *hrtimer = this_cpu_ptr(&watchdog_hrtimer);
 
        watchdog_set_prio(SCHED_NORMAL, 0);
-       hrtimer_cancel(hrtimer);
-       /* disable the perf event */
+       /*
+        * Disable the perf event first. That prevents that a large delay
+        * between disabling the timer and disabling the perf event causes
+        * the perf NMI to detect a false positive.
+        */
        watchdog_nmi_disable(cpu);
+       hrtimer_cancel(hrtimer);
 }
 
 static void watchdog_cleanup(unsigned int cpu, bool online)
@@ -499,21 +513,6 @@ static void watchdog(unsigned int cpu)
        __this_cpu_write(soft_lockup_hrtimer_cnt,
                         __this_cpu_read(hrtimer_interrupts));
        __touch_watchdog();
-
-       /*
-        * watchdog_nmi_enable() clears the NMI_WATCHDOG_ENABLED bit in the
-        * failure path. Check for failures that can occur asynchronously -
-        * for example, when CPUs are on-lined - and shut down the hardware
-        * perf event on each CPU accordingly.
-        *
-        * The only non-obvious place this bit can be cleared is through
-        * watchdog_nmi_enable(), so a pr_info() is placed there.  Placing a
-        * pr_info here would be too noisy as it would result in a message
-        * every few seconds if the hardlockup was disabled but the softlockup
-        * enabled.
-        */
-       if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
-               watchdog_nmi_disable(cpu);
 }
 
 static struct smp_hotplug_thread watchdog_threads = {
@@ -527,295 +526,174 @@ static struct smp_hotplug_thread watchdog_threads = {
        .unpark                 = watchdog_enable,
 };
 
-/*
- * park all watchdog threads that are specified in 'watchdog_cpumask'
- *
- * This function returns an error if kthread_park() of a watchdog thread
- * fails. In this situation, the watchdog threads of some CPUs can already
- * be parked and the watchdog threads of other CPUs can still be runnable.
- * Callers are expected to handle this special condition as appropriate in
- * their context.
- *
- * This function may only be called in a context that is protected against
- * races with CPU hotplug - for example, via get_online_cpus().
- */
-static int watchdog_park_threads(void)
+static void softlockup_update_smpboot_threads(void)
 {
-       int cpu, ret = 0;
+       lockdep_assert_held(&watchdog_mutex);
 
-       atomic_set(&watchdog_park_in_progress, 1);
+       if (!softlockup_threads_initialized)
+               return;
 
-       for_each_watchdog_cpu(cpu) {
-               ret = kthread_park(per_cpu(softlockup_watchdog, cpu));
-               if (ret)
-                       break;
-       }
-
-       atomic_set(&watchdog_park_in_progress, 0);
-
-       return ret;
+       smpboot_update_cpumask_percpu_thread(&watchdog_threads,
+                                            &watchdog_allowed_mask);
 }
 
-/*
- * unpark all watchdog threads that are specified in 'watchdog_cpumask'
- *
- * This function may only be called in a context that is protected against
- * races with CPU hotplug - for example, via get_online_cpus().
- */
-static void watchdog_unpark_threads(void)
+/* Temporarily park all watchdog threads */
+static void softlockup_park_all_threads(void)
 {
-       int cpu;
-
-       for_each_watchdog_cpu(cpu)
-               kthread_unpark(per_cpu(softlockup_watchdog, cpu));
+       cpumask_clear(&watchdog_allowed_mask);
+       softlockup_update_smpboot_threads();
 }
 
-static int update_watchdog_all_cpus(void)
+/* Unpark enabled threads */
+static void softlockup_unpark_threads(void)
 {
-       int ret;
-
-       ret = watchdog_park_threads();
-       if (ret)
-               return ret;
-
-       watchdog_unpark_threads();
-
-       return 0;
+       cpumask_copy(&watchdog_allowed_mask, &watchdog_cpumask);
+       softlockup_update_smpboot_threads();
 }
 
-static int watchdog_enable_all_cpus(void)
+static void lockup_detector_reconfigure(void)
 {
-       int err = 0;
-
-       if (!watchdog_running) {
-               err = smpboot_register_percpu_thread_cpumask(&watchdog_threads,
-                                                            &watchdog_cpumask);
-               if (err)
-                       pr_err("Failed to create watchdog threads, disabled\n");
-               else
-                       watchdog_running = 1;
-       } else {
-               /*
-                * Enable/disable the lockup detectors or
-                * change the sample period 'on the fly'.
-                */
-               err = update_watchdog_all_cpus();
-
-               if (err) {
-                       watchdog_disable_all_cpus();
-                       pr_err("Failed to update lockup detectors, disabled\n");
-               }
-       }
-
-       if (err)
-               watchdog_enabled = 0;
-
-       return err;
+       cpus_read_lock();
+       watchdog_nmi_stop();
+       softlockup_park_all_threads();
+       set_sample_period();
+       lockup_detector_update_enable();
+       if (watchdog_enabled && watchdog_thresh)
+               softlockup_unpark_threads();
+       watchdog_nmi_start();
+       cpus_read_unlock();
+       /*
+        * Must be called outside the cpus locked section to prevent
+        * recursive locking in the perf code.
+        */
+       __lockup_detector_cleanup();
 }
 
-static void watchdog_disable_all_cpus(void)
+/*
+ * Create the watchdog thread infrastructure and configure the detector(s).
+ *
+ * The threads are not unparked as watchdog_allowed_mask is empty.  When
+ * the threads are sucessfully initialized, take the proper locks and
+ * unpark the threads in the watchdog_cpumask if the watchdog is enabled.
+ */
+static __init void lockup_detector_setup(void)
 {
-       if (watchdog_running) {
-               watchdog_running = 0;
-               smpboot_unregister_percpu_thread(&watchdog_threads);
-       }
-}
+       int ret;
 
-#ifdef CONFIG_SYSCTL
-static int watchdog_update_cpus(void)
-{
-       return smpboot_update_cpumask_percpu_thread(
-                   &watchdog_threads, &watchdog_cpumask);
-}
-#endif
+       /*
+        * If sysctl is off and watchdog got disabled on the command line,
+        * nothing to do here.
+        */
+       lockup_detector_update_enable();
 
-#else /* SOFTLOCKUP */
-static int watchdog_park_threads(void)
-{
-       return 0;
-}
+       if (!IS_ENABLED(CONFIG_SYSCTL) &&
+           !(watchdog_enabled && watchdog_thresh))
+               return;
 
-static void watchdog_unpark_threads(void)
-{
-}
+       ret = smpboot_register_percpu_thread_cpumask(&watchdog_threads,
+                                                    &watchdog_allowed_mask);
+       if (ret) {
+               pr_err("Failed to initialize soft lockup detector threads\n");
+               return;
+       }
 
-static int watchdog_enable_all_cpus(void)
-{
-       return 0;
+       mutex_lock(&watchdog_mutex);
+       softlockup_threads_initialized = true;
+       lockup_detector_reconfigure();
+       mutex_unlock(&watchdog_mutex);
 }
 
-static void watchdog_disable_all_cpus(void)
+#else /* CONFIG_SOFTLOCKUP_DETECTOR */
+static inline int watchdog_park_threads(void) { return 0; }
+static inline void watchdog_unpark_threads(void) { }
+static inline int watchdog_enable_all_cpus(void) { return 0; }
+static inline void watchdog_disable_all_cpus(void) { }
+static void lockup_detector_reconfigure(void)
 {
+       cpus_read_lock();
+       watchdog_nmi_stop();
+       lockup_detector_update_enable();
+       watchdog_nmi_start();
+       cpus_read_unlock();
 }
-
-#ifdef CONFIG_SYSCTL
-static int watchdog_update_cpus(void)
+static inline void lockup_detector_setup(void)
 {
-       return 0;
+       lockup_detector_reconfigure();
 }
-#endif
+#endif /* !CONFIG_SOFTLOCKUP_DETECTOR */
 
-static void set_sample_period(void)
+static void __lockup_detector_cleanup(void)
 {
+       lockdep_assert_held(&watchdog_mutex);
+       hardlockup_detector_perf_cleanup();
 }
-#endif /* SOFTLOCKUP */
 
-/*
- * Suspend the hard and soft lockup detector by parking the watchdog threads.
+/**
+ * lockup_detector_cleanup - Cleanup after cpu hotplug or sysctl changes
+ *
+ * Caller must not hold the cpu hotplug rwsem.
  */
-int lockup_detector_suspend(void)
+void lockup_detector_cleanup(void)
 {
-       int ret = 0;
-
-       get_online_cpus();
-       mutex_lock(&watchdog_proc_mutex);
-       /*
-        * Multiple suspend requests can be active in parallel (counted by
-        * the 'watchdog_suspended' variable). If the watchdog threads are
-        * running, the first caller takes care that they will be parked.
-        * The state of 'watchdog_running' cannot change while a suspend
-        * request is active (see related code in 'proc' handlers).
-        */
-       if (watchdog_running && !watchdog_suspended)
-               ret = watchdog_park_threads();
-
-       if (ret == 0)
-               watchdog_suspended++;
-       else {
-               watchdog_disable_all_cpus();
-               pr_err("Failed to suspend lockup detectors, disabled\n");
-               watchdog_enabled = 0;
-       }
-
-       watchdog_nmi_reconfigure();
-
-       mutex_unlock(&watchdog_proc_mutex);
-
-       return ret;
+       mutex_lock(&watchdog_mutex);
+       __lockup_detector_cleanup();
+       mutex_unlock(&watchdog_mutex);
 }
 
-/*
- * Resume the hard and soft lockup detector by unparking the watchdog threads.
+/**
+ * lockup_detector_soft_poweroff - Interface to stop lockup detector(s)
+ *
+ * Special interface for parisc. It prevents lockup detector warnings from
+ * the default pm_poweroff() function which busy loops forever.
  */
-void lockup_detector_resume(void)
+void lockup_detector_soft_poweroff(void)
 {
-       mutex_lock(&watchdog_proc_mutex);
-
-       watchdog_suspended--;
-       /*
-        * The watchdog threads are unparked if they were previously running
-        * and if there is no more active suspend request.
-        */
-       if (watchdog_running && !watchdog_suspended)
-               watchdog_unpark_threads();
-
-       watchdog_nmi_reconfigure();
-
-       mutex_unlock(&watchdog_proc_mutex);
-       put_online_cpus();
+       watchdog_enabled = 0;
 }
 
 #ifdef CONFIG_SYSCTL
 
-/*
- * Update the run state of the lockup detectors.
- */
-static int proc_watchdog_update(void)
+/* Propagate any changes to the watchdog threads */
+static void proc_watchdog_update(void)
 {
-       int err = 0;
-
-       /*
-        * Watchdog threads won't be started if they are already active.
-        * The 'watchdog_running' variable in watchdog_*_all_cpus() takes
-        * care of this. If those threads are already active, the sample
-        * period will be updated and the lockup detectors will be enabled
-        * or disabled 'on the fly'.
-        */
-       if (watchdog_enabled && watchdog_thresh)
-               err = watchdog_enable_all_cpus();
-       else
-               watchdog_disable_all_cpus();
-
-       watchdog_nmi_reconfigure();
-
-       return err;
-
+       /* Remove impossible cpus to keep sysctl output clean. */
+       cpumask_and(&watchdog_cpumask, &watchdog_cpumask, cpu_possible_mask);
+       lockup_detector_reconfigure();
 }
 
 /*
  * common function for watchdog, nmi_watchdog and soft_watchdog parameter
  *
- * caller             | table->data points to | 'which' contains the flag(s)
- * -------------------|-----------------------|-----------------------------
- * proc_watchdog      | watchdog_user_enabled | NMI_WATCHDOG_ENABLED or'ed
- *                    |                       | with SOFT_WATCHDOG_ENABLED
- * -------------------|-----------------------|-----------------------------
- * proc_nmi_watchdog  | nmi_watchdog_enabled  | NMI_WATCHDOG_ENABLED
- * -------------------|-----------------------|-----------------------------
- * proc_soft_watchdog | soft_watchdog_enabled | SOFT_WATCHDOG_ENABLED
+ * caller             | table->data points to      | 'which'
+ * -------------------|----------------------------|--------------------------
+ * proc_watchdog      | watchdog_user_enabled      | NMI_WATCHDOG_ENABLED |
+ *                    |                            | SOFT_WATCHDOG_ENABLED
+ * -------------------|----------------------------|--------------------------
+ * proc_nmi_watchdog  | nmi_watchdog_user_enabled  | NMI_WATCHDOG_ENABLED
+ * -------------------|----------------------------|--------------------------
+ * proc_soft_watchdog | soft_watchdog_user_enabled | SOFT_WATCHDOG_ENABLED
  */
 static int proc_watchdog_common(int which, struct ctl_table *table, int write,
                                void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-       int err, old, new;
-       int *watchdog_param = (int *)table->data;
+       int err, old, *param = table->data;
 
-       get_online_cpus();
-       mutex_lock(&watchdog_proc_mutex);
+       mutex_lock(&watchdog_mutex);
 
-       if (watchdog_suspended) {
-               /* no parameter changes allowed while watchdog is suspended */
-               err = -EAGAIN;
-               goto out;
-       }
-
-       /*
-        * If the parameter is being read return the state of the corresponding
-        * bit(s) in 'watchdog_enabled', else update 'watchdog_enabled' and the
-        * run state of the lockup detectors.
-        */
        if (!write) {
-               *watchdog_param = (watchdog_enabled & which) != 0;
+               /*
+                * On read synchronize the userspace interface. This is a
+                * racy snapshot.
+                */
+               *param = (watchdog_enabled & which) != 0;
                err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
        } else {
+               old = READ_ONCE(*param);
                err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
-               if (err)
-                       goto out;
-
-               /*
-                * There is a race window between fetching the current value
-                * from 'watchdog_enabled' and storing the new value. During
-                * this race window, watchdog_nmi_enable() can sneak in and
-                * clear the NMI_WATCHDOG_ENABLED bit in 'watchdog_enabled'.
-                * The 'cmpxchg' detects this race and the loop retries.
-                */
-               do {
-                       old = watchdog_enabled;
-                       /*
-                        * If the parameter value is not zero set the
-                        * corresponding bit(s), else clear it(them).
-                        */
-                       if (*watchdog_param)
-                               new = old | which;
-                       else
-                               new = old & ~which;
-               } while (cmpxchg(&watchdog_enabled, old, new) != old);
-
-               /*
-                * Update the run state of the lockup detectors. There is _no_
-                * need to check the value returned by proc_watchdog_update()
-                * and to restore the previous value of 'watchdog_enabled' as
-                * both lockup detectors are disabled if proc_watchdog_update()
-                * returns an error.
-                */
-               if (old == new)
-                       goto out;
-
-               err = proc_watchdog_update();
+               if (!err && old != READ_ONCE(*param))
+                       proc_watchdog_update();
        }
-out:
-       mutex_unlock(&watchdog_proc_mutex);
-       put_online_cpus();
+       mutex_unlock(&watchdog_mutex);
        return err;
 }
 
@@ -835,6 +713,8 @@ int proc_watchdog(struct ctl_table *table, int write,
 int proc_nmi_watchdog(struct ctl_table *table, int write,
                      void __user *buffer, size_t *lenp, loff_t *ppos)
 {
+       if (!nmi_watchdog_available && write)
+               return -ENOTSUPP;
        return proc_watchdog_common(NMI_WATCHDOG_ENABLED,
                                    table, write, buffer, lenp, ppos);
 }
@@ -855,39 +735,17 @@ int proc_soft_watchdog(struct ctl_table *table, int write,
 int proc_watchdog_thresh(struct ctl_table *table, int write,
                         void __user *buffer, size_t *lenp, loff_t *ppos)
 {
-       int err, old, new;
-
-       get_online_cpus();
-       mutex_lock(&watchdog_proc_mutex);
+       int err, old;
 
-       if (watchdog_suspended) {
-               /* no parameter changes allowed while watchdog is suspended */
-               err = -EAGAIN;
-               goto out;
-       }
+       mutex_lock(&watchdog_mutex);
 
-       old = ACCESS_ONCE(watchdog_thresh);
+       old = READ_ONCE(watchdog_thresh);
        err = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
 
-       if (err || !write)
-               goto out;
-
-       /*
-        * Update the sample period. Restore on failure.
-        */
-       new = ACCESS_ONCE(watchdog_thresh);
-       if (old == new)
-               goto out;
+       if (!err && write && old != READ_ONCE(watchdog_thresh))
+               proc_watchdog_update();
 
-       set_sample_period();
-       err = proc_watchdog_update();
-       if (err) {
-               watchdog_thresh = old;
-               set_sample_period();
-       }
-out:
-       mutex_unlock(&watchdog_proc_mutex);
-       put_online_cpus();
+       mutex_unlock(&watchdog_mutex);
        return err;
 }
 
@@ -902,45 +760,19 @@ int proc_watchdog_cpumask(struct ctl_table *table, int write,
 {
        int err;
 
-       get_online_cpus();
-       mutex_lock(&watchdog_proc_mutex);
-
-       if (watchdog_suspended) {
-               /* no parameter changes allowed while watchdog is suspended */
-               err = -EAGAIN;
-               goto out;
-       }
+       mutex_lock(&watchdog_mutex);
 
        err = proc_do_large_bitmap(table, write, buffer, lenp, ppos);
-       if (!err && write) {
-               /* Remove impossible cpus to keep sysctl output cleaner. */
-               cpumask_and(&watchdog_cpumask, &watchdog_cpumask,
-                           cpu_possible_mask);
-
-               if (watchdog_running) {
-                       /*
-                        * Failure would be due to being unable to allocate
-                        * a temporary cpumask, so we are likely not in a
-                        * position to do much else to make things better.
-                        */
-                       if (watchdog_update_cpus() != 0)
-                               pr_err("cpumask update failed\n");
-               }
+       if (!err && write)
+               proc_watchdog_update();
 
-               watchdog_nmi_reconfigure();
-       }
-out:
-       mutex_unlock(&watchdog_proc_mutex);
-       put_online_cpus();
+       mutex_unlock(&watchdog_mutex);
        return err;
 }
-
 #endif /* CONFIG_SYSCTL */
 
 void __init lockup_detector_init(void)
 {
-       set_sample_period();
-
 #ifdef CONFIG_NO_HZ_FULL
        if (tick_nohz_full_enabled()) {
                pr_info("Disabling watchdog on nohz_full cores by default\n");
@@ -951,6 +783,7 @@ void __init lockup_detector_init(void)
        cpumask_copy(&watchdog_cpumask, cpu_possible_mask);
 #endif
 
-       if (watchdog_enabled)
-               watchdog_enable_all_cpus();
+       if (!watchdog_nmi_probe())
+               nmi_watchdog_available = true;
+       lockup_detector_setup();
 }
index 3a09ea1..71a62ce 100644 (file)
 static DEFINE_PER_CPU(bool, hard_watchdog_warn);
 static DEFINE_PER_CPU(bool, watchdog_nmi_touch);
 static DEFINE_PER_CPU(struct perf_event *, watchdog_ev);
+static struct cpumask dead_events_mask;
 
 static unsigned long hardlockup_allcpu_dumped;
+static unsigned int watchdog_cpus;
 
 void arch_touch_nmi_watchdog(void)
 {
@@ -103,15 +105,12 @@ static struct perf_event_attr wd_hw_attr = {
 
 /* Callback function for perf event subsystem */
 static void watchdog_overflow_callback(struct perf_event *event,
-                struct perf_sample_data *data,
-                struct pt_regs *regs)
+                                      struct perf_sample_data *data,
+                                      struct pt_regs *regs)
 {
        /* Ensure the watchdog never gets throttled */
        event->hw.interrupts = 0;
 
-       if (atomic_read(&watchdog_park_in_progress) != 0)
-               return;
-
        if (__this_cpu_read(watchdog_nmi_touch) == true) {
                __this_cpu_write(watchdog_nmi_touch, false);
                return;
@@ -160,104 +159,131 @@ static void watchdog_overflow_callback(struct perf_event *event,
        return;
 }
 
-/*
- * People like the simple clean cpu node info on boot.
- * Reduce the watchdog noise by only printing messages
- * that are different from what cpu0 displayed.
- */
-static unsigned long firstcpu_err;
-static atomic_t watchdog_cpus;
-
-int watchdog_nmi_enable(unsigned int cpu)
+static int hardlockup_detector_event_create(void)
 {
+       unsigned int cpu = smp_processor_id();
        struct perf_event_attr *wd_attr;
-       struct perf_event *event = per_cpu(watchdog_ev, cpu);
-       int firstcpu = 0;
-
-       /* nothing to do if the hard lockup detector is disabled */
-       if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
-               goto out;
-
-       /* is it already setup and enabled? */
-       if (event && event->state > PERF_EVENT_STATE_OFF)
-               goto out;
-
-       /* it is setup but not enabled */
-       if (event != NULL)
-               goto out_enable;
-
-       if (atomic_inc_return(&watchdog_cpus) == 1)
-               firstcpu = 1;
+       struct perf_event *evt;
 
        wd_attr = &wd_hw_attr;
        wd_attr->sample_period = hw_nmi_get_sample_period(watchdog_thresh);
 
        /* Try to register using hardware perf events */
-       event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL);
+       evt = perf_event_create_kernel_counter(wd_attr, cpu, NULL,
+                                              watchdog_overflow_callback, NULL);
+       if (IS_ERR(evt)) {
+               pr_info("Perf event create on CPU %d failed with %ld\n", cpu,
+                       PTR_ERR(evt));
+               return PTR_ERR(evt);
+       }
+       this_cpu_write(watchdog_ev, evt);
+       return 0;
+}
 
-       /* save the first cpu's error for future comparision */
-       if (firstcpu && IS_ERR(event))
-               firstcpu_err = PTR_ERR(event);
+/**
+ * hardlockup_detector_perf_enable - Enable the local event
+ */
+void hardlockup_detector_perf_enable(void)
+{
+       if (hardlockup_detector_event_create())
+               return;
 
-       if (!IS_ERR(event)) {
-               /* only print for the first cpu initialized */
-               if (firstcpu || firstcpu_err)
-                       pr_info("enabled on all CPUs, permanently consumes one hw-PMU counter.\n");
-               goto out_save;
-       }
+       if (!watchdog_cpus++)
+               pr_info("Enabled. Permanently consumes one hw-PMU counter.\n");
 
-       /*
-        * Disable the hard lockup detector if _any_ CPU fails to set up
-        * set up the hardware perf event. The watchdog() function checks
-        * the NMI_WATCHDOG_ENABLED bit periodically.
-        *
-        * The barriers are for syncing up watchdog_enabled across all the
-        * cpus, as clear_bit() does not use barriers.
-        */
-       smp_mb__before_atomic();
-       clear_bit(NMI_WATCHDOG_ENABLED_BIT, &watchdog_enabled);
-       smp_mb__after_atomic();
-
-       /* skip displaying the same error again */
-       if (!firstcpu && (PTR_ERR(event) == firstcpu_err))
-               return PTR_ERR(event);
-
-       /* vary the KERN level based on the returned errno */
-       if (PTR_ERR(event) == -EOPNOTSUPP)
-               pr_info("disabled (cpu%i): not supported (no LAPIC?)\n", cpu);
-       else if (PTR_ERR(event) == -ENOENT)
-               pr_warn("disabled (cpu%i): hardware events not enabled\n",
-                        cpu);
-       else
-               pr_err("disabled (cpu%i): unable to create perf event: %ld\n",
-                       cpu, PTR_ERR(event));
-
-       pr_info("Shutting down hard lockup detector on all cpus\n");
-
-       return PTR_ERR(event);
-
-       /* success path */
-out_save:
-       per_cpu(watchdog_ev, cpu) = event;
-out_enable:
-       perf_event_enable(per_cpu(watchdog_ev, cpu));
-out:
-       return 0;
+       perf_event_enable(this_cpu_read(watchdog_ev));
 }
 
-void watchdog_nmi_disable(unsigned int cpu)
+/**
+ * hardlockup_detector_perf_disable - Disable the local event
+ */
+void hardlockup_detector_perf_disable(void)
 {
-       struct perf_event *event = per_cpu(watchdog_ev, cpu);
+       struct perf_event *event = this_cpu_read(watchdog_ev);
 
        if (event) {
                perf_event_disable(event);
+               cpumask_set_cpu(smp_processor_id(), &dead_events_mask);
+               watchdog_cpus--;
+       }
+}
+
+/**
+ * hardlockup_detector_perf_cleanup - Cleanup disabled events and destroy them
+ *
+ * Called from lockup_detector_cleanup(). Serialized by the caller.
+ */
+void hardlockup_detector_perf_cleanup(void)
+{
+       int cpu;
+
+       for_each_cpu(cpu, &dead_events_mask) {
+               struct perf_event *event = per_cpu(watchdog_ev, cpu);
+
+               /*
+                * Required because for_each_cpu() reports  unconditionally
+                * CPU0 as set on UP kernels. Sigh.
+                */
+               if (event)
+                       perf_event_release_kernel(event);
                per_cpu(watchdog_ev, cpu) = NULL;
+       }
+       cpumask_clear(&dead_events_mask);
+}
+
+/**
+ * hardlockup_detector_perf_stop - Globally stop watchdog events
+ *
+ * Special interface for x86 to handle the perf HT bug.
+ */
+void __init hardlockup_detector_perf_stop(void)
+{
+       int cpu;
+
+       lockdep_assert_cpus_held();
+
+       for_each_online_cpu(cpu) {
+               struct perf_event *event = per_cpu(watchdog_ev, cpu);
+
+               if (event)
+                       perf_event_disable(event);
+       }
+}
 
-               /* should be in cleanup, but blocks oprofile */
-               perf_event_release_kernel(event);
+/**
+ * hardlockup_detector_perf_restart - Globally restart watchdog events
+ *
+ * Special interface for x86 to handle the perf HT bug.
+ */
+void __init hardlockup_detector_perf_restart(void)
+{
+       int cpu;
+
+       lockdep_assert_cpus_held();
+
+       if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
+               return;
+
+       for_each_online_cpu(cpu) {
+               struct perf_event *event = per_cpu(watchdog_ev, cpu);
+
+               if (event)
+                       perf_event_enable(event);
+       }
+}
+
+/**
+ * hardlockup_detector_perf_init - Probe whether NMI event is available at all
+ */
+int __init hardlockup_detector_perf_init(void)
+{
+       int ret = hardlockup_detector_event_create();
 
-               /* watchdog_nmi_enable() expects this to be zero initially. */
-               if (atomic_dec_and_test(&watchdog_cpus))
-                       firstcpu_err = 0;
+       if (ret) {
+               pr_info("Perf NMI watchdog permanently disabled\n");
+       } else {
+               perf_event_release_kernel(this_cpu_read(watchdog_ev));
+               this_cpu_write(watchdog_ev, NULL);
        }
+       return ret;
 }
index f9adf48..edd9b2b 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -146,8 +146,8 @@ EXPORT_SYMBOL(idr_get_next_ext);
  * idr_alloc() and idr_remove() (as long as the ID being removed is not
  * the one being replaced!).
  *
- * Returns: 0 on success.  %-ENOENT indicates that @id was not found.
- * %-EINVAL indicates that @id or @ptr were not valid.
+ * Returns: the old value on success.  %-ENOENT indicates that @id was not
+ * found.  %-EINVAL indicates that @id or @ptr were not valid.
  */
 void *idr_replace(struct idr *idr, void *ptr, int id)
 {
index e590523..f237a09 100644 (file)
@@ -294,6 +294,26 @@ static void cleanup_uevent_env(struct subprocess_info *info)
 }
 #endif
 
+static void zap_modalias_env(struct kobj_uevent_env *env)
+{
+       static const char modalias_prefix[] = "MODALIAS=";
+       int i;
+
+       for (i = 0; i < env->envp_idx;) {
+               if (strncmp(env->envp[i], modalias_prefix,
+                           sizeof(modalias_prefix) - 1)) {
+                       i++;
+                       continue;
+               }
+
+               if (i != env->envp_idx - 1)
+                       memmove(&env->envp[i], &env->envp[i + 1],
+                               sizeof(env->envp[i]) * env->envp_idx - 1);
+
+               env->envp_idx--;
+       }
+}
+
 /**
  * kobject_uevent_env - send an uevent with environmental data
  *
@@ -409,16 +429,29 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
                }
        }
 
-       /*
-        * Mark "add" and "remove" events in the object to ensure proper
-        * events to userspace during automatic cleanup. If the object did
-        * send an "add" event, "remove" will automatically generated by
-        * the core, if not already done by the caller.
-        */
-       if (action == KOBJ_ADD)
+       switch (action) {
+       case KOBJ_ADD:
+               /*
+                * Mark "add" event so we can make sure we deliver "remove"
+                * event to userspace during automatic cleanup. If
+                * the object did send an "add" event, "remove" will
+                * automatically generated by the core, if not already done
+                * by the caller.
+                */
                kobj->state_add_uevent_sent = 1;
-       else if (action == KOBJ_REMOVE)
+               break;
+
+       case KOBJ_REMOVE:
                kobj->state_remove_uevent_sent = 1;
+               break;
+
+       case KOBJ_UNBIND:
+               zap_modalias_env(env);
+               break;
+
+       default:
+               break;
+       }
 
        mutex_lock(&uevent_sock_mutex);
        /* we will send an event, so request a new sequence number */
index bd35743..141734d 100644 (file)
@@ -85,8 +85,8 @@ static FORCE_INLINE int LZ4_decompress_generic(
        const BYTE * const lowLimit = lowPrefix - dictSize;
 
        const BYTE * const dictEnd = (const BYTE *)dictStart + dictSize;
-       const unsigned int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };
-       const int dec64table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
+       static const unsigned int dec32table[] = { 0, 1, 2, 1, 4, 4, 4, 4 };
+       static const int dec64table[] = { 0, 0, 0, -1, 0, 1, 2, 3 };
 
        const int safeDecode = (endOnInput == endOnInputSize);
        const int checkOffset = ((safeDecode) && (dictSize < (int)(64 * KB)));
index 08f8043..d01f471 100644 (file)
@@ -48,7 +48,9 @@ int ___ratelimit(struct ratelimit_state *rs, const char *func)
        if (time_is_before_jiffies(rs->begin + rs->interval)) {
                if (rs->missed) {
                        if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) {
-                               pr_warn("%s: %d callbacks suppressed\n", func, rs->missed);
+                               printk_deferred(KERN_WARNING
+                                               "%s: %d callbacks suppressed\n",
+                                               func, rs->missed);
                                rs->missed = 0;
                        }
                }
index fb548e4..03d31a8 100644 (file)
@@ -1999,17 +1999,14 @@ void wakeup_kcompactd(pg_data_t *pgdat, int order, int classzone_idx)
        if (pgdat->kcompactd_max_order < order)
                pgdat->kcompactd_max_order = order;
 
-       /*
-        * Pairs with implicit barrier in wait_event_freezable()
-        * such that wakeups are not missed in the lockless
-        * waitqueue_active() call.
-        */
-       smp_acquire__after_ctrl_dep();
-
        if (pgdat->kcompactd_classzone_idx > classzone_idx)
                pgdat->kcompactd_classzone_idx = classzone_idx;
 
-       if (!waitqueue_active(&pgdat->kcompactd_wait))
+       /*
+        * Pairs with implicit barrier in wait_event_freezable()
+        * such that wakeups are not missed.
+        */
+       if (!wq_has_sleeper(&pgdat->kcompactd_wait))
                return;
 
        if (!kcompactd_node_suitable(pgdat))
index db250d0..594d73f 100644 (file)
@@ -620,6 +620,14 @@ int file_check_and_advance_wb_err(struct file *file)
                trace_file_check_and_advance_wb_err(file, old);
                spin_unlock(&file->f_lock);
        }
+
+       /*
+        * We're mostly using this function as a drop in replacement for
+        * filemap_check_errors. Clear AS_EIO/AS_ENOSPC to emulate the effect
+        * that the legacy code would have had on these flags.
+        */
+       clear_bit(AS_EIO, &mapping->flags);
+       clear_bit(AS_ENOSPC, &mapping->flags);
        return err;
 }
 EXPORT_SYMBOL(file_check_and_advance_wb_err);
index 15dd741..6cb60f4 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -1990,6 +1990,7 @@ static void stable_tree_append(struct rmap_item *rmap_item,
  */
 static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item)
 {
+       struct mm_struct *mm = rmap_item->mm;
        struct rmap_item *tree_rmap_item;
        struct page *tree_page = NULL;
        struct stable_node *stable_node;
@@ -2062,9 +2063,11 @@ static void cmp_and_merge_page(struct page *page, struct rmap_item *rmap_item)
        if (ksm_use_zero_pages && (checksum == zero_checksum)) {
                struct vm_area_struct *vma;
 
-               vma = find_mergeable_vma(rmap_item->mm, rmap_item->address);
+               down_read(&mm->mmap_sem);
+               vma = find_mergeable_vma(mm, rmap_item->address);
                err = try_to_merge_one_page(vma, page,
                                            ZERO_PAGE(rmap_item->address));
+               up_read(&mm->mmap_sem);
                /*
                 * In case of failure, the page was not really empty, so we
                 * need to continue. Otherwise we're done.
index 7a40fa2..f141f0c 100644 (file)
@@ -325,12 +325,12 @@ static int memcg_init_list_lru_node(struct list_lru_node *nlru)
 {
        int size = memcg_nr_cache_ids;
 
-       nlru->memcg_lrus = kmalloc(size * sizeof(void *), GFP_KERNEL);
+       nlru->memcg_lrus = kvmalloc(size * sizeof(void *), GFP_KERNEL);
        if (!nlru->memcg_lrus)
                return -ENOMEM;
 
        if (__memcg_init_list_lru_node(nlru->memcg_lrus, 0, size)) {
-               kfree(nlru->memcg_lrus);
+               kvfree(nlru->memcg_lrus);
                return -ENOMEM;
        }
 
@@ -340,7 +340,7 @@ static int memcg_init_list_lru_node(struct list_lru_node *nlru)
 static void memcg_destroy_list_lru_node(struct list_lru_node *nlru)
 {
        __memcg_destroy_list_lru_node(nlru->memcg_lrus, 0, memcg_nr_cache_ids);
-       kfree(nlru->memcg_lrus);
+       kvfree(nlru->memcg_lrus);
 }
 
 static int memcg_update_list_lru_node(struct list_lru_node *nlru,
@@ -351,12 +351,12 @@ static int memcg_update_list_lru_node(struct list_lru_node *nlru,
        BUG_ON(old_size > new_size);
 
        old = nlru->memcg_lrus;
-       new = kmalloc(new_size * sizeof(void *), GFP_KERNEL);
+       new = kvmalloc(new_size * sizeof(void *), GFP_KERNEL);
        if (!new)
                return -ENOMEM;
 
        if (__memcg_init_list_lru_node(new, old_size, new_size)) {
-               kfree(new);
+               kvfree(new);
                return -ENOMEM;
        }
 
@@ -373,7 +373,7 @@ static int memcg_update_list_lru_node(struct list_lru_node *nlru,
        nlru->memcg_lrus = new;
        spin_unlock_irq(&nlru->lock);
 
-       kfree(old);
+       kvfree(old);
        return 0;
 }
 
index 21261ff..25bade3 100644 (file)
@@ -625,18 +625,26 @@ static int madvise_inject_error(int behavior,
 {
        struct page *page;
        struct zone *zone;
+       unsigned int order;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       for (; start < end; start += PAGE_SIZE <<
-                               compound_order(compound_head(page))) {
+
+       for (; start < end; start += PAGE_SIZE << order) {
                int ret;
 
                ret = get_user_pages_fast(start, 1, 0, &page);
                if (ret != 1)
                        return ret;
 
+               /*
+                * When soft offlining hugepages, after migrating the page
+                * we dissolve it, therefore in the second loop "page" will
+                * no longer be a compound page, and order will be 0.
+                */
+               order = compound_order(compound_head(page));
+
                if (PageHWPoison(page)) {
                        put_page(page);
                        continue;
index 15af3da..d5f3a62 100644 (file)
@@ -1777,6 +1777,10 @@ static void drain_local_stock(struct work_struct *dummy)
        struct memcg_stock_pcp *stock;
        unsigned long flags;
 
+       /*
+        * The only protection from memory hotplug vs. drain_stock races is
+        * that we always operate on local CPU stock here with IRQ disabled
+        */
        local_irq_save(flags);
 
        stock = this_cpu_ptr(&memcg_stock);
@@ -1821,27 +1825,33 @@ static void drain_all_stock(struct mem_cgroup *root_memcg)
        /* If someone's already draining, avoid adding running more workers. */
        if (!mutex_trylock(&percpu_charge_mutex))
                return;
-       /* Notify other cpus that system-wide "drain" is running */
-       get_online_cpus();
+       /*
+        * Notify other cpus that system-wide "drain" is running
+        * We do not care about races with the cpu hotplug because cpu down
+        * as well as workers from this path always operate on the local
+        * per-cpu data. CPU up doesn't touch memcg_stock at all.
+        */
        curcpu = get_cpu();
        for_each_online_cpu(cpu) {
                struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
                struct mem_cgroup *memcg;
 
                memcg = stock->cached;
-               if (!memcg || !stock->nr_pages)
+               if (!memcg || !stock->nr_pages || !css_tryget(&memcg->css))
                        continue;
-               if (!mem_cgroup_is_descendant(memcg, root_memcg))
+               if (!mem_cgroup_is_descendant(memcg, root_memcg)) {
+                       css_put(&memcg->css);
                        continue;
+               }
                if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags)) {
                        if (cpu == curcpu)
                                drain_local_stock(&stock->work);
                        else
                                schedule_work_on(cpu, &stock->work);
                }
+               css_put(&memcg->css);
        }
        put_cpu();
-       put_online_cpus();
        mutex_unlock(&percpu_charge_mutex);
 }
 
@@ -5648,7 +5658,8 @@ static void uncharge_batch(const struct uncharge_gather *ug)
 static void uncharge_page(struct page *page, struct uncharge_gather *ug)
 {
        VM_BUG_ON_PAGE(PageLRU(page), page);
-       VM_BUG_ON_PAGE(!PageHWPoison(page) && page_count(page), page);
+       VM_BUG_ON_PAGE(page_count(page) && !is_zone_device_page(page) &&
+                       !PageHWPoison(page) , page);
 
        if (!page->mem_cgroup)
                return;
index ec4e154..a728bed 100644 (file)
@@ -845,7 +845,7 @@ struct page *_vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
                 * vm_normal_page() so that we do not have to special case all
                 * call site of vm_normal_page().
                 */
-               if (likely(pfn < highest_memmap_pfn)) {
+               if (likely(pfn <= highest_memmap_pfn)) {
                        struct page *page = pfn_to_page(pfn);
 
                        if (is_device_public_page(page)) {
index e882cb6..d4b5f29 100644 (file)
@@ -328,6 +328,7 @@ int __ref __add_pages(int nid, unsigned long phys_start_pfn,
                if (err && (err != -EEXIST))
                        break;
                err = 0;
+               cond_resched();
        }
        vmemmap_populate_print_last();
 out:
@@ -337,7 +338,7 @@ EXPORT_SYMBOL_GPL(__add_pages);
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
 /* find the smallest valid pfn in the range [start_pfn, end_pfn) */
-static int find_smallest_section_pfn(int nid, struct zone *zone,
+static unsigned long find_smallest_section_pfn(int nid, struct zone *zone,
                                     unsigned long start_pfn,
                                     unsigned long end_pfn)
 {
@@ -362,7 +363,7 @@ static int find_smallest_section_pfn(int nid, struct zone *zone,
 }
 
 /* find the biggest valid pfn in the range [start_pfn, end_pfn). */
-static int find_biggest_section_pfn(int nid, struct zone *zone,
+static unsigned long find_biggest_section_pfn(int nid, struct zone *zone,
                                    unsigned long start_pfn,
                                    unsigned long end_pfn)
 {
@@ -550,7 +551,7 @@ static int __remove_section(struct zone *zone, struct mem_section *ms,
                return ret;
 
        scn_nr = __section_nr(ms);
-       start_pfn = section_nr_to_pfn(scn_nr);
+       start_pfn = section_nr_to_pfn((unsigned long)scn_nr);
        __remove_zone(zone, start_pfn);
 
        sparse_remove_one_section(zone, ms, map_offset);
index 99736e0..dee0f75 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/ratelimit.h>
 #include <linux/kthread.h>
 #include <linux/init.h>
+#include <linux/mmu_notifier.h>
 
 #include <asm/tlb.h>
 #include "internal.h"
@@ -495,6 +496,21 @@ static bool __oom_reap_task_mm(struct task_struct *tsk, struct mm_struct *mm)
        }
 
        /*
+        * If the mm has notifiers then we would need to invalidate them around
+        * unmap_page_range and that is risky because notifiers can sleep and
+        * what they do is basically undeterministic.  So let's have a short
+        * sleep to give the oom victim some more time.
+        * TODO: we really want to get rid of this ugly hack and make sure that
+        * notifiers cannot block for unbounded amount of time and add
+        * mmu_notifier_invalidate_range_{start,end} around unmap_page_range
+        */
+       if (mm_has_notifiers(mm)) {
+               up_read(&mm->mmap_sem);
+               schedule_timeout_idle(HZ);
+               goto unlock_oom;
+       }
+
+       /*
         * MMF_OOM_SKIP is set by exit_mmap when the OOM reaper can't
         * work on the mm anymore. The check for MMF_OOM_SKIP must run
         * under mmap_sem for reading because it serializes against the
index c841af8..77e4d3c 100644 (file)
@@ -1190,7 +1190,7 @@ static void __meminit __init_single_pfn(unsigned long pfn, unsigned long zone,
 }
 
 #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
-static void init_reserved_page(unsigned long pfn)
+static void __meminit init_reserved_page(unsigned long pfn)
 {
        pg_data_t *pgdat;
        int nid, zid;
@@ -5367,6 +5367,7 @@ not_early:
 
                        __init_single_page(page, pfn, zone, nid);
                        set_pageblock_migratetype(page, MIGRATE_MOVABLE);
+                       cond_resched();
                } else {
                        __init_single_pfn(pfn, zone, nid);
                }
index 6142484..7a58460 100644 (file)
@@ -73,7 +73,7 @@ static void chunk_map_stats(struct seq_file *m, struct pcpu_chunk *chunk,
                     last_alloc + 1 : 0;
 
        as_len = 0;
-       start = chunk->start_offset;
+       start = chunk->start_offset / PCPU_MIN_ALLOC_SIZE;
 
        /*
         * If a bit is set in the allocation map, the bound_map identifies
index 59d44d6..aa121ce 100644 (file)
@@ -353,6 +353,8 @@ static void pcpu_next_md_free_region(struct pcpu_chunk *chunk, int *bit_off,
                                        block->contig_hint_start);
                        return;
                }
+               /* reset to satisfy the second predicate above */
+               block_off = 0;
 
                *bits = block->right_free;
                *bit_off = (i + 1) * PCPU_BITMAP_BLOCK_BITS - block->right_free;
@@ -407,6 +409,8 @@ static void pcpu_next_fit_region(struct pcpu_chunk *chunk, int alloc_bits,
                        *bit_off = pcpu_block_off_to_off(i, block->first_free);
                        return;
                }
+               /* reset to satisfy the second predicate above */
+               block_off = 0;
 
                *bit_off = ALIGN(PCPU_BITMAP_BLOCK_BITS - block->right_free,
                                 align);
index 6bb4deb..d908c87 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/uaccess.h>
 #include <asm/sections.h>
 
-const int rodata_test_data = 0xC3;
+static const int rodata_test_data = 0xC3;
 
 void rodata_test(void)
 {
index 904a83b..8016459 100644 (file)
@@ -165,9 +165,9 @@ static int init_memcg_params(struct kmem_cache *s,
        if (!memcg_nr_cache_ids)
                return 0;
 
-       arr = kzalloc(sizeof(struct memcg_cache_array) +
-                     memcg_nr_cache_ids * sizeof(void *),
-                     GFP_KERNEL);
+       arr = kvzalloc(sizeof(struct memcg_cache_array) +
+                      memcg_nr_cache_ids * sizeof(void *),
+                      GFP_KERNEL);
        if (!arr)
                return -ENOMEM;
 
@@ -178,15 +178,23 @@ static int init_memcg_params(struct kmem_cache *s,
 static void destroy_memcg_params(struct kmem_cache *s)
 {
        if (is_root_cache(s))
-               kfree(rcu_access_pointer(s->memcg_params.memcg_caches));
+               kvfree(rcu_access_pointer(s->memcg_params.memcg_caches));
+}
+
+static void free_memcg_params(struct rcu_head *rcu)
+{
+       struct memcg_cache_array *old;
+
+       old = container_of(rcu, struct memcg_cache_array, rcu);
+       kvfree(old);
 }
 
 static int update_memcg_params(struct kmem_cache *s, int new_array_size)
 {
        struct memcg_cache_array *old, *new;
 
-       new = kzalloc(sizeof(struct memcg_cache_array) +
-                     new_array_size * sizeof(void *), GFP_KERNEL);
+       new = kvzalloc(sizeof(struct memcg_cache_array) +
+                      new_array_size * sizeof(void *), GFP_KERNEL);
        if (!new)
                return -ENOMEM;
 
@@ -198,7 +206,7 @@ static int update_memcg_params(struct kmem_cache *s, int new_array_size)
 
        rcu_assign_pointer(s->memcg_params.memcg_caches, new);
        if (old)
-               kfree_rcu(old, rcu);
+               call_rcu(&old->rcu, free_memcg_params);
        return 0;
 }
 
index 9295ae9..a77d68f 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -575,7 +575,7 @@ static void lru_lazyfree_fn(struct page *page, struct lruvec *lruvec,
                            void *arg)
 {
        if (PageLRU(page) && PageAnon(page) && PageSwapBacked(page) &&
-           !PageUnevictable(page)) {
+           !PageSwapCache(page) && !PageUnevictable(page)) {
                bool active = PageActive(page);
 
                del_page_from_lru_list(page, lruvec,
@@ -665,7 +665,7 @@ void deactivate_file_page(struct page *page)
 void mark_page_lazyfree(struct page *page)
 {
        if (PageLRU(page) && PageAnon(page) && PageSwapBacked(page) &&
-           !PageUnevictable(page)) {
+           !PageSwapCache(page) && !PageUnevictable(page)) {
                struct pagevec *pvec = &get_cpu_var(lru_lazyfree_pvecs);
 
                get_page(page);
index 71ce2d1..ed91091 100644 (file)
@@ -242,6 +242,17 @@ int add_to_swap(struct page *page)
                 * clear SWAP_HAS_CACHE flag.
                 */
                goto fail;
+       /*
+        * Normally the page will be dirtied in unmap because its pte should be
+        * dirty. A special case is MADV_FREE page. The page'e pte could have
+        * dirty bit cleared but the page's SwapBacked bit is still set because
+        * clearing the dirty bit and SwapBacked bit has no lock protected. For
+        * such page, unmap will not set dirty bit for it, so page reclaim will
+        * not write the page out. This can cause data corruption when the page
+        * is swap in later. Always setting the dirty bit for the page solves
+        * the problem.
+        */
+       set_page_dirty(page);
 
        return 1;
 
index 486550d..b2ba2ba 100644 (file)
@@ -250,6 +250,7 @@ static void __release_z3fold_page(struct z3fold_header *zhdr, bool locked)
 
        WARN_ON(!list_empty(&zhdr->buddy));
        set_bit(PAGE_STALE, &page->private);
+       clear_bit(NEEDS_COMPACTING, &page->private);
        spin_lock(&pool->lock);
        if (!list_empty(&page->lru))
                list_del(&page->lru);
@@ -303,7 +304,6 @@ static void free_pages_work(struct work_struct *w)
                list_del(&zhdr->buddy);
                if (WARN_ON(!test_bit(PAGE_STALE, &page->private)))
                        continue;
-               clear_bit(NEEDS_COMPACTING, &page->private);
                spin_unlock(&pool->stale_lock);
                cancel_work_sync(&zhdr->work);
                free_z3fold_page(page);
@@ -624,10 +624,8 @@ lookup:
         * stale pages list. cancel_work_sync() can sleep so we must make
         * sure it won't be called in case we're in atomic context.
         */
-       if (zhdr && (can_sleep || !work_pending(&zhdr->work) ||
-           !unlikely(work_busy(&zhdr->work)))) {
+       if (zhdr && (can_sleep || !work_pending(&zhdr->work))) {
                list_del(&zhdr->buddy);
-               clear_bit(NEEDS_COMPACTING, &page->private);
                spin_unlock(&pool->stale_lock);
                if (can_sleep)
                        cancel_work_sync(&zhdr->work);
@@ -875,16 +873,18 @@ static int z3fold_reclaim_page(struct z3fold_pool *pool, unsigned int retries)
                                goto next;
                }
 next:
+               spin_lock(&pool->lock);
                if (test_bit(PAGE_HEADLESS, &page->private)) {
                        if (ret == 0) {
+                               spin_unlock(&pool->lock);
                                free_z3fold_page(page);
                                return 0;
                        }
                } else if (kref_put(&zhdr->refcount, release_z3fold_page)) {
                        atomic64_dec(&pool->pages_nr);
+                       spin_unlock(&pool->lock);
                        return 0;
                }
-               spin_lock(&pool->lock);
 
                /*
                 * Add to the beginning of LRU.
index e2ed698..0bc31de 100644 (file)
@@ -21,6 +21,12 @@ bool vlan_do_receive(struct sk_buff **skbp)
        if (unlikely(!skb))
                return false;
 
+       if (unlikely(!(vlan_dev->flags & IFF_UP))) {
+               kfree_skb(skb);
+               *skbp = NULL;
+               return false;
+       }
+
        skb->dev = vlan_dev;
        if (unlikely(skb->pkt_type == PACKET_OTHERHOST)) {
                /* Our lower layer thinks this is not local, let's make sure.
index 82edad5..74b8c91 100644 (file)
@@ -989,10 +989,14 @@ static bool __sk_filter_charge(struct sock *sk, struct sk_filter *fp)
 
 bool sk_filter_charge(struct sock *sk, struct sk_filter *fp)
 {
-       bool ret = __sk_filter_charge(sk, fp);
-       if (ret)
-               refcount_inc(&fp->refcnt);
-       return ret;
+       if (!refcount_inc_not_zero(&fp->refcnt))
+               return false;
+
+       if (!__sk_filter_charge(sk, fp)) {
+               sk_filter_release(fp);
+               return false;
+       }
+       return true;
 }
 
 static struct bpf_prog *bpf_migrate_filter(struct bpf_prog *fp)
index a78fd61..d4bcdcc 100644 (file)
@@ -3854,6 +3854,9 @@ static int rtnl_fill_statsinfo(struct sk_buff *skb, struct net_device *dev,
                return -EMSGSIZE;
 
        ifsm = nlmsg_data(nlh);
+       ifsm->family = PF_UNSPEC;
+       ifsm->pad1 = 0;
+       ifsm->pad2 = 0;
        ifsm->ifindex = dev->ifindex;
        ifsm->filter_mask = filter_mask;
 
index 9b7b6bb..23953b7 100644 (file)
@@ -1654,6 +1654,8 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
 
                sock_copy(newsk, sk);
 
+               newsk->sk_prot_creator = sk->sk_prot;
+
                /* SANITY */
                if (likely(newsk->sk_net_refcnt))
                        get_net(sock_net(newsk));
@@ -1682,13 +1684,16 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
 
                sock_reset_flag(newsk, SOCK_DONE);
 
-               filter = rcu_dereference_protected(newsk->sk_filter, 1);
+               rcu_read_lock();
+               filter = rcu_dereference(sk->sk_filter);
                if (filter != NULL)
                        /* though it's an empty new sock, the charging may fail
                         * if sysctl_optmem_max was changed between creation of
                         * original socket and cloning
                         */
                        is_charged = sk_filter_charge(newsk, filter);
+               RCU_INIT_POINTER(newsk->sk_filter, filter);
+               rcu_read_unlock();
 
                if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk, sk))) {
                        /* We need to make sure that we don't uncharge the new
index 2afa995..865e29e 100644 (file)
@@ -1301,28 +1301,33 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
        p->old_duplex = -1;
 
        port->netdev = slave_dev;
-       ret = register_netdev(slave_dev);
-       if (ret) {
-               netdev_err(master, "error %d registering interface %s\n",
-                          ret, slave_dev->name);
-               port->netdev = NULL;
-               free_percpu(p->stats64);
-               free_netdev(slave_dev);
-               return ret;
-       }
 
        netif_carrier_off(slave_dev);
 
        ret = dsa_slave_phy_setup(p, slave_dev);
        if (ret) {
                netdev_err(master, "error %d setting up slave phy\n", ret);
-               unregister_netdev(slave_dev);
-               free_percpu(p->stats64);
-               free_netdev(slave_dev);
-               return ret;
+               goto out_free;
+       }
+
+       ret = register_netdev(slave_dev);
+       if (ret) {
+               netdev_err(master, "error %d registering interface %s\n",
+                          ret, slave_dev->name);
+               goto out_phy;
        }
 
        return 0;
+
+out_phy:
+       phy_disconnect(p->phy);
+       if (of_phy_is_fixed_link(p->dp->dn))
+               of_phy_deregister_fixed_link(p->dp->dn);
+out_free:
+       free_percpu(p->stats64);
+       free_netdev(slave_dev);
+       port->netdev = NULL;
+       return ret;
 }
 
 void dsa_slave_destroy(struct net_device *slave_dev)
index e7eb590..b20c8ac 100644 (file)
@@ -128,9 +128,9 @@ static struct inet_peer *lookup(const struct inetpeer_addr *daddr,
                        break;
                }
                if (cmp == -1)
-                       pp = &(*pp)->rb_left;
+                       pp = &next->rb_left;
                else
-                       pp = &(*pp)->rb_right;
+                       pp = &next->rb_right;
        }
        *parent_p = parent;
        *pp_p = pp;
index 0162fb9..467e44d 100644 (file)
@@ -259,7 +259,6 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
        struct ip_tunnel *tunnel;
        struct erspanhdr *ershdr;
        const struct iphdr *iph;
-       __be32 session_id;
        __be32 index;
        int len;
 
@@ -275,8 +274,7 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
        /* The original GRE header does not have key field,
         * Use ERSPAN 10-bit session ID as key.
         */
-       session_id = cpu_to_be32(ntohs(ershdr->session_id));
-       tpi->key = session_id;
+       tpi->key = cpu_to_be32(ntohs(ershdr->session_id) & ID_MASK);
        index = ershdr->md.index;
        tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
                                  tpi->flags | TUNNEL_KEY,
@@ -733,7 +731,7 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
        if (skb_cow_head(skb, dev->needed_headroom))
                goto free_skb;
 
-       if (skb->len > dev->mtu) {
+       if (skb->len - dev->hard_header_len > dev->mtu) {
                pskb_trim(skb, dev->mtu);
                truncate = true;
        }
@@ -1223,6 +1221,7 @@ static int gre_tap_init(struct net_device *dev)
 {
        __gre_tunnel_init(dev);
        dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+       netif_keep_dst(dev);
 
        return ip_tunnel_init(dev);
 }
@@ -1246,13 +1245,16 @@ static int erspan_tunnel_init(struct net_device *dev)
 
        tunnel->tun_hlen = 8;
        tunnel->parms.iph.protocol = IPPROTO_GRE;
-       t_hlen = tunnel->hlen + sizeof(struct iphdr) + sizeof(struct erspanhdr);
+       tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen +
+                      sizeof(struct erspanhdr);
+       t_hlen = tunnel->hlen + sizeof(struct iphdr);
 
        dev->needed_headroom = LL_MAX_HEADER + t_hlen + 4;
        dev->mtu = ETH_DATA_LEN - t_hlen - 4;
        dev->features           |= GRE_FEATURES;
        dev->hw_features        |= GRE_FEATURES;
        dev->priv_flags         |= IFF_LIVE_ADDR_CHANGE;
+       netif_keep_dst(dev);
 
        return ip_tunnel_init(dev);
 }
index fa2dc8f..57fc13c 100644 (file)
@@ -311,9 +311,10 @@ drop:
 static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
        const struct iphdr *iph = ip_hdr(skb);
-       struct rtable *rt;
+       int (*edemux)(struct sk_buff *skb);
        struct net_device *dev = skb->dev;
-       void (*edemux)(struct sk_buff *skb);
+       struct rtable *rt;
+       int err;
 
        /* if ingress device is enslaved to an L3 master device pass the
         * skb to its handler for processing
@@ -331,7 +332,9 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 
                ipprot = rcu_dereference(inet_protos[protocol]);
                if (ipprot && (edemux = READ_ONCE(ipprot->early_demux))) {
-                       edemux(skb);
+                       err = edemux(skb);
+                       if (unlikely(err))
+                               goto drop_error;
                        /* must reload iph, skb->head might have changed */
                        iph = ip_hdr(skb);
                }
@@ -342,13 +345,10 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
         *      how the packet travels inside Linux networking.
         */
        if (!skb_valid_dst(skb)) {
-               int err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
-                                              iph->tos, dev);
-               if (unlikely(err)) {
-                       if (err == -EXDEV)
-                               __NET_INC_STATS(net, LINUX_MIB_IPRPFILTER);
-                       goto drop;
-               }
+               err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
+                                          iph->tos, dev);
+               if (unlikely(err))
+                       goto drop_error;
        }
 
 #ifdef CONFIG_IP_ROUTE_CLASSID
@@ -399,6 +399,11 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 drop:
        kfree_skb(skb);
        return NET_RX_DROP;
+
+drop_error:
+       if (err == -EXDEV)
+               __NET_INC_STATS(net, LINUX_MIB_IPRPFILTER);
+       goto drop;
 }
 
 /*
index 5ed63d2..89453cf 100644 (file)
@@ -168,6 +168,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
        struct ip_tunnel_parm *parms = &tunnel->parms;
        struct dst_entry *dst = skb_dst(skb);
        struct net_device *tdev;        /* Device to other host */
+       int pkt_len = skb->len;
        int err;
        int mtu;
 
@@ -229,7 +230,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
 
        err = dst_output(tunnel->net, skb->sk, skb);
        if (net_xmit_eval(err) == 0)
-               err = skb->len;
+               err = pkt_len;
        iptunnel_xmit_stats(dev, err);
        return NETDEV_TX_OK;
 
index 94d4cd2..ac6fde5 100644 (file)
@@ -1520,43 +1520,56 @@ struct rtable *rt_dst_alloc(struct net_device *dev,
 EXPORT_SYMBOL(rt_dst_alloc);
 
 /* called in rcu_read_lock() section */
-static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
-                               u8 tos, struct net_device *dev, int our)
+int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+                         u8 tos, struct net_device *dev,
+                         struct in_device *in_dev, u32 *itag)
 {
-       struct rtable *rth;
-       struct in_device *in_dev = __in_dev_get_rcu(dev);
-       unsigned int flags = RTCF_MULTICAST;
-       u32 itag = 0;
        int err;
 
        /* Primary sanity checks. */
-
        if (!in_dev)
                return -EINVAL;
 
        if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr) ||
            skb->protocol != htons(ETH_P_IP))
-               goto e_inval;
+               return -EINVAL;
 
        if (ipv4_is_loopback(saddr) && !IN_DEV_ROUTE_LOCALNET(in_dev))
-               goto e_inval;
+               return -EINVAL;
 
        if (ipv4_is_zeronet(saddr)) {
                if (!ipv4_is_local_multicast(daddr))
-                       goto e_inval;
+                       return -EINVAL;
        } else {
                err = fib_validate_source(skb, saddr, 0, tos, 0, dev,
-                                         in_dev, &itag);
+                                         in_dev, itag);
                if (err < 0)
-                       goto e_err;
+                       return err;
        }
+       return 0;
+}
+
+/* called in rcu_read_lock() section */
+static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+                            u8 tos, struct net_device *dev, int our)
+{
+       struct in_device *in_dev = __in_dev_get_rcu(dev);
+       unsigned int flags = RTCF_MULTICAST;
+       struct rtable *rth;
+       u32 itag = 0;
+       int err;
+
+       err = ip_mc_validate_source(skb, daddr, saddr, tos, dev, in_dev, &itag);
+       if (err)
+               return err;
+
        if (our)
                flags |= RTCF_LOCAL;
 
        rth = rt_dst_alloc(dev_net(dev)->loopback_dev, flags, RTN_MULTICAST,
                           IN_DEV_CONF_GET(in_dev, NOPOLICY), false, false);
        if (!rth)
-               goto e_nobufs;
+               return -ENOBUFS;
 
 #ifdef CONFIG_IP_ROUTE_CLASSID
        rth->dst.tclassid = itag;
@@ -1572,13 +1585,6 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 
        skb_dst_set(skb, &rth->dst);
        return 0;
-
-e_nobufs:
-       return -ENOBUFS;
-e_inval:
-       return -EINVAL;
-e_err:
-       return err;
 }
 
 
index d9416b5..85164d4 100644 (file)
@@ -1503,23 +1503,23 @@ csum_err:
 }
 EXPORT_SYMBOL(tcp_v4_do_rcv);
 
-void tcp_v4_early_demux(struct sk_buff *skb)
+int tcp_v4_early_demux(struct sk_buff *skb)
 {
        const struct iphdr *iph;
        const struct tcphdr *th;
        struct sock *sk;
 
        if (skb->pkt_type != PACKET_HOST)
-               return;
+               return 0;
 
        if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct tcphdr)))
-               return;
+               return 0;
 
        iph = ip_hdr(skb);
        th = tcp_hdr(skb);
 
        if (th->doff < sizeof(struct tcphdr) / 4)
-               return;
+               return 0;
 
        sk = __inet_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
                                       iph->saddr, th->source,
@@ -1538,6 +1538,7 @@ void tcp_v4_early_demux(struct sk_buff *skb)
                                skb_dst_set_noref(skb, dst);
                }
        }
+       return 0;
 }
 
 bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
index ef29df8..5676237 100644 (file)
@@ -2221,9 +2221,10 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net,
        return NULL;
 }
 
-void udp_v4_early_demux(struct sk_buff *skb)
+int udp_v4_early_demux(struct sk_buff *skb)
 {
        struct net *net = dev_net(skb->dev);
+       struct in_device *in_dev = NULL;
        const struct iphdr *iph;
        const struct udphdr *uh;
        struct sock *sk = NULL;
@@ -2234,24 +2235,24 @@ void udp_v4_early_demux(struct sk_buff *skb)
 
        /* validate the packet */
        if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr)))
-               return;
+               return 0;
 
        iph = ip_hdr(skb);
        uh = udp_hdr(skb);
 
        if (skb->pkt_type == PACKET_BROADCAST ||
            skb->pkt_type == PACKET_MULTICAST) {
-               struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
+               in_dev = __in_dev_get_rcu(skb->dev);
 
                if (!in_dev)
-                       return;
+                       return 0;
 
                /* we are supposed to accept bcast packets */
                if (skb->pkt_type == PACKET_MULTICAST) {
                        ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr,
                                               iph->protocol);
                        if (!ours)
-                               return;
+                               return 0;
                }
 
                sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
@@ -2263,7 +2264,7 @@ void udp_v4_early_demux(struct sk_buff *skb)
        }
 
        if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt))
-               return;
+               return 0;
 
        skb->sk = sk;
        skb->destructor = sock_efree;
@@ -2272,12 +2273,23 @@ void udp_v4_early_demux(struct sk_buff *skb)
        if (dst)
                dst = dst_check(dst, 0);
        if (dst) {
+               u32 itag = 0;
+
                /* set noref for now.
                 * any place which wants to hold dst has to call
                 * dst_hold_safe()
                 */
                skb_dst_set_noref(skb, dst);
+
+               /* for unconnected multicast sockets we need to validate
+                * the source on each packet
+                */
+               if (!inet_sk(sk)->inet_daddr && in_dev)
+                       return ip_mc_validate_source(skb, iph->daddr,
+                                                    iph->saddr, iph->tos,
+                                                    skb->dev, in_dev, &itag);
        }
+       return 0;
 }
 
 int udp_rcv(struct sk_buff *skb)
index 20f66f4..1602b49 100644 (file)
@@ -1311,6 +1311,7 @@ static void ip6gre_tap_setup(struct net_device *dev)
        dev->features |= NETIF_F_NETNS_LOCAL;
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
        dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+       netif_keep_dst(dev);
 }
 
 static bool ip6gre_netlink_encap_parms(struct nlattr *data[],
index f2f21c2..a1c2444 100644 (file)
@@ -1043,6 +1043,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
        struct dst_entry *dst = NULL, *ndst = NULL;
        struct net_device *tdev;
        int mtu;
+       unsigned int eth_hlen = t->dev->type == ARPHRD_ETHER ? ETH_HLEN : 0;
        unsigned int psh_hlen = sizeof(struct ipv6hdr) + t->encap_hlen;
        unsigned int max_headroom = psh_hlen;
        bool use_cache = false;
@@ -1124,7 +1125,7 @@ route_lookup:
                                     t->parms.name);
                goto tx_err_dst_release;
        }
-       mtu = dst_mtu(dst) - psh_hlen - t->tun_hlen;
+       mtu = dst_mtu(dst) - eth_hlen - psh_hlen - t->tun_hlen;
        if (encap_limit >= 0) {
                max_headroom += 8;
                mtu -= 8;
@@ -1133,7 +1134,7 @@ route_lookup:
                mtu = IPV6_MIN_MTU;
        if (skb_dst(skb) && !t->parms.collect_md)
                skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
-       if (skb->len - t->tun_hlen > mtu && !skb_is_gso(skb)) {
+       if (skb->len - t->tun_hlen - eth_hlen > mtu && !skb_is_gso(skb)) {
                *pmtu = mtu;
                err = -EMSGSIZE;
                goto tx_err_dst_release;
index 79444a4..bcdc2d5 100644 (file)
@@ -445,6 +445,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
        struct dst_entry *dst = skb_dst(skb);
        struct net_device *tdev;
        struct xfrm_state *x;
+       int pkt_len = skb->len;
        int err = -1;
        int mtu;
 
@@ -502,7 +503,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
                struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
 
                u64_stats_update_begin(&tstats->syncp);
-               tstats->tx_bytes += skb->len;
+               tstats->tx_bytes += pkt_len;
                tstats->tx_packets++;
                u64_stats_update_end(&tstats->syncp);
        } else {
index ee485df..02d6110 100644 (file)
@@ -1314,6 +1314,9 @@ again:
 
                        hlist_del_init(&session->hlist);
 
+                       if (test_and_set_bit(0, &session->dead))
+                               goto again;
+
                        if (session->ref != NULL)
                                (*session->ref)(session);
 
@@ -1685,14 +1688,12 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create);
 
 /* This function is used by the netlink TUNNEL_DELETE command.
  */
-int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
+void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
 {
-       l2tp_tunnel_inc_refcount(tunnel);
-       if (false == queue_work(l2tp_wq, &tunnel->del_work)) {
-               l2tp_tunnel_dec_refcount(tunnel);
-               return 1;
+       if (!test_and_set_bit(0, &tunnel->dead)) {
+               l2tp_tunnel_inc_refcount(tunnel);
+               queue_work(l2tp_wq, &tunnel->del_work);
        }
-       return 0;
 }
 EXPORT_SYMBOL_GPL(l2tp_tunnel_delete);
 
@@ -1750,6 +1751,9 @@ EXPORT_SYMBOL_GPL(__l2tp_session_unhash);
  */
 int l2tp_session_delete(struct l2tp_session *session)
 {
+       if (test_and_set_bit(0, &session->dead))
+               return 0;
+
        if (session->ref)
                (*session->ref)(session);
        __l2tp_session_unhash(session);
index a305e0c..67c79d9 100644 (file)
@@ -76,6 +76,7 @@ struct l2tp_session_cfg {
 struct l2tp_session {
        int                     magic;          /* should be
                                                 * L2TP_SESSION_MAGIC */
+       long                    dead;
 
        struct l2tp_tunnel      *tunnel;        /* back pointer to tunnel
                                                 * context */
@@ -160,6 +161,9 @@ struct l2tp_tunnel_cfg {
 
 struct l2tp_tunnel {
        int                     magic;          /* Should be L2TP_TUNNEL_MAGIC */
+
+       unsigned long           dead;
+
        struct rcu_head rcu;
        rwlock_t                hlist_lock;     /* protect session_hlist */
        bool                    acpt_newsess;   /* Indicates whether this
@@ -254,7 +258,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id,
                       u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg,
                       struct l2tp_tunnel **tunnelp);
 void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel);
-int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel);
+void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel);
 struct l2tp_session *l2tp_session_create(int priv_size,
                                         struct l2tp_tunnel *tunnel,
                                         u32 session_id, u32 peer_session_id,
index 87da9ef..014a7bc 100644 (file)
@@ -44,7 +44,6 @@ struct l2tp_eth {
        struct net_device       *dev;
        struct sock             *tunnel_sock;
        struct l2tp_session     *session;
-       struct list_head        list;
        atomic_long_t           tx_bytes;
        atomic_long_t           tx_packets;
        atomic_long_t           tx_dropped;
@@ -58,17 +57,6 @@ struct l2tp_eth_sess {
        struct net_device       *dev;
 };
 
-/* per-net private data for this module */
-static unsigned int l2tp_eth_net_id;
-struct l2tp_eth_net {
-       struct list_head l2tp_eth_dev_list;
-       spinlock_t l2tp_eth_lock;
-};
-
-static inline struct l2tp_eth_net *l2tp_eth_pernet(struct net *net)
-{
-       return net_generic(net, l2tp_eth_net_id);
-}
 
 static int l2tp_eth_dev_init(struct net_device *dev)
 {
@@ -84,12 +72,6 @@ static int l2tp_eth_dev_init(struct net_device *dev)
 
 static void l2tp_eth_dev_uninit(struct net_device *dev)
 {
-       struct l2tp_eth *priv = netdev_priv(dev);
-       struct l2tp_eth_net *pn = l2tp_eth_pernet(dev_net(dev));
-
-       spin_lock(&pn->l2tp_eth_lock);
-       list_del_init(&priv->list);
-       spin_unlock(&pn->l2tp_eth_lock);
        dev_put(dev);
 }
 
@@ -273,7 +255,6 @@ static int l2tp_eth_create(struct net *net, struct l2tp_tunnel *tunnel,
        struct l2tp_eth *priv;
        struct l2tp_eth_sess *spriv;
        int rc;
-       struct l2tp_eth_net *pn;
 
        if (cfg->ifname) {
                strlcpy(name, cfg->ifname, IFNAMSIZ);
@@ -305,7 +286,6 @@ static int l2tp_eth_create(struct net *net, struct l2tp_tunnel *tunnel,
        priv = netdev_priv(dev);
        priv->dev = dev;
        priv->session = session;
-       INIT_LIST_HEAD(&priv->list);
 
        priv->tunnel_sock = tunnel->sock;
        session->recv_skb = l2tp_eth_dev_recv;
@@ -326,10 +306,6 @@ static int l2tp_eth_create(struct net *net, struct l2tp_tunnel *tunnel,
        strlcpy(session->ifname, dev->name, IFNAMSIZ);
 
        dev_hold(dev);
-       pn = l2tp_eth_pernet(dev_net(dev));
-       spin_lock(&pn->l2tp_eth_lock);
-       list_add(&priv->list, &pn->l2tp_eth_dev_list);
-       spin_unlock(&pn->l2tp_eth_lock);
 
        return 0;
 
@@ -342,22 +318,6 @@ out:
        return rc;
 }
 
-static __net_init int l2tp_eth_init_net(struct net *net)
-{
-       struct l2tp_eth_net *pn = net_generic(net, l2tp_eth_net_id);
-
-       INIT_LIST_HEAD(&pn->l2tp_eth_dev_list);
-       spin_lock_init(&pn->l2tp_eth_lock);
-
-       return 0;
-}
-
-static struct pernet_operations l2tp_eth_net_ops = {
-       .init = l2tp_eth_init_net,
-       .id   = &l2tp_eth_net_id,
-       .size = sizeof(struct l2tp_eth_net),
-};
-
 
 static const struct l2tp_nl_cmd_ops l2tp_eth_nl_cmd_ops = {
        .session_create = l2tp_eth_create,
@@ -371,25 +331,18 @@ static int __init l2tp_eth_init(void)
 
        err = l2tp_nl_register_ops(L2TP_PWTYPE_ETH, &l2tp_eth_nl_cmd_ops);
        if (err)
-               goto out;
-
-       err = register_pernet_device(&l2tp_eth_net_ops);
-       if (err)
-               goto out_unreg;
+               goto err;
 
        pr_info("L2TP ethernet pseudowire support (L2TPv3)\n");
 
        return 0;
 
-out_unreg:
-       l2tp_nl_unregister_ops(L2TP_PWTYPE_ETH);
-out:
+err:
        return err;
 }
 
 static void __exit l2tp_eth_exit(void)
 {
-       unregister_pernet_device(&l2tp_eth_net_ops);
        l2tp_nl_unregister_ops(L2TP_PWTYPE_ETH);
 }
 
index 50e3ee9..bc6e8bf 100644 (file)
@@ -437,11 +437,11 @@ static void pppol2tp_session_close(struct l2tp_session *session)
 
        BUG_ON(session->magic != L2TP_SESSION_MAGIC);
 
-       if (sock) {
+       if (sock)
                inet_shutdown(sock, SEND_SHUTDOWN);
-               /* Don't let the session go away before our socket does */
-               l2tp_session_inc_refcount(session);
-       }
+
+       /* Don't let the session go away before our socket does */
+       l2tp_session_inc_refcount(session);
 }
 
 /* Really kill the session socket. (Called from sock_put() if
index 3278077..94c11cf 100644 (file)
@@ -2270,10 +2270,13 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 
        mutex_unlock(nlk->cb_mutex);
 
+       ret = 0;
        if (cb->start)
-               cb->start(cb);
+               ret = cb->start(cb);
+
+       if (!ret)
+               ret = netlink_dump(sk);
 
-       ret = netlink_dump(sk);
        sock_put(sk);
 
        if (ret)
index d288f52..bec01a3 100644 (file)
@@ -2840,6 +2840,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
        struct virtio_net_hdr vnet_hdr = { 0 };
        int offset = 0;
        struct packet_sock *po = pkt_sk(sk);
+       bool has_vnet_hdr = false;
        int hlen, tlen, linear;
        int extra_len = 0;
 
@@ -2883,6 +2884,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
                err = packet_snd_vnet_parse(msg, &len, &vnet_hdr);
                if (err)
                        goto out_unlock;
+               has_vnet_hdr = true;
        }
 
        if (unlikely(sock_flag(sk, SOCK_NOFCS))) {
@@ -2941,7 +2943,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
        skb->priority = sk->sk_priority;
        skb->mark = sockc.mark;
 
-       if (po->has_vnet_hdr) {
+       if (has_vnet_hdr) {
                err = virtio_net_hdr_to_skb(skb, &vnet_hdr, vio_le());
                if (err)
                        goto out_free;
@@ -3069,13 +3071,15 @@ static int packet_do_bind(struct sock *sk, const char *name, int ifindex,
        int ret = 0;
        bool unlisted = false;
 
-       if (po->fanout)
-               return -EINVAL;
-
        lock_sock(sk);
        spin_lock(&po->bind_lock);
        rcu_read_lock();
 
+       if (po->fanout) {
+               ret = -EINVAL;
+               goto out_unlock;
+       }
+
        if (name) {
                dev = dev_get_by_name_rcu(sock_net(sk), name);
                if (!dev) {
index 22ed01a..a72a7d9 100644 (file)
@@ -463,6 +463,7 @@ static void sctp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
                .r = r,
                .net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN),
        };
+       int pos = cb->args[2];
 
        /* eps hashtable dumps
         * args:
@@ -493,7 +494,8 @@ skip:
                goto done;
 
        sctp_for_each_transport(sctp_sock_filter, sctp_sock_dump,
-                               net, (int *)&cb->args[2], &commp);
+                               net, &pos, &commp);
+       cb->args[2] = pos;
 
 done:
        cb->args[1] = cb->args[4];
index 6ef379f..121e59a 100644 (file)
@@ -551,7 +551,7 @@ bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, int *err)
                return false;
        if (msg_errcode(msg))
                return false;
-       *err = -TIPC_ERR_NO_NAME;
+       *err = TIPC_ERR_NO_NAME;
        if (skb_linearize(skb))
                return false;
        msg = buf_msg(skb);
index dd2c262..8b80bac 100755 (executable)
@@ -6390,7 +6390,7 @@ sub process {
                exit(0);
        }
 
-       if (!$is_patch && $file !~ /cover-letter\.patch$/) {
+       if (!$is_patch && $filename !~ /cover-letter\.patch$/) {
                ERROR("NOT_UNIFIED_DIFF",
                      "Does not appear to be a unified-diff format patch\n");
        }
index 400ef35..aa0cc49 100644 (file)
@@ -53,6 +53,7 @@ acumulator||accumulator
 adapater||adapter
 addional||additional
 additionaly||additionally
+additonal||additional
 addres||address
 adddress||address
 addreses||addresses
@@ -67,6 +68,8 @@ adviced||advised
 afecting||affecting
 againt||against
 agaist||against
+aggreataon||aggregation
+aggreation||aggregation
 albumns||albums
 alegorical||allegorical
 algined||aligned
@@ -80,6 +83,8 @@ aligment||alignment
 alignement||alignment
 allign||align
 alligned||aligned
+alllocate||allocate
+alloated||allocated
 allocatote||allocate
 allocatrd||allocated
 allocte||allocate
@@ -171,6 +176,7 @@ availale||available
 availavility||availability
 availble||available
 availiable||available
+availible||available
 avalable||available
 avaliable||available
 aysnc||async
@@ -203,6 +209,7 @@ broadcat||broadcast
 cacluated||calculated
 caculation||calculation
 calender||calendar
+calescing||coalescing
 calle||called
 callibration||calibration
 calucate||calculate
@@ -210,6 +217,7 @@ calulate||calculate
 cancelation||cancellation
 cancle||cancel
 capabilites||capabilities
+capabilty||capability
 capabitilies||capabilities
 capatibilities||capabilities
 capapbilities||capabilities
@@ -302,6 +310,7 @@ containts||contains
 contaisn||contains
 contant||contact
 contence||contents
+continious||continuous
 continous||continuous
 continously||continuously
 continueing||continuing
@@ -393,6 +402,7 @@ differrence||difference
 diffrent||different
 diffrentiate||differentiate
 difinition||definition
+dimesions||dimensions
 diplay||display
 direectly||directly
 disassocation||disassociation
@@ -449,6 +459,7 @@ equiped||equipped
 equivelant||equivalent
 equivilant||equivalent
 eror||error
+errorr||error
 estbalishment||establishment
 etsablishment||establishment
 etsbalishment||establishment
@@ -481,6 +492,7 @@ failied||failed
 faillure||failure
 failue||failure
 failuer||failure
+failng||failing
 faireness||fairness
 falied||failed
 faliure||failure
@@ -493,6 +505,7 @@ fetaure||feature
 fetaures||features
 fileystem||filesystem
 fimware||firmware
+firware||firmware
 finanize||finalize
 findn||find
 finilizes||finalizes
@@ -502,6 +515,7 @@ folloing||following
 followign||following
 followings||following
 follwing||following
+fonud||found
 forseeable||foreseeable
 forse||force
 fortan||fortran
@@ -532,6 +546,7 @@ grabing||grabbing
 grahical||graphical
 grahpical||graphical
 grapic||graphic
+grranted||granted
 guage||gauge
 guarenteed||guaranteed
 guarentee||guarantee
@@ -543,6 +558,7 @@ happend||happened
 harware||hardware
 heirarchically||hierarchically
 helpfull||helpful
+hybernate||hibernate
 hierachy||hierarchy
 hierarchie||hierarchy
 howver||however
@@ -565,16 +581,19 @@ implemenation||implementation
 implementaiton||implementation
 implementated||implemented
 implemention||implementation
+implementd||implemented
 implemetation||implementation
 implemntation||implementation
 implentation||implementation
 implmentation||implementation
 implmenting||implementing
+incative||inactive
 incomming||incoming
 incompatabilities||incompatibilities
 incompatable||incompatible
 inconsistant||inconsistent
 increas||increase
+incremeted||incremented
 incrment||increment
 indendation||indentation
 indended||intended
@@ -619,6 +638,7 @@ interger||integer
 intermittant||intermittent
 internel||internal
 interoprability||interoperability
+interuupt||interrupt
 interrface||interface
 interrrupt||interrupt
 interrup||interrupt
@@ -638,8 +658,10 @@ intrrupt||interrupt
 intterrupt||interrupt
 intuative||intuitive
 invaid||invalid
+invald||invalid
 invalde||invalid
 invalide||invalid
+invalidiate||invalidate
 invalud||invalid
 invididual||individual
 invokation||invocation
@@ -713,6 +735,7 @@ misformed||malformed
 mispelled||misspelled
 mispelt||misspelt
 mising||missing
+mismactch||mismatch
 missmanaged||mismanaged
 missmatch||mismatch
 miximum||maximum
@@ -731,6 +754,7 @@ multidimensionnal||multidimensional
 multple||multiple
 mumber||number
 muticast||multicast
+mutilcast||multicast
 mutiple||multiple
 mutli||multi
 nams||names
@@ -834,6 +858,7 @@ posible||possible
 positon||position
 possibilites||possibilities
 powerfull||powerful
+preample||preamble
 preapre||prepare
 preceeded||preceded
 preceeding||preceding
@@ -1059,6 +1084,7 @@ sturcture||structure
 subdirectoires||subdirectories
 suble||subtle
 substract||subtract
+submition||submission
 succesfully||successfully
 succesful||successful
 successed||succeeded
@@ -1078,6 +1104,7 @@ suppoted||supported
 suppported||supported
 suppport||support
 supress||suppress
+surpressed||suppressed
 surpresses||suppresses
 susbsystem||subsystem
 suspeneded||suspended
@@ -1091,6 +1118,7 @@ swithced||switched
 swithcing||switching
 swithed||switched
 swithing||switching
+swtich||switch
 symetric||symmetric
 synax||syntax
 synchonized||synchronized
@@ -1111,7 +1139,9 @@ therfore||therefore
 thier||their
 threds||threads
 threshhold||threshold
+thresold||threshold
 throught||through
+troughput||throughput
 thses||these
 tiggered||triggered
 tipically||typically
@@ -1120,6 +1150,7 @@ tmis||this
 torerable||tolerable
 tramsmitted||transmitted
 tramsmit||transmit
+tranasction||transaction
 tranfer||transfer
 transciever||transceiver
 transferd||transferred
@@ -1133,6 +1164,7 @@ trasmission||transmission
 treshold||threshold
 trigerring||triggering
 trun||turn
+tunning||tuning
 ture||true
 tyep||type
 udpate||update
@@ -1199,6 +1231,7 @@ visiters||visitors
 vitual||virtual
 wakeus||wakeups
 wating||waiting
+wiat||wait
 wether||whether
 whataver||whatever
 whcih||which
index 319add3..286171a 100644 (file)
@@ -1473,7 +1473,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
  * @inode: the object
  * @name: attribute name
  * @buffer: where to put the result
- * @alloc: unused
+ * @alloc: duplicate memory
  *
  * Returns the size of the attribute or an error code
  */
@@ -1486,43 +1486,38 @@ static int smack_inode_getsecurity(struct inode *inode,
        struct super_block *sbp;
        struct inode *ip = (struct inode *)inode;
        struct smack_known *isp;
-       int ilen;
-       int rc = 0;
 
-       if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
+       if (strcmp(name, XATTR_SMACK_SUFFIX) == 0)
                isp = smk_of_inode(inode);
-               ilen = strlen(isp->smk_known);
-               *buffer = isp->smk_known;
-               return ilen;
-       }
+       else {
+               /*
+                * The rest of the Smack xattrs are only on sockets.
+                */
+               sbp = ip->i_sb;
+               if (sbp->s_magic != SOCKFS_MAGIC)
+                       return -EOPNOTSUPP;
 
-       /*
-        * The rest of the Smack xattrs are only on sockets.
-        */
-       sbp = ip->i_sb;
-       if (sbp->s_magic != SOCKFS_MAGIC)
-               return -EOPNOTSUPP;
+               sock = SOCKET_I(ip);
+               if (sock == NULL || sock->sk == NULL)
+                       return -EOPNOTSUPP;
 
-       sock = SOCKET_I(ip);
-       if (sock == NULL || sock->sk == NULL)
-               return -EOPNOTSUPP;
-
-       ssp = sock->sk->sk_security;
+               ssp = sock->sk->sk_security;
 
-       if (strcmp(name, XATTR_SMACK_IPIN) == 0)
-               isp = ssp->smk_in;
-       else if (strcmp(name, XATTR_SMACK_IPOUT) == 0)
-               isp = ssp->smk_out;
-       else
-               return -EOPNOTSUPP;
+               if (strcmp(name, XATTR_SMACK_IPIN) == 0)
+                       isp = ssp->smk_in;
+               else if (strcmp(name, XATTR_SMACK_IPOUT) == 0)
+                       isp = ssp->smk_out;
+               else
+                       return -EOPNOTSUPP;
+       }
 
-       ilen = strlen(isp->smk_known);
-       if (rc == 0) {
-               *buffer = isp->smk_known;
-               rc = ilen;
+       if (alloc) {
+               *buffer = kstrdup(isp->smk_known, GFP_KERNEL);
+               if (*buffer == NULL)
+                       return -ENOMEM;
        }
 
-       return rc;
+       return strlen(isp->smk_known);
 }
 
 
index fec1dfd..4490a69 100644 (file)
@@ -948,14 +948,13 @@ static const struct file_operations snd_compr_file_ops = {
 static int snd_compress_dev_register(struct snd_device *device)
 {
        int ret = -EINVAL;
-       char str[16];
        struct snd_compr *compr;
 
        if (snd_BUG_ON(!device || !device->device_data))
                return -EBADFD;
        compr = device->device_data;
 
-       pr_debug("reg %s for device %s, direction %d\n", str, compr->name,
+       pr_debug("reg device %s, direction %d\n", compr->name,
                        compr->direction);
        /* register compressed device */
        ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS,
index 3a1cc7b..b719d0b 100644 (file)
@@ -547,6 +547,7 @@ struct snd_pcm_mmap_status_x32 {
        u32 pad2; /* alignment */
        struct timespec tstamp;
        s32 suspended_state;
+       s32 pad3;
        struct timespec audio_tstamp;
 } __packed;
 
index 7e3aa50..5badd08 100644 (file)
@@ -103,6 +103,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        void __user *puhr;
        union hpi_message_buffer_v1 *hm;
        union hpi_response_buffer_v1 *hr;
+       u16 msg_size;
        u16 res_max_size;
        u32 uncopied_bytes;
        int err = 0;
@@ -127,22 +128,25 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        }
 
        /* Now read the message size and data from user space.  */
-       if (get_user(hm->h.size, (u16 __user *)puhm)) {
+       if (get_user(msg_size, (u16 __user *)puhm)) {
                err = -EFAULT;
                goto out;
        }
-       if (hm->h.size > sizeof(*hm))
-               hm->h.size = sizeof(*hm);
+       if (msg_size > sizeof(*hm))
+               msg_size = sizeof(*hm);
 
        /* printk(KERN_INFO "message size %d\n", hm->h.wSize); */
 
-       uncopied_bytes = copy_from_user(hm, puhm, hm->h.size);
+       uncopied_bytes = copy_from_user(hm, puhm, msg_size);
        if (uncopied_bytes) {
                HPI_DEBUG_LOG(ERROR, "uncopied bytes %d\n", uncopied_bytes);
                err = -EFAULT;
                goto out;
        }
 
+       /* Override h.size in case it is changed between two userspace fetches */
+       hm->h.size = msg_size;
+
        if (get_user(res_max_size, (u16 __user *)puhr)) {
                err = -EFAULT;
                goto out;
index 7326695..d68f99e 100644 (file)
@@ -1272,11 +1272,11 @@ static int snd_echo_mixer_info(struct snd_kcontrol *kcontrol,
 
        chip = snd_kcontrol_chip(kcontrol);
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
        uinfo->value.integer.min = ECHOGAIN_MINOUT;
        uinfo->value.integer.max = ECHOGAIN_MAXOUT;
        uinfo->dimen.d[0] = num_busses_out(chip);
        uinfo->dimen.d[1] = num_busses_in(chip);
-       uinfo->count = uinfo->dimen.d[0] * uinfo->dimen.d[1];
        return 0;
 }
 
@@ -1344,11 +1344,11 @@ static int snd_echo_vmixer_info(struct snd_kcontrol *kcontrol,
 
        chip = snd_kcontrol_chip(kcontrol);
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
        uinfo->value.integer.min = ECHOGAIN_MINOUT;
        uinfo->value.integer.max = ECHOGAIN_MAXOUT;
        uinfo->dimen.d[0] = num_busses_out(chip);
        uinfo->dimen.d[1] = num_pipes_out(chip);
-       uinfo->count = uinfo->dimen.d[0] * uinfo->dimen.d[1];
        return 0;
 }
 
@@ -1728,6 +1728,7 @@ static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol,
                                  struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 96;
        uinfo->value.integer.min = ECHOGAIN_MINOUT;
        uinfo->value.integer.max = 0;
 #ifdef ECHOCARD_HAS_VMIXER
@@ -1737,7 +1738,6 @@ static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol,
 #endif
        uinfo->dimen.d[1] = 16; /* 16 channels */
        uinfo->dimen.d[2] = 2;  /* 0=level, 1=peak */
-       uinfo->count = uinfo->dimen.d[0] * uinfo->dimen.d[1] * uinfo->dimen.d[2];
        return 0;
 }
 
index 2b64fab..c19c81d 100644 (file)
@@ -906,6 +906,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
                              hda_nid_t pin_nid, u32 stream_tag, int format)
 {
        struct hdmi_spec *spec = codec->spec;
+       unsigned int param;
        int err;
 
        err = spec->ops.pin_hbr_setup(codec, pin_nid, is_hbr_format(format));
@@ -915,6 +916,26 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
                return err;
        }
 
+       if (is_haswell_plus(codec)) {
+
+               /*
+                * on recent platforms IEC Coding Type is required for HBR
+                * support, read current Digital Converter settings and set
+                * ICT bitfield if needed.
+                */
+               param = snd_hda_codec_read(codec, cvt_nid, 0,
+                                          AC_VERB_GET_DIGI_CONVERT_1, 0);
+
+               param = (param >> 16) & ~(AC_DIG3_ICT);
+
+               /* on recent platforms ICT mode is required for HBR support */
+               if (is_hbr_format(format))
+                       param |= 0x1;
+
+               snd_hda_codec_write(codec, cvt_nid, 0,
+                                   AC_VERB_SET_DIGI_CONVERT_3, param);
+       }
+
        snd_hda_codec_setup_stream(codec, cvt_nid, stream_tag, 0, format);
        return 0;
 }
index 3dc36d9..23d1d23 100644 (file)
@@ -221,6 +221,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
        struct usb_interface_descriptor *altsd;
        void *control_header;
        int i, protocol;
+       int rest_bytes;
 
        /* find audiocontrol interface */
        host_iface = &usb_ifnum_to_if(dev, ctrlif)->altsetting[0];
@@ -235,6 +236,15 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
                return -EINVAL;
        }
 
+       rest_bytes = (void *)(host_iface->extra + host_iface->extralen) -
+               control_header;
+
+       /* just to be sure -- this shouldn't hit at all */
+       if (rest_bytes <= 0) {
+               dev_err(&dev->dev, "invalid control header\n");
+               return -EINVAL;
+       }
+
        switch (protocol) {
        default:
                dev_warn(&dev->dev,
@@ -245,11 +255,21 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
        case UAC_VERSION_1: {
                struct uac1_ac_header_descriptor *h1 = control_header;
 
+               if (rest_bytes < sizeof(*h1)) {
+                       dev_err(&dev->dev, "too short v1 buffer descriptor\n");
+                       return -EINVAL;
+               }
+
                if (!h1->bInCollection) {
                        dev_info(&dev->dev, "skipping empty audio interface (v1)\n");
                        return -EINVAL;
                }
 
+               if (rest_bytes < h1->bLength) {
+                       dev_err(&dev->dev, "invalid buffer length (v1)\n");
+                       return -EINVAL;
+               }
+
                if (h1->bLength < sizeof(*h1) + h1->bInCollection) {
                        dev_err(&dev->dev, "invalid UAC_HEADER (v1)\n");
                        return -EINVAL;
index 9135520..b8cb57a 100644 (file)
@@ -1137,6 +1137,8 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
        case USB_ID(0x047F, 0x02F7): /* Plantronics BT-600 */
        case USB_ID(0x047F, 0x0415): /* Plantronics BT-300 */
        case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */
+       case USB_ID(0x047F, 0xC022): /* Plantronics C310 */
+       case USB_ID(0x047F, 0xC036): /* Plantronics C520-M */
        case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
        case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */
        case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */
index 4dab490..e229abd 100644 (file)
@@ -191,7 +191,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk,
        }
 
        pg = get_order(read_size);
-       sk->s = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg);
+       sk->s = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO|
+                                         __GFP_NOWARN, pg);
        if (!sk->s) {
                snd_printk(KERN_WARNING "couldn't __get_free_pages()\n");
                goto out;
@@ -211,7 +212,8 @@ struct usb_stream *usb_stream_new(struct usb_stream_kernel *sk,
        pg = get_order(write_size);
 
        sk->write_page =
-               (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO, pg);
+               (void *)__get_free_pages(GFP_KERNEL|__GFP_COMP|__GFP_ZERO|
+                                        __GFP_NOWARN, pg);
        if (!sk->write_page) {
                snd_printk(KERN_WARNING "couldn't __get_free_pages()\n");
                usb_stream_free(sk);