]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'md/4.3-rc7-fixes' of git://neil.brown.name/md
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 1 Nov 2015 04:20:49 +0000 (21:20 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 1 Nov 2015 04:20:49 +0000 (21:20 -0700)
Pull md bug fixes from Neil Brown:
 "Two more bug fixes for md.

  One bugfix for a list corruption in raid5 because of incorrect
  locking.

  Other for possible data corruption when a recovering device is failed,
  removed, and re-added.

  Both tagged for -stable"

* tag 'md/4.3-rc7-fixes' of git://neil.brown.name/md:
  Revert "md: allow a partially recovered device to be hot-added to an array."
  md/raid5: fix locking in handle_stripe_clean_event()

328 files changed:
.mailmap
Documentation/arm/OMAP/README [new file with mode: 0644]
Documentation/devicetree/bindings/net/cpsw.txt
Documentation/devicetree/bindings/net/smsc-lan87xx.txt [new file with mode: 0644]
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/boot/dts/am57xx-beagle-x15.dts
arch/arm/boot/dts/armada-385-db-ap.dts
arch/arm/boot/dts/berlin2q.dtsi
arch/arm/boot/dts/exynos5420-peach-pit.dts
arch/arm/boot/dts/exynos5800-peach-pi.dts
arch/arm/boot/dts/imx7d.dtsi
arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts
arch/arm/boot/dts/meson.dtsi
arch/arm/boot/dts/omap3-evm-37xx.dts
arch/arm/boot/dts/ste-hrefv60plus.dtsi
arch/arm/boot/dts/tegra114.dtsi
arch/arm/boot/dts/tegra124.dtsi
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/uniphier-ph1-ld6b-ref.dts
arch/arm/kvm/Kconfig
arch/arm/kvm/arm.c
arch/arm/mach-exynos/pm_domains.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/pdata-quirks.c
arch/arm/mach-pxa/pxa3xx.c
arch/arm/net/bpf_jit_32.c
arch/arm/plat-orion/common.c
arch/arm/vdso/vdsomunge.c
arch/arm64/kernel/armv8_deprecated.c
arch/arm64/kernel/efi-stub.c
arch/arm64/kernel/stacktrace.c
arch/arm64/kernel/suspend.c
arch/ia64/include/asm/unistd.h
arch/ia64/include/uapi/asm/unistd.h
arch/ia64/kernel/entry.S
arch/powerpc/include/asm/cache.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/include/asm/reg.h
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/rtas.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/platforms/powernv/smp.c
arch/um/Makefile
arch/um/kernel/trap.c
arch/um/os-Linux/helper.c
arch/x86/boot/compressed/eboot.c
arch/x86/include/asm/string_64.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/process.c
arch/x86/kernel/setup.c
arch/x86/kernel/smpboot.c
arch/x86/um/ldt.c
block/blk-core.c
block/blk-lib.c
block/blk-mq-tag.c
block/blk-mq.c
block/blk-sysfs.c
crypto/ablkcipher.c
crypto/algapi.c
crypto/api.c
crypto/crypto_user.c
drivers/base/dma-contiguous.c
drivers/block/nbd.c
drivers/block/nvme-core.c
drivers/block/rbd.c
drivers/block/xen-blkfront.c
drivers/bus/arm-ccn.c
drivers/clk/clkdev.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/kv_dpm.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/i915/i915_gem_shrinker.c
drivers/gpu/drm/i915/i915_gem_userptr.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_lrc.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-pnx.c
drivers/iio/accel/st_accel_core.c
drivers/iio/adc/twl4030-madc.c
drivers/infiniband/core/cache.c
drivers/infiniband/core/cm.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/roce_gid_mgmt.c
drivers/infiniband/core/ucma.c
drivers/input/mouse/alps.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/lpc32xx_ts.c
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_types.h
drivers/iommu/amd_iommu_v2.c
drivers/iommu/intel-iommu.c
drivers/isdn/hisax/isdnl2.c
drivers/isdn/mISDN/layer2.c
drivers/md/dm-cache-metadata.c
drivers/md/persistent-data/dm-btree-remove.c
drivers/md/persistent-data/dm-btree.c
drivers/media/dvb-frontends/horus3a.h
drivers/media/dvb-frontends/lnbh25.h
drivers/media/dvb-frontends/m88ds3103.c
drivers/media/dvb-frontends/si2168.c
drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
drivers/media/rc/ir-hix5hd2.c
drivers/media/tuners/si2157.c
drivers/media/usb/dvb-usb-v2/rtl28xxu.c
drivers/media/usb/dvb-usb-v2/rtl28xxu.h
drivers/media/v4l2-core/Kconfig
drivers/memory/Kconfig
drivers/memory/omap-gpmc.c
drivers/mmc/card/mmc_test.c
drivers/mmc/core/mmc.c
drivers/net/can/sja1000/peak_pci.c
drivers/net/ethernet/allwinner/sun4i-emac.c
drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
drivers/net/ethernet/amd/xgbe/xgbe-dev.c
drivers/net/ethernet/amd/xgbe/xgbe-drv.c
drivers/net/ethernet/broadcom/bcm63xx_enet.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/cavium/Kconfig
drivers/net/ethernet/cavium/thunder/nic_main.c
drivers/net/ethernet/cavium/thunder/nic_reg.h
drivers/net/ethernet/cavium/thunder/nicvf_main.c
drivers/net/ethernet/cavium/thunder/thunder_bgx.c
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fsl_pq_mdio.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/gianfar_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_adminq.c
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40evf/i40e_adminq.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx5/core/en_flow_table.c
drivers/net/ethernet/mellanox/mlx5/core/port.c
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mellanox/mlxsw/item.h
drivers/net/ethernet/mellanox/mlxsw/pci.c
drivers/net/ethernet/mellanox/mlxsw/switchx2.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/netcp_ethss.c
drivers/net/ethernet/via/via-rhine.c
drivers/net/geneve.c
drivers/net/macvtap.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/dp83848.c [new file with mode: 0644]
drivers/net/phy/mdio-mux-mmioreg.c
drivers/net/phy/mdio-mux.c
drivers/net/phy/micrel.c
drivers/net/phy/smsc.c
drivers/net/ppp/pppoe.c
drivers/net/usb/Kconfig
drivers/net/usb/asix_common.c
drivers/net/usb/asix_devices.c
drivers/net/usb/qmi_wwan.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath10k/hw.h
drivers/net/wireless/ath/ath6kl/init.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/iwlwifi/dvm/lib.c
drivers/net/wireless/iwlwifi/iwl-7000.c
drivers/net/wireless/iwlwifi/mvm/d3.c
drivers/net/wireless/iwlwifi/mvm/fw.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rtlwifi/pci.h
drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
drivers/net/wireless/rtlwifi/rtl8821ae/sw.c
drivers/net/wireless/rtlwifi/wifi.h
drivers/net/xen-netback/xenbus.c
drivers/net/xen-netfront.c
drivers/pci/pci-sysfs.c
drivers/perf/arm_pmu.c
drivers/staging/iio/accel/sca3000_ring.c
drivers/staging/iio/adc/mxs-lradc.c
drivers/thermal/samsung/exynos_tmu.c
drivers/tty/serial/8250/8250_dma.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/vhost/vhost.h
drivers/video/console/fbcon.c
fs/btrfs/file.c
fs/btrfs/ioctl.c
fs/fs-writeback.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmrecovery.c
fs/overlayfs/copy_up.c
fs/overlayfs/inode.c
fs/overlayfs/super.c
include/linux/backing-dev-defs.h
include/linux/backing-dev.h
include/linux/blk-cgroup.h
include/linux/cma.h
include/linux/compiler-gcc.h
include/linux/compiler.h
include/linux/dma-contiguous.h
include/linux/memcontrol.h
include/linux/netdevice.h
include/net/af_unix.h
include/net/dst_metadata.h
include/net/inet_timewait_sock.h
include/net/sock.h
include/sound/soc.h
include/sound/wm8904.h
include/uapi/linux/openvswitch.h
include/uapi/linux/rtnetlink.h
kernel/kmod.c
kernel/module.c
kernel/sched/core.c
kernel/sched/deadline.c
kernel/sched/fair.c
kernel/sched/idle.c
kernel/trace/trace_stack.c
lib/Kconfig.debug
lib/fault-inject.c
mm/backing-dev.c
mm/cma.c
mm/filemap.c
mm/huge_memory.c
mm/memcontrol.c
mm/page-writeback.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/mgmt.c
net/core/dev.c
net/core/ethtool.c
net/core/filter.c
net/dsa/dsa.c
net/ipv4/arp.c
net/ipv4/fib_trie.c
net/ipv4/gre_offload.c
net/ipv4/inet_connection_sock.c
net/ipv4/ip_gre.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/ipt_rpfilter.c
net/ipv4/tcp_dctcp.c
net/ipv4/tcp_output.c
net/ipv4/xfrm4_output.c
net/ipv6/addrconf.c
net/ipv6/fib6_rules.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_output.c
net/ipv6/netfilter/Kconfig
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/route.c
net/ipv6/xfrm6_output.c
net/ipv6/xfrm6_policy.c
net/irda/irlmp.c
net/key/af_key.c
net/mac80211/debugfs.c
net/mac80211/status.c
net/mac80211/tx.c
net/netfilter/core.c
net/netfilter/ipset/ip_set_list_set.c
net/netlink/af_netlink.c
net/openvswitch/actions.c
net/openvswitch/conntrack.c
net/openvswitch/conntrack.h
net/openvswitch/datapath.c
net/openvswitch/datapath.h
net/openvswitch/flow.h
net/openvswitch/flow_netlink.c
net/openvswitch/flow_netlink.h
net/openvswitch/flow_table.c
net/openvswitch/vport-geneve.c
net/openvswitch/vport-gre.c
net/openvswitch/vport-internal_dev.c
net/openvswitch/vport-vxlan.c
net/openvswitch/vport.c
net/openvswitch/vport.h
net/rds/tcp_recv.c
net/sched/act_mirred.c
net/sched/sch_hhf.c
net/switchdev/switchdev.c
net/sysctl_net.c
net/tipc/bcast.c
net/tipc/msg.c
net/tipc/msg.h
net/tipc/node.c
net/tipc/udp_media.c
net/unix/af_unix.c
net/vmw_vsock/af_vsock.c
net/vmw_vsock/vmci_transport.c
net/vmw_vsock/vmci_transport.h
net/xfrm/xfrm_user.c
samples/bpf/bpf_helpers.h
security/keys/gc.c
security/keys/request_key.c
sound/hda/ext/hdac_ext_bus.c
sound/pci/hda/hda_codec.c
sound/pci/hda/patch_conexant.c
sound/soc/codecs/rt298.c
sound/soc/codecs/wm8962.c
sound/soc/soc-ops.c
virt/kvm/arm/arch_timer.c
virt/kvm/arm/vgic.c

index 4b31af54ccd5864359c0810f9733f3026181a631..b1e9a97653dc64853775a97db377a8f269cc8d95 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -59,6 +59,7 @@ James Bottomley <jejb@mulgrave.(none)>
 James Bottomley <jejb@titanic.il.steeleye.com>
 James E Wilson <wilson@specifix.com>
 James Ketrenos <jketreno@io.(none)>
+<javier@osg.samsung.com> <javier.martinez@collabora.co.uk>
 Jean Tourrilhes <jt@hpl.hp.com>
 Jeff Garzik <jgarzik@pretzel.yyz.us>
 Jens Axboe <axboe@suse.de>
diff --git a/Documentation/arm/OMAP/README b/Documentation/arm/OMAP/README
new file mode 100644 (file)
index 0000000..75645c4
--- /dev/null
@@ -0,0 +1,7 @@
+This file contains documentation for running mainline
+kernel on omaps.
+
+KERNEL         NEW DEPENDENCIES
+v4.3+          Update is needed for custom .config files to make sure
+               CONFIG_REGULATOR_PBIAS is enabled for MMC1 to work
+               properly.
index a9df21aaa1548a64da26c74dfbbef13e652cf3da..a2cae4eb4a60a38c83059c66934e6462ca5a2c6c 100644 (file)
@@ -39,6 +39,7 @@ Required properties:
 Optional properties:
 - dual_emac_res_vlan   : Specifies VID to be used to segregate the ports
 - mac-address          : See ethernet.txt file in the same directory
+- phy-handle           : See ethernet.txt file in the same directory
 
 Note: "ti,hwmods" field is used to fetch the base address and irq
 resources from TI, omap hwmod data base during device registration.
diff --git a/Documentation/devicetree/bindings/net/smsc-lan87xx.txt b/Documentation/devicetree/bindings/net/smsc-lan87xx.txt
new file mode 100644 (file)
index 0000000..974edd5
--- /dev/null
@@ -0,0 +1,24 @@
+SMSC LAN87xx Ethernet PHY
+
+Some boards require special tuning values. Configure them
+through an Ethernet OF device node.
+
+Optional properties:
+
+- smsc,disable-energy-detect:
+  If set, do not enable energy detect mode for the SMSC phy.
+  default: enable energy detect mode
+
+Examples:
+smsc phy with disabled energy detect mode on an am335x based board.
+&davinci_mdio {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&davinci_mdio_default>;
+       pinctrl-1 = <&davinci_mdio_sleep>;
+       status = "okay";
+
+       ethernetphy0: ethernet-phy@0 {
+               reg = <0>;
+               smsc,disable-energy-detect;
+       };
+};
index b8577ad9b8a24debb71b8834ce371091754f30c1..747c65316167a70ec147d1254dc33afe7708c149 100644 (file)
@@ -894,11 +894,12 @@ M:        Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 
-ARM/Allwinner A1X SoC support
+ARM/Allwinner sunXi SoC support
 M:     Maxime Ripard <maxime.ripard@free-electrons.com>
+M:     Chen-Yu Tsai <wens@csie.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-N:     sun[x4567]i
+N:     sun[x456789]i
 
 ARM/Allwinner SoC Clock Support
 M:     Emilio López <emilio@elopez.com.ar>
@@ -4427,6 +4428,14 @@ L:       linuxppc-dev@lists.ozlabs.org
 S:     Maintained
 F:     drivers/net/ethernet/freescale/ucc_geth*
 
+FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
+M:     Claudiu Manoil <claudiu.manoil@freescale.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/ethernet/freescale/gianfar*
+X:     drivers/net/ethernet/freescale/gianfar_ptp.c
+F:     Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
+
 FREESCALE QUICC ENGINE UCC UART DRIVER
 M:     Timur Tabi <timur@tabi.org>
 L:     linuxppc-dev@lists.ozlabs.org
@@ -6793,7 +6802,6 @@ F:        drivers/scsi/megaraid/
 
 MELLANOX ETHERNET DRIVER (mlx4_en)
 M:     Amir Vadai <amirv@mellanox.com>
-M:     Ido Shamay <idos@mellanox.com>
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.mellanox.com
@@ -11675,6 +11683,7 @@ F:      drivers/tty/serial/zs.*
 ZSMALLOC COMPRESSED SLAB MEMORY ALLOCATOR
 M:     Minchan Kim <minchan@kernel.org>
 M:     Nitin Gupta <ngupta@vflare.org>
+R:     Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/zsmalloc.c
index d33ab74bffce02ad49424fafb60b9a941b815ffe..431067a41fcfe5df67e3799ad0a6c7880030d41d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 3
 SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc7
 NAME = Blurry Fish Butt
 
 # *DOCUMENTATION*
index 72ad724c67ae94cd6682ec15f3834966dd7028c0..639411f73ca9571f2e0d8b1c4531429e87d11eb1 100644 (file)
@@ -645,6 +645,7 @@ config ARCH_SHMOBILE_LEGACY
 
 config ARCH_RPC
        bool "RiscPC"
+       depends on MMU
        select ARCH_ACORN
        select ARCH_MAY_HAVE_PC_FDC
        select ARCH_SPARSEMEM_ENABLE
index 568adf5efde059f8c9a5ee56d182ea8def05788e..d55e3ea89fda51ba1d6b45f69eeaa8849dad9487 100644 (file)
                                /* SMPS9 unused */
 
                                ldo1_reg: ldo1 {
-                                       /* VDD_SD  */
+                                       /* VDD_SD / VDDSHV8  */
                                        regulator-name = "ldo1";
                                        regulator-min-microvolt = <1800000>;
                                        regulator-max-microvolt = <3300000>;
                                        regulator-boot-on;
+                                       regulator-always-on;
                                };
 
                                ldo2_reg: ldo2 {
index 89f5a95954ed9020c070491cae36cc7b2556eccf..4047621b137e6b107f875dc2f7c82292752bf448 100644 (file)
@@ -46,7 +46,7 @@
 
 / {
        model = "Marvell Armada 385 Access Point Development Board";
-       compatible = "marvell,a385-db-ap", "marvell,armada385", "marvell,armada38x";
+       compatible = "marvell,a385-db-ap", "marvell,armada385", "marvell,armada380";
 
        chosen {
                stdout-path = "serial1:115200n8";
index 63a48490e2f9653ff83f7f6202fd993d101b6ec9..d4dbd28d348c0b74ae4b23b5886b1dfb29dc3aa6 100644 (file)
                };
 
                usb_phy2: phy@a2f400 {
-                       compatible = "marvell,berlin2-usb-phy";
+                       compatible = "marvell,berlin2cd-usb-phy";
                        reg = <0xa2f400 0x128>;
                        #phy-cells = <0>;
                        resets = <&chip_rst 0x104 14>;
                };
 
                usb_phy0: phy@b74000 {
-                       compatible = "marvell,berlin2-usb-phy";
+                       compatible = "marvell,berlin2cd-usb-phy";
                        reg = <0xb74000 0x128>;
                        #phy-cells = <0>;
                        resets = <&chip_rst 0x104 12>;
                };
 
                usb_phy1: phy@b78000 {
-                       compatible = "marvell,berlin2-usb-phy";
+                       compatible = "marvell,berlin2cd-usb-phy";
                        reg = <0xb78000 0x128>;
                        #phy-cells = <0>;
                        resets = <&chip_rst 0x104 13>;
index 8f4d76c5e11c5821ef7e504f21aa87c6103c92de..1b95da79293c58a173ce833d2e72e995a7761cb0 100644 (file)
        };
 };
 
+&pmu_system_controller {
+       assigned-clocks = <&pmu_system_controller 0>;
+       assigned-clock-parents = <&clock CLK_FIN_PLL>;
+};
+
 &rtc {
        status = "okay";
        clocks = <&clock CLK_RTC>, <&max77802 MAX77802_CLK_32K_AP>;
index 7d5b386b5ae6aeb32aed5baf55a2d50ddf374b39..8f40c7e549bd5ef48d77c4ee5c9dacaaae65d820 100644 (file)
        };
 };
 
+&pmu_system_controller {
+       assigned-clocks = <&pmu_system_controller 0>;
+       assigned-clock-parents = <&clock CLK_FIN_PLL>;
+};
+
 &rtc {
        status = "okay";
        clocks = <&clock CLK_RTC>, <&max77802 MAX77802_CLK_32K_AP>;
index b738ce0f9d9bc31f5369b1c97284cf1ec7ff9bb7..6e444bb873f92ee28dd5cebec93d5947f3b8ea15 100644 (file)
                                status = "disabled";
                        };
 
-                       uart2: serial@30870000 {
+                       uart2: serial@30890000 {
                                compatible = "fsl,imx7d-uart",
                                             "fsl,imx6q-uart";
-                               reg = <0x30870000 0x10000>;
+                               reg = <0x30890000 0x10000>;
                                interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX7D_UART2_ROOT_CLK>,
                                        <&clks IMX7D_UART2_ROOT_CLK>;
index 91146c318798ff3422f5fecb87ec0d8f0c97df45..5b0430041ec6d1980cb47ba253ce410bcebd05d0 100644 (file)
@@ -12,7 +12,7 @@
 
 / {
        model = "LogicPD Zoom DM3730 Torpedo Development Kit";
-       compatible = "logicpd,dm3730-torpedo-devkit", "ti,omap36xx";
+       compatible = "logicpd,dm3730-torpedo-devkit", "ti,omap3630", "ti,omap3";
 
        gpio_keys {
                compatible = "gpio-keys";
index 548441384d2a39488d7daffef79ed6c707576a86..8c77c87660cdf2d72e1df3f00d2c76a8e447293c 100644 (file)
@@ -67,7 +67,7 @@
 
        timer@c1109940 {
                compatible = "amlogic,meson6-timer";
-               reg = <0xc1109940 0x14>;
+               reg = <0xc1109940 0x18>;
                interrupts = <0 10 1>;
        };
 
                wdt: watchdog@c1109900 {
                        compatible = "amlogic,meson6-wdt";
                        reg = <0xc1109900 0x8>;
+                       interrupts = <0 0 1>;
                };
 
                uart_AO: serial@c81004c0 {
                        compatible = "amlogic,meson-uart";
-                       reg = <0xc81004c0 0x14>;
+                       reg = <0xc81004c0 0x18>;
                        interrupts = <0 90 1>;
                        clocks = <&clk81>;
                        status = "disabled";
                };
 
-               uart_A: serial@c81084c0 {
+               uart_A: serial@c11084c0 {
                        compatible = "amlogic,meson-uart";
-                       reg = <0xc81084c0 0x14>;
-                       interrupts = <0 90 1>;
+                       reg = <0xc11084c0 0x18>;
+                       interrupts = <0 26 1>;
                        clocks = <&clk81>;
                        status = "disabled";
                };
 
-               uart_B: serial@c81084dc {
+               uart_B: serial@c11084dc {
                        compatible = "amlogic,meson-uart";
-                       reg = <0xc81084dc 0x14>;
-                       interrupts = <0 90 1>;
+                       reg = <0xc11084dc 0x18>;
+                       interrupts = <0 75 1>;
                        clocks = <&clk81>;
                        status = "disabled";
                };
 
-               uart_C: serial@c8108700 {
+               uart_C: serial@c1108700 {
                        compatible = "amlogic,meson-uart";
-                       reg = <0xc8108700 0x14>;
-                       interrupts = <0 90 1>;
+                       reg = <0xc1108700 0x18>;
+                       interrupts = <0 93 1>;
                        clocks = <&clk81>;
                        status = "disabled";
                };
index 16e8ce350ddaae4f4bedc3d86f9d0418e4852f87..bb339d1648e071c4c456a3f627de68f805e1aa9b 100644 (file)
@@ -13,7 +13,7 @@
 
 / {
        model = "TI OMAP37XX EVM (TMDSEVM3730)";
-       compatible = "ti,omap3-evm-37xx", "ti,omap36xx";
+       compatible = "ti,omap3-evm-37xx", "ti,omap3630", "ti,omap3";
 
        memory {
                device_type = "memory";
index 810cda743b6d56ae19118260367f986dcee690af..9c2387b34d0c73c6942c4051d7f6ce72ee2a0aec 100644 (file)
@@ -56,7 +56,7 @@
                                        /* VMMCI level-shifter enable */
                                        default_hrefv60_cfg2 {
                                                pins = "GPIO169_D22";
-                                               ste,config = <&gpio_out_lo>;
+                                               ste,config = <&gpio_out_hi>;
                                        };
                                        /* VMMCI level-shifter voltage select */
                                        default_hrefv60_cfg3 {
index 9d4f86e9c50ada156a5ae785399799b23d67efba..d845bd1448b5459f9a6e4ab52c538c541b8832ef 100644 (file)
                gpio-controller;
                #interrupt-cells = <2>;
                interrupt-controller;
+               /*
                gpio-ranges = <&pinmux 0 0 246>;
+               */
        };
 
        apbmisc@70000800 {
index 1e204a6de12c3a4156821a289a2f7064bd346574..819e2ae2cabe28b09952807ca2f0249c1aa82b7f 100644 (file)
                gpio-controller;
                #interrupt-cells = <2>;
                interrupt-controller;
+               /*
                gpio-ranges = <&pinmux 0 0 251>;
+               */
        };
 
        apbdma: dma@0,60020000 {
index e058709e6d98c0db886bf4549366722605380985..969b828505ae4404846ff169ce17ad7ffd178ec2 100644 (file)
                gpio-controller;
                #interrupt-cells = <2>;
                interrupt-controller;
+               /*
                gpio-ranges = <&pinmux 0 0 224>;
+               */
        };
 
        apbmisc@70000800 {
index fe04fb5e155f4c7dd39509b8877d95eb7a6f8021..c6938ad1b543fb93cf22d297dda5b2d18795afe8 100644 (file)
                gpio-controller;
                #interrupt-cells = <2>;
                interrupt-controller;
+               /*
                gpio-ranges = <&pinmux 0 0 248>;
+               */
        };
 
        apbmisc@70000800 {
index 33963acd7e8f9227eaca31a60c240a37d9f6e754..f80f772d99fb5750ca4cb484a49bbea18b8ba61a 100644 (file)
@@ -85,7 +85,7 @@
 };
 
 &ethsc {
-       interrupts = <0 50 4>;
+       interrupts = <0 52 4>;
 };
 
 &serial0 {
index 210eccadb69a9770ba1b51beb077bb071f565261..356970f3b25e3d2f54b691c8c8b1bb9baca1d7b1 100644 (file)
@@ -21,6 +21,7 @@ config KVM
        depends on MMU && OF
        select PREEMPT_NOTIFIERS
        select ANON_INODES
+       select ARM_GIC
        select HAVE_KVM_CPU_RELAX_INTERCEPT
        select HAVE_KVM_ARCH_TLB_FLUSH_ALL
        select KVM_MMIO
index dc017adfddc8b83698fa8486e2b9b6dbc1e189a0..78b286994577183b8d9ef415ae3ba5f6a41113c4 100644 (file)
@@ -1080,7 +1080,7 @@ static int init_hyp_mode(void)
         */
        err = kvm_timer_hyp_init();
        if (err)
-               goto out_free_mappings;
+               goto out_free_context;
 
 #ifndef CONFIG_HOTPLUG_CPU
        free_boot_hyp_pgd();
index 4a87e86dec45d1546153ca0ebb7310bbd5f82d93..7c21760f590ffd0d4cd47fcafcbcaffe64a85952 100644 (file)
@@ -200,15 +200,15 @@ no_clk:
                args.args_count = 0;
                child_domain = of_genpd_get_from_provider(&args);
                if (IS_ERR(child_domain))
-                       goto next_pd;
+                       continue;
 
                if (of_parse_phandle_with_args(np, "power-domains",
                                         "#power-domain-cells", 0, &args) != 0)
-                       goto next_pd;
+                       continue;
 
                parent_domain = of_genpd_get_from_provider(&args);
                if (IS_ERR(parent_domain))
-                       goto next_pd;
+                       continue;
 
                if (pm_genpd_add_subdomain(parent_domain, child_domain))
                        pr_warn("%s failed to add subdomain: %s\n",
@@ -216,8 +216,6 @@ no_clk:
                else
                        pr_info("%s has as child subdomain: %s.\n",
                                parent_domain->name, child_domain->name);
-next_pd:
-               of_node_put(np);
        }
 
        return 0;
index b3a0dff67e3fc48bb34b13567778d0f178298834..33d1460a56391c397ef305d8ed8275fa94b15720 100644 (file)
@@ -49,6 +49,7 @@ config SOC_OMAP5
        select OMAP_INTERCONNECT
        select OMAP_INTERCONNECT_BARRIER
        select PM_OPP if PM
+       select ZONE_DMA if ARM_LPAE
 
 config SOC_AM33XX
        bool "TI AM33XX"
@@ -78,6 +79,7 @@ config SOC_DRA7XX
        select OMAP_INTERCONNECT
        select OMAP_INTERCONNECT_BARRIER
        select PM_OPP if PM
+       select ZONE_DMA if ARM_LPAE
 
 config ARCH_OMAP2PLUS
        bool
index 6133eaac685df545ec5a6665db0ae72051d8c2fa..fb219a30c10c60ff56f8b6c0ae754a861f886dc0 100644 (file)
@@ -106,6 +106,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
 MACHINE_END
 
 static const char *const omap36xx_boards_compat[] __initconst = {
+       "ti,omap3630",
        "ti,omap36xx",
        NULL,
 };
@@ -243,6 +244,9 @@ static const char *const omap5_boards_compat[] __initconst = {
 };
 
 DT_MACHINE_START(OMAP5_DT, "Generic OMAP5 (Flattened Device Tree)")
+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
+       .dma_zone_size  = SZ_2G,
+#endif
        .reserve        = omap_reserve,
        .smp            = smp_ops(omap4_smp_ops),
        .map_io         = omap5_map_io,
@@ -288,6 +292,9 @@ static const char *const dra74x_boards_compat[] __initconst = {
 };
 
 DT_MACHINE_START(DRA74X_DT, "Generic DRA74X (Flattened Device Tree)")
+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
+       .dma_zone_size  = SZ_2G,
+#endif
        .reserve        = omap_reserve,
        .smp            = smp_ops(omap4_smp_ops),
        .map_io         = dra7xx_map_io,
@@ -308,6 +315,9 @@ static const char *const dra72x_boards_compat[] __initconst = {
 };
 
 DT_MACHINE_START(DRA72X_DT, "Generic DRA72X (Flattened Device Tree)")
+#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
+       .dma_zone_size  = SZ_2G,
+#endif
        .reserve        = omap_reserve,
        .map_io         = dra7xx_map_io,
        .init_early     = dra7xx_init_early,
index ea56397599c21b1f0c7d806ccfe9b1f4fb062f52..1dfe34654c43a353a34ac2cb9b941ff9f951b275 100644 (file)
@@ -559,7 +559,14 @@ static void pdata_quirks_check(struct pdata_init *quirks)
 
 void __init pdata_quirks_init(const struct of_device_id *omap_dt_match_table)
 {
-       omap_sdrc_init(NULL, NULL);
+       /*
+        * We still need this for omap2420 and omap3 PM to work, others are
+        * using drivers/misc/sram.c already.
+        */
+       if (of_machine_is_compatible("ti,omap2420") ||
+           of_machine_is_compatible("ti,omap3"))
+               omap_sdrc_init(NULL, NULL);
+
        pdata_quirks_check(auxdata_quirks);
        of_platform_populate(NULL, omap_dt_match_table,
                             omap_auxdata_lookup, NULL);
index 06005d3f2ba33523d1ee4f9e96499290a9908572..20ce2d386f172c849459e94d1bb88601f1fdd0e7 100644 (file)
 #define PECR_IS(n)     ((1 << ((n) * 2)) << 29)
 
 extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
-#ifdef CONFIG_PM
-
-#define ISRAM_START    0x5c000000
-#define ISRAM_SIZE     SZ_256K
 
 /*
  * NAND NFC: DFI bus arbitration subset
@@ -54,6 +50,11 @@ extern void __init pxa_dt_irq_init(int (*fn)(struct irq_data *, unsigned int));
 #define NDCR_ND_ARB_EN         (1 << 12)
 #define NDCR_ND_ARB_CNTL       (1 << 19)
 
+#ifdef CONFIG_PM
+
+#define ISRAM_START    0x5c000000
+#define ISRAM_SIZE     SZ_256K
+
 static void __iomem *sram;
 static unsigned long wakeup_src;
 
index 876060bcceeb3ea989e24fe18b42910f3cce4058..b8efb8cd1f73ee1cb7de196ae88d9173203c4d2a 100644 (file)
@@ -614,6 +614,7 @@ load_common:
                case BPF_LD | BPF_B | BPF_IND:
                        load_order = 0;
 load_ind:
+                       update_on_xread(ctx);
                        OP_IMM3(ARM_ADD, r_off, r_X, k, ctx);
                        goto load_common;
                case BPF_LDX | BPF_IMM:
index 2235081a04eeac818f58b44923aa565026c0b746..8861c367d06114651920b05420e53ebde3099712 100644 (file)
@@ -495,7 +495,7 @@ void __init orion_ge00_switch_init(struct dsa_platform_data *d, int irq)
 
        d->netdev = &orion_ge00.dev;
        for (i = 0; i < d->nr_chips; i++)
-               d->chip[i].host_dev = &orion_ge00_shared.dev;
+               d->chip[i].host_dev = &orion_ge_mvmdio.dev;
        orion_switch_device.dev.platform_data = d;
 
        platform_device_register(&orion_switch_device);
index aedec81d11988181e3e6f0631113fd01e4737ac8..0cebd98cd88c3fcbfcb88e0d3b1eae757755b3d4 100644 (file)
@@ -45,7 +45,6 @@
  * it does.
  */
 
-#include <byteswap.h>
 #include <elf.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <unistd.h>
 
+#define swab16(x) \
+       ((((x) & 0x00ff) << 8) | \
+        (((x) & 0xff00) >> 8))
+
+#define swab32(x) \
+       ((((x) & 0x000000ff) << 24) | \
+        (((x) & 0x0000ff00) <<  8) | \
+        (((x) & 0x00ff0000) >>  8) | \
+        (((x) & 0xff000000) << 24))
+
 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 #define HOST_ORDER ELFDATA2LSB
 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
@@ -104,17 +113,17 @@ static void cleanup(void)
 
 static Elf32_Word read_elf_word(Elf32_Word word, bool swap)
 {
-       return swap ? bswap_32(word) : word;
+       return swap ? swab32(word) : word;
 }
 
 static Elf32_Half read_elf_half(Elf32_Half half, bool swap)
 {
-       return swap ? bswap_16(half) : half;
+       return swap ? swab16(half) : half;
 }
 
 static void write_elf_word(Elf32_Word val, Elf32_Word *dst, bool swap)
 {
-       *dst = swap ? bswap_32(val) : val;
+       *dst = swap ? swab32(val) : val;
 }
 
 int main(int argc, char **argv)
index bcee7abac68ebb5bcbcde829039113e1e76d5a65..937f5e58a4d340a27234c76b5a84fedcf9aa6373 100644 (file)
@@ -284,21 +284,23 @@ static void register_insn_emulation_sysctl(struct ctl_table *table)
        __asm__ __volatile__(                                   \
        ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN,    \
                    CONFIG_ARM64_PAN)                           \
-       "       mov             %w2, %w1\n"                     \
-       "0:     ldxr"B"         %w1, [%3]\n"                    \
-       "1:     stxr"B"         %w0, %w2, [%3]\n"               \
+       "0:     ldxr"B"         %w2, [%3]\n"                    \
+       "1:     stxr"B"         %w0, %w1, [%3]\n"               \
        "       cbz             %w0, 2f\n"                      \
        "       mov             %w0, %w4\n"                     \
+       "       b               3f\n"                           \
        "2:\n"                                                  \
+       "       mov             %w1, %w2\n"                     \
+       "3:\n"                                                  \
        "       .pushsection     .fixup,\"ax\"\n"               \
        "       .align          2\n"                            \
-       "3:     mov             %w0, %w5\n"                     \
-       "       b               2b\n"                           \
+       "4:     mov             %w0, %w5\n"                     \
+       "       b               3b\n"                           \
        "       .popsection"                                    \
        "       .pushsection     __ex_table,\"a\"\n"            \
        "       .align          3\n"                            \
-       "       .quad           0b, 3b\n"                       \
-       "       .quad           1b, 3b\n"                       \
+       "       .quad           0b, 4b\n"                       \
+       "       .quad           1b, 4b\n"                       \
        "       .popsection\n"                                  \
        ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,    \
                CONFIG_ARM64_PAN)                               \
index 816120ece6bcecfbcbc1c25be51324c5197b65cd..78dfbd34b6bffd2fa36312da89dc6ca43f036c3c 100644 (file)
@@ -25,10 +25,20 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
        unsigned long kernel_size, kernel_memsize = 0;
        unsigned long nr_pages;
        void *old_image_addr = (void *)*image_addr;
+       unsigned long preferred_offset;
+
+       /*
+        * The preferred offset of the kernel Image is TEXT_OFFSET bytes beyond
+        * a 2 MB aligned base, which itself may be lower than dram_base, as
+        * long as the resulting offset equals or exceeds it.
+        */
+       preferred_offset = round_down(dram_base, SZ_2M) + TEXT_OFFSET;
+       if (preferred_offset < dram_base)
+               preferred_offset += SZ_2M;
 
        /* Relocate the image, if required. */
        kernel_size = _edata - _text;
-       if (*image_addr != (dram_base + TEXT_OFFSET)) {
+       if (*image_addr != preferred_offset) {
                kernel_memsize = kernel_size + (_end - _edata);
 
                /*
@@ -42,7 +52,7 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
                 * Mustang), we can still place the kernel at the address
                 * 'dram_base + TEXT_OFFSET'.
                 */
-               *image_addr = *reserve_addr = dram_base + TEXT_OFFSET;
+               *image_addr = *reserve_addr = preferred_offset;
                nr_pages = round_up(kernel_memsize, EFI_ALLOC_ALIGN) /
                           EFI_PAGE_SIZE;
                status = efi_call_early(allocate_pages, EFI_ALLOCATE_ADDRESS,
index 407991bf79f5116eed6d5aa4aa2f1314ecabe0fc..ccb6078ed9f20fb55132deb48504df3a3134a784 100644 (file)
@@ -48,11 +48,7 @@ int notrace unwind_frame(struct stackframe *frame)
 
        frame->sp = fp + 0x10;
        frame->fp = *(unsigned long *)(fp);
-       /*
-        * -4 here because we care about the PC at time of bl,
-        * not where the return will go.
-        */
-       frame->pc = *(unsigned long *)(fp + 8) - 4;
+       frame->pc = *(unsigned long *)(fp + 8);
 
        return 0;
 }
index 8297d502217e13010bc891e7d68b5f7279ea62b9..44ca4143b013227ebf9eb40eafd721454ab45074 100644 (file)
@@ -80,17 +80,21 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
        if (ret == 0) {
                /*
                 * We are resuming from reset with TTBR0_EL1 set to the
-                * idmap to enable the MMU; restore the active_mm mappings in
-                * TTBR0_EL1 unless the active_mm == &init_mm, in which case
-                * the thread entered cpu_suspend with TTBR0_EL1 set to
-                * reserved TTBR0 page tables and should be restored as such.
+                * idmap to enable the MMU; set the TTBR0 to the reserved
+                * page tables to prevent speculative TLB allocations, flush
+                * the local tlb and set the default tcr_el1.t0sz so that
+                * the TTBR0 address space set-up is properly restored.
+                * If the current active_mm != &init_mm we entered cpu_suspend
+                * with mappings in TTBR0 that must be restored, so we switch
+                * them back to complete the address space configuration
+                * restoration before returning.
                 */
-               if (mm == &init_mm)
-                       cpu_set_reserved_ttbr0();
-               else
-                       cpu_switch_mm(mm->pgd, mm);
-
+               cpu_set_reserved_ttbr0();
                flush_tlb_all();
+               cpu_set_default_tcr_t0sz();
+
+               if (mm != &init_mm)
+                       cpu_switch_mm(mm->pgd, mm);
 
                /*
                 * Restore per-cpu offset before any kernel
index 99c96a5e6016b50a951ba8dfccf609cb06962232..db73390568c8dd873fc045cd35773714bd35f8e1 100644 (file)
@@ -11,7 +11,7 @@
 
 
 
-#define NR_syscalls                    321 /* length of syscall table */
+#define NR_syscalls                    322 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
index 98e94e19a5a0870fc71b34f85310f475de85697b..9038726e7d26777bf8f704f101ff86090e4d5059 100644 (file)
 #define __NR_execveat                  1342
 #define __NR_userfaultfd               1343
 #define __NR_membarrier                        1344
+#define __NR_kcmp                      1345
 
 #endif /* _UAPI_ASM_IA64_UNISTD_H */
index 37cc7a65cd3ee1fc3304d862776f438db4158b4d..dcd97f84d065435a8eca5c041f33bb67c3912797 100644 (file)
@@ -1770,5 +1770,6 @@ sys_call_table:
        data8 sys_execveat
        data8 sys_userfaultfd
        data8 sys_membarrier
+       data8 sys_kcmp                          // 1345
 
        .org sys_call_table + 8*NR_syscalls     // guard against failures to increase NR_syscalls
index 0dc42c5082b74a1d4fee5709e21100ee0ec8a2df..5f8229e24fe6523a73ef2335a5f480e5f3983911 100644 (file)
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <asm/reg.h>
 
 /* bytes per L1 cache line */
 #if defined(CONFIG_8xx) || defined(CONFIG_403GCX)
@@ -40,12 +39,6 @@ struct ppc64_caches {
 };
 
 extern struct ppc64_caches ppc64_caches;
-
-static inline void logmpp(u64 x)
-{
-       asm volatile(PPC_LOGMPP(R1) : : "r" (x));
-}
-
 #endif /* __powerpc64__ && ! __ASSEMBLY__ */
 
 #if defined(__ASSEMBLY__)
index 827a38d7a9dbe32adfcaf7937c276f6cfce222a4..887c259556dff8e6a2f534ec38355d77a90fbeda 100644 (file)
@@ -297,8 +297,6 @@ struct kvmppc_vcore {
        u32 arch_compat;
        ulong pcr;
        ulong dpdes;            /* doorbell state (POWER8) */
-       void *mpp_buffer; /* Micro Partition Prefetch buffer */
-       bool mpp_buffer_is_valid;
        ulong conferring_threads;
 };
 
index 790f5d1d9a4624d6f17bdde78706be7240d29ad2..7ab04fc59e2462917501a7f6a1b8727be3685163 100644 (file)
 #define PPC_INST_ISEL                  0x7c00001e
 #define PPC_INST_ISEL_MASK             0xfc00003e
 #define PPC_INST_LDARX                 0x7c0000a8
-#define PPC_INST_LOGMPP                        0x7c0007e4
 #define PPC_INST_LSWI                  0x7c0004aa
 #define PPC_INST_LSWX                  0x7c00042a
 #define PPC_INST_LWARX                 0x7c000028
 #define __PPC_EH(eh)   0
 #endif
 
-/* POWER8 Micro Partition Prefetch (MPP) parameters */
-/* Address mask is common for LOGMPP instruction and MPPR SPR */
-#define PPC_MPPE_ADDRESS_MASK 0xffffffffc000ULL
-
-/* Bits 60 and 61 of MPP SPR should be set to one of the following */
-/* Aborting the fetch is indeed setting 00 in the table size bits */
-#define PPC_MPPR_FETCH_ABORT (0x0ULL << 60)
-#define PPC_MPPR_FETCH_WHOLE_TABLE (0x2ULL << 60)
-
-/* Bits 54 and 55 of register for LOGMPP instruction should be set to: */
-#define PPC_LOGMPP_LOG_L2 (0x02ULL << 54)
-#define PPC_LOGMPP_LOG_L2L3 (0x01ULL << 54)
-#define PPC_LOGMPP_LOG_ABORT (0x03ULL << 54)
-
 /* Deal with instructions that older assemblers aren't aware of */
 #define        PPC_DCBAL(a, b)         stringify_in_c(.long PPC_INST_DCBAL | \
                                        __PPC_RA(a) | __PPC_RB(b))
 #define PPC_LDARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LDARX | \
                                        ___PPC_RT(t) | ___PPC_RA(a) | \
                                        ___PPC_RB(b) | __PPC_EH(eh))
-#define PPC_LOGMPP(b)          stringify_in_c(.long PPC_INST_LOGMPP | \
-                                       __PPC_RB(b))
 #define PPC_LWARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LWARX | \
                                        ___PPC_RT(t) | ___PPC_RA(a) | \
                                        ___PPC_RB(b) | __PPC_EH(eh))
index aa1cc5f015eeee564e2c1c83f295acb7d0c523d8..a908ada8e0a5353f5fce19af6ad3e59779ce2e0e 100644 (file)
 #define   CTRL_TE      0x00c00000      /* thread enable */
 #define   CTRL_RUNLATCH        0x1
 #define SPRN_DAWR      0xB4
-#define SPRN_MPPR      0xB8    /* Micro Partition Prefetch Register */
 #define SPRN_RPR       0xBA    /* Relative Priority Register */
 #define SPRN_CIABR     0xBB
 #define   CIABR_PRIV           0x3
index 59503ed98e5fcd5bdb783b23a074eadf4ac3fafa..3f1472a78f393434e2b77df6ab2e24587566befe 100644 (file)
@@ -303,7 +303,7 @@ int dma_set_coherent_mask(struct device *dev, u64 mask)
        dev->coherent_dma_mask = mask;
        return 0;
 }
-EXPORT_SYMBOL_GPL(dma_set_coherent_mask);
+EXPORT_SYMBOL(dma_set_coherent_mask);
 
 #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
 
index 84bf934cf74874eab39926b292c6fa7534829d24..5a753fae8265ae8fc2f9e2e99152c0192fd62b9d 100644 (file)
@@ -1043,6 +1043,9 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       if (!rtas.entry)
+               return -EINVAL;
+
        if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)
                return -EFAULT;
 
index 2280497868886990678c19c01f5cf1c22b25f7a5..9c26c5a96ea2bc0ea9d2286f4995b2d629be9003 100644 (file)
@@ -36,7 +36,6 @@
 
 #include <asm/reg.h>
 #include <asm/cputable.h>
-#include <asm/cache.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 #include <asm/uaccess.h>
 
 static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1);
 
-#if defined(CONFIG_PPC_64K_PAGES)
-#define MPP_BUFFER_ORDER       0
-#elif defined(CONFIG_PPC_4K_PAGES)
-#define MPP_BUFFER_ORDER       3
-#endif
-
 static int dynamic_mt_modes = 6;
 module_param(dynamic_mt_modes, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(dynamic_mt_modes, "Set of allowed dynamic micro-threading modes: 0 (= none), 2, 4, or 6 (= 2 or 4)");
@@ -1455,13 +1448,6 @@ static struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int core)
        vcore->kvm = kvm;
        INIT_LIST_HEAD(&vcore->preempt_list);
 
-       vcore->mpp_buffer_is_valid = false;
-
-       if (cpu_has_feature(CPU_FTR_ARCH_207S))
-               vcore->mpp_buffer = (void *)__get_free_pages(
-                       GFP_KERNEL|__GFP_ZERO,
-                       MPP_BUFFER_ORDER);
-
        return vcore;
 }
 
@@ -1894,33 +1880,6 @@ static int on_primary_thread(void)
        return 1;
 }
 
-static void kvmppc_start_saving_l2_cache(struct kvmppc_vcore *vc)
-{
-       phys_addr_t phy_addr, mpp_addr;
-
-       phy_addr = (phys_addr_t)virt_to_phys(vc->mpp_buffer);
-       mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
-
-       mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_ABORT);
-       logmpp(mpp_addr | PPC_LOGMPP_LOG_L2);
-
-       vc->mpp_buffer_is_valid = true;
-}
-
-static void kvmppc_start_restoring_l2_cache(const struct kvmppc_vcore *vc)
-{
-       phys_addr_t phy_addr, mpp_addr;
-
-       phy_addr = virt_to_phys(vc->mpp_buffer);
-       mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK;
-
-       /* We must abort any in-progress save operations to ensure
-        * the table is valid so that prefetch engine knows when to
-        * stop prefetching. */
-       logmpp(mpp_addr | PPC_LOGMPP_LOG_ABORT);
-       mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_WHOLE_TABLE);
-}
-
 /*
  * A list of virtual cores for each physical CPU.
  * These are vcores that could run but their runner VCPU tasks are
@@ -2471,14 +2430,8 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
 
        srcu_idx = srcu_read_lock(&vc->kvm->srcu);
 
-       if (vc->mpp_buffer_is_valid)
-               kvmppc_start_restoring_l2_cache(vc);
-
        __kvmppc_vcore_entry();
 
-       if (vc->mpp_buffer)
-               kvmppc_start_saving_l2_cache(vc);
-
        srcu_read_unlock(&vc->kvm->srcu, srcu_idx);
 
        spin_lock(&vc->lock);
@@ -3073,14 +3026,8 @@ static void kvmppc_free_vcores(struct kvm *kvm)
 {
        long int i;
 
-       for (i = 0; i < KVM_MAX_VCORES; ++i) {
-               if (kvm->arch.vcores[i] && kvm->arch.vcores[i]->mpp_buffer) {
-                       struct kvmppc_vcore *vc = kvm->arch.vcores[i];
-                       free_pages((unsigned long)vc->mpp_buffer,
-                                  MPP_BUFFER_ORDER);
-               }
+       for (i = 0; i < KVM_MAX_VCORES; ++i)
                kfree(kvm->arch.vcores[i]);
-       }
        kvm->arch.online_vcores = 0;
 }
 
index 8f70ba681a78b91e6755e3e123c3dc784857e3c6..ca264833ee64d5c7a55035c66c21454d7b4d0b14 100644 (file)
@@ -171,7 +171,26 @@ static void pnv_smp_cpu_kill_self(void)
         * so clear LPCR:PECE1. We keep PECE2 enabled.
         */
        mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
+
+       /*
+        * Hard-disable interrupts, and then clear irq_happened flags
+        * that we can safely ignore while off-line, since they
+        * are for things for which we do no processing when off-line
+        * (or in the case of HMI, all the processing we need to do
+        * is done in lower-level real-mode code).
+        */
+       hard_irq_disable();
+       local_paca->irq_happened &= ~(PACA_IRQ_DEC | PACA_IRQ_HMI);
+
        while (!generic_check_cpu_restart(cpu)) {
+               /*
+                * Clear IPI flag, since we don't handle IPIs while
+                * offline, except for those when changing micro-threading
+                * mode, which are handled explicitly below, and those
+                * for coming online, which are handled via
+                * generic_check_cpu_restart() calls.
+                */
+               kvmppc_set_host_ipi(cpu, 0);
 
                ppc64_runlatch_off();
 
@@ -196,20 +215,20 @@ static void pnv_smp_cpu_kill_self(void)
                 * having finished executing in a KVM guest, then srr1
                 * contains 0.
                 */
-               if ((srr1 & wmask) == SRR1_WAKEEE) {
+               if (((srr1 & wmask) == SRR1_WAKEEE) ||
+                   (local_paca->irq_happened & PACA_IRQ_EE)) {
                        icp_native_flush_interrupt();
-                       local_paca->irq_happened &= PACA_IRQ_HARD_DIS;
-                       smp_mb();
                } else if ((srr1 & wmask) == SRR1_WAKEHDBELL) {
                        unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER);
                        asm volatile(PPC_MSGCLR(%0) : : "r" (msg));
-                       kvmppc_set_host_ipi(cpu, 0);
                }
+               local_paca->irq_happened &= ~(PACA_IRQ_EE | PACA_IRQ_DBELL);
+               smp_mb();
 
                if (cpu_core_split_required())
                        continue;
 
-               if (!generic_check_cpu_restart(cpu))
+               if (srr1 && !generic_check_cpu_restart(cpu))
                        DBG("CPU%d Unexpected exit while offline !\n", cpu);
        }
        mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_PECE1);
index 098ab3333e7cdd5e4cdce7f20b28c7678ed2a852..e3abe6f3156d3fbacca4003c072954619c7e1bb1 100644 (file)
@@ -70,8 +70,8 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
 
 USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
                $(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \
-               -D_FILE_OFFSET_BITS=64 -idirafter include \
-               -D__KERNEL__ -D__UM_HOST__
+               -D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \
+               -idirafter $(obj)/include -D__KERNEL__ -D__UM_HOST__
 
 #This will adjust *FLAGS accordingly to the platform.
 include $(ARCH_DIR)/Makefile-os-$(OS)
index d8a9fce6ee2e5b10a63405654c3958c7361951fe..98783dd0fa2ea697a50cb65afb661aa7f7bf0322 100644 (file)
@@ -220,7 +220,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
                show_regs(container_of(regs, struct pt_regs, regs));
                panic("Segfault with no mm");
        }
-       else if (!is_user && address < TASK_SIZE) {
+       else if (!is_user && address > PAGE_SIZE && address < TASK_SIZE) {
                show_regs(container_of(regs, struct pt_regs, regs));
                panic("Kernel tried to access user memory at addr 0x%lx, ip 0x%lx",
                       address, ip);
index e3ee4a51ef63a3ec7e7314aa7f00d59ec93ce37e..3f02d42328127bc6c41b786fd9b10145256cd57f 100644 (file)
@@ -96,7 +96,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
                               "ret = %d\n", -n);
                        ret = n;
                }
-               CATCH_EINTR(waitpid(pid, NULL, __WCLONE));
+               CATCH_EINTR(waitpid(pid, NULL, __WALL));
        }
 
 out_free2:
@@ -129,7 +129,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
                return err;
        }
        if (stack_out == NULL) {
-               CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE));
+               CATCH_EINTR(pid = waitpid(pid, &status, __WALL));
                if (pid < 0) {
                        err = -errno;
                        printk(UM_KERN_ERR "run_helper_thread - wait failed, "
@@ -148,7 +148,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
 int helper_wait(int pid)
 {
        int ret, status;
-       int wflags = __WCLONE;
+       int wflags = __WALL;
 
        CATCH_EINTR(ret = waitpid(pid, &status, wflags));
        if (ret < 0) {
index ee1b6d346b983ad196a003dcb47c7a1de439eb3b..db51c1f27446157001cedc87bdd38b551e2f1844 100644 (file)
@@ -667,6 +667,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
                bool conout_found = false;
                void *dummy = NULL;
                u32 h = handles[i];
+               u32 current_fb_base;
 
                status = efi_call_early(handle_protocol, h,
                                        proto, (void **)&gop32);
@@ -678,7 +679,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
                if (status == EFI_SUCCESS)
                        conout_found = true;
 
-               status = __gop_query32(gop32, &info, &size, &fb_base);
+               status = __gop_query32(gop32, &info, &size, &current_fb_base);
                if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
                        /*
                         * Systems that use the UEFI Console Splitter may
@@ -692,6 +693,7 @@ setup_gop32(struct screen_info *si, efi_guid_t *proto,
                        pixel_format = info->pixel_format;
                        pixel_info = info->pixel_information;
                        pixels_per_scan_line = info->pixels_per_scan_line;
+                       fb_base = current_fb_base;
 
                        /*
                         * Once we've found a GOP supporting ConOut,
@@ -770,6 +772,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
                bool conout_found = false;
                void *dummy = NULL;
                u64 h = handles[i];
+               u32 current_fb_base;
 
                status = efi_call_early(handle_protocol, h,
                                        proto, (void **)&gop64);
@@ -781,7 +784,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
                if (status == EFI_SUCCESS)
                        conout_found = true;
 
-               status = __gop_query64(gop64, &info, &size, &fb_base);
+               status = __gop_query64(gop64, &info, &size, &current_fb_base);
                if (status == EFI_SUCCESS && (!first_gop || conout_found)) {
                        /*
                         * Systems that use the UEFI Console Splitter may
@@ -795,6 +798,7 @@ setup_gop64(struct screen_info *si, efi_guid_t *proto,
                        pixel_format = info->pixel_format;
                        pixel_info = info->pixel_information;
                        pixels_per_scan_line = info->pixels_per_scan_line;
+                       fb_base = current_fb_base;
 
                        /*
                         * Once we've found a GOP supporting ConOut,
index e4661196994e86b189da7f6c2e84841d3dcdcb9b..ff8b9a17dc4b2d354971fb52b60b69e6fbb0e903 100644 (file)
@@ -27,12 +27,11 @@ static __always_inline void *__inline_memcpy(void *to, const void *from, size_t
    function. */
 
 #define __HAVE_ARCH_MEMCPY 1
+extern void *memcpy(void *to, const void *from, size_t len);
 extern void *__memcpy(void *to, const void *from, size_t len);
 
 #ifndef CONFIG_KMEMCHECK
-#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4
-extern void *memcpy(void *to, const void *from, size_t len);
-#else
+#if (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || __GNUC__ < 4
 #define memcpy(dst, src, len)                                  \
 ({                                                             \
        size_t __len = (len);                                   \
index 5c60bb16262203ab63720ee349384180e9e7d8fb..bb6bfc01cb82dd6ffbe4aa49e92020b2600584d6 100644 (file)
@@ -2907,6 +2907,7 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
        struct irq_data *irq_data;
        struct mp_chip_data *data;
        struct irq_alloc_info *info = arg;
+       unsigned long flags;
 
        if (!info || nr_irqs > 1)
                return -EINVAL;
@@ -2939,11 +2940,14 @@ int mp_irqdomain_alloc(struct irq_domain *domain, unsigned int virq,
 
        cfg = irqd_cfg(irq_data);
        add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin);
+
+       local_irq_save(flags);
        if (info->ioapic_entry)
                mp_setup_entry(cfg, data, info->ioapic_entry);
        mp_register_handler(virq, data->trigger);
        if (virq < nr_legacy_irqs())
                legacy_pic->mask(virq);
+       local_irq_restore(flags);
 
        apic_printk(APIC_VERBOSE, KERN_DEBUG
                    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i Dest:%d)\n",
index 39e585a554b71d2a469c8b8c3ba487be7edc87a7..e28db181e4fcb04d19c02e7709e20fabb06f8c29 100644 (file)
@@ -550,14 +550,14 @@ unsigned long get_wchan(struct task_struct *p)
        if (sp < bottom || sp > top)
                return 0;
 
-       fp = READ_ONCE(*(unsigned long *)sp);
+       fp = READ_ONCE_NOCHECK(*(unsigned long *)sp);
        do {
                if (fp < bottom || fp > top)
                        return 0;
-               ip = READ_ONCE(*(unsigned long *)(fp + sizeof(unsigned long)));
+               ip = READ_ONCE_NOCHECK(*(unsigned long *)(fp + sizeof(unsigned long)));
                if (!in_sched_functions(ip))
                        return ip;
-               fp = READ_ONCE(*(unsigned long *)fp);
+               fp = READ_ONCE_NOCHECK(*(unsigned long *)fp);
        } while (count++ < 16 && p->state != TASK_RUNNING);
        return 0;
 }
index fdb7f2a2d3286013a7ea41d392e48596c90fc672..a3cccbfc5f777e3483cad7da4a5a587bdd56c09c 100644 (file)
@@ -1173,6 +1173,14 @@ void __init setup_arch(char **cmdline_p)
        clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
                        swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
                        KERNEL_PGD_PTRS);
+
+       /*
+        * sync back low identity map too.  It is used for example
+        * in the 32-bit EFI stub.
+        */
+       clone_pgd_range(initial_page_table,
+                       swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
+                       KERNEL_PGD_PTRS);
 #endif
 
        tboot_probe();
index e0c198e5f920202bf25fa36e34922d4b0d29d82c..892ee2e5ecbce417df506715f7b28d28c403ef91 100644 (file)
@@ -509,7 +509,7 @@ void __inquire_remote_apic(int apicid)
  */
 #define UDELAY_10MS_DEFAULT 10000
 
-static unsigned int init_udelay = UDELAY_10MS_DEFAULT;
+static unsigned int init_udelay = INT_MAX;
 
 static int __init cpu_init_udelay(char *str)
 {
@@ -522,13 +522,16 @@ early_param("cpu_init_udelay", cpu_init_udelay);
 static void __init smp_quirk_init_udelay(void)
 {
        /* if cmdline changed it from default, leave it alone */
-       if (init_udelay != UDELAY_10MS_DEFAULT)
+       if (init_udelay != INT_MAX)
                return;
 
        /* if modern processor, use no delay */
        if (((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 6)) ||
            ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && (boot_cpu_data.x86 >= 0xF)))
                init_udelay = 0;
+
+       /* else, use legacy delay */
+       init_udelay = UDELAY_10MS_DEFAULT;
 }
 
 /*
@@ -657,7 +660,9 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
                /*
                 * Give the other CPU some time to accept the IPI.
                 */
-               if (init_udelay)
+               if (init_udelay == 0)
+                       udelay(10);
+               else
                        udelay(300);
 
                pr_debug("Startup point 1\n");
@@ -668,7 +673,9 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
                /*
                 * Give the other CPU some time to accept the IPI.
                 */
-               if (init_udelay)
+               if (init_udelay == 0)
+                       udelay(10);
+               else
                        udelay(200);
 
                if (maxlvt > 3)         /* Due to the Pentium erratum 3AP.  */
index 9701a4fd7bf2ea83d640ddeefebd5e4d5de27598..836a1eb5df436bdad88fe3b4ae59b512f9573b19 100644 (file)
 #include <skas.h>
 #include <sysdep/tls.h>
 
-extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
+static inline int modify_ldt (int func, void *ptr, unsigned long bytecount)
+{
+       return syscall(__NR_modify_ldt, func, ptr, bytecount);
+}
 
 static long write_ldt_entry(struct mm_id *mm_idp, int func,
                     struct user_desc *desc, void **addr, int done)
index 2eb722d48773cb8a8de49d58b934eed830755da7..18e92a6645e24741b786bc35f14b9d06f1355569 100644 (file)
@@ -576,7 +576,7 @@ void blk_cleanup_queue(struct request_queue *q)
                q->queue_lock = &q->__queue_lock;
        spin_unlock_irq(lock);
 
-       bdi_destroy(&q->backing_dev_info);
+       bdi_unregister(&q->backing_dev_info);
 
        /* @q is and will stay empty, shutdown and put */
        blk_put_queue(q);
index bd40292e5009675ef17d6914b67010834cf1beb6..9ebf65379556a0f5730b3934acd2fa78e232e816 100644 (file)
@@ -26,13 +26,6 @@ static void bio_batch_end_io(struct bio *bio)
        bio_put(bio);
 }
 
-/*
- * Ensure that max discard sectors doesn't overflow bi_size and hopefully
- * it is of the proper granularity as long as the granularity is a power
- * of two.
- */
-#define MAX_BIO_SECTORS ((1U << 31) >> 9)
-
 /**
  * blkdev_issue_discard - queue a discard
  * @bdev:      blockdev to issue discard for
@@ -50,6 +43,8 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
        DECLARE_COMPLETION_ONSTACK(wait);
        struct request_queue *q = bdev_get_queue(bdev);
        int type = REQ_WRITE | REQ_DISCARD;
+       unsigned int granularity;
+       int alignment;
        struct bio_batch bb;
        struct bio *bio;
        int ret = 0;
@@ -61,6 +56,10 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
        if (!blk_queue_discard(q))
                return -EOPNOTSUPP;
 
+       /* Zero-sector (unknown) and one-sector granularities are the same.  */
+       granularity = max(q->limits.discard_granularity >> 9, 1U);
+       alignment = (bdev_discard_alignment(bdev) >> 9) % granularity;
+
        if (flags & BLKDEV_DISCARD_SECURE) {
                if (!blk_queue_secdiscard(q))
                        return -EOPNOTSUPP;
@@ -74,7 +73,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
        blk_start_plug(&plug);
        while (nr_sects) {
                unsigned int req_sects;
-               sector_t end_sect;
+               sector_t end_sect, tmp;
 
                bio = bio_alloc(gfp_mask, 1);
                if (!bio) {
@@ -82,8 +81,22 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
                        break;
                }
 
-               req_sects = min_t(sector_t, nr_sects, MAX_BIO_SECTORS);
+               /* Make sure bi_size doesn't overflow */
+               req_sects = min_t(sector_t, nr_sects, UINT_MAX >> 9);
+
+               /*
+                * If splitting a request, and the next starting sector would be
+                * misaligned, stop the discard at the previous aligned sector.
+                */
                end_sect = sector + req_sects;
+               tmp = end_sect;
+               if (req_sects < nr_sects &&
+                   sector_div(tmp, granularity) != alignment) {
+                       end_sect = end_sect - alignment;
+                       sector_div(end_sect, granularity);
+                       end_sect = end_sect * granularity + alignment;
+                       req_sects = end_sect - sector;
+               }
 
                bio->bi_iter.bi_sector = sector;
                bio->bi_end_io = bio_batch_end_io;
index ed96474d75cb62fb261526736727c67ea2238d46..ec2d11915142a8f9b7a49e839e41a2f54a55aa09 100644 (file)
@@ -641,6 +641,7 @@ void blk_mq_free_tags(struct blk_mq_tags *tags)
 {
        bt_free(&tags->bitmap_tags);
        bt_free(&tags->breserved_tags);
+       free_cpumask_var(tags->cpumask);
        kfree(tags);
 }
 
index 7785ae96267a197926c700f74bcd6524892a8c01..85f014327342efc775c31833a52f531b69a66329 100644 (file)
@@ -2296,10 +2296,8 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set)
        int i;
 
        for (i = 0; i < set->nr_hw_queues; i++) {
-               if (set->tags[i]) {
+               if (set->tags[i])
                        blk_mq_free_rq_map(set, set->tags[i], i);
-                       free_cpumask_var(set->tags[i]->cpumask);
-               }
        }
 
        kfree(set->tags);
index 3e44a9da2a13579cacaee3d5e03bb3868f34d02a..07b42f5ad797b7b5e6367d5c70051d3b34fca55c 100644 (file)
@@ -540,6 +540,7 @@ static void blk_release_queue(struct kobject *kobj)
        struct request_queue *q =
                container_of(kobj, struct request_queue, kobj);
 
+       bdi_exit(&q->backing_dev_info);
        blkcg_exit_queue(q);
 
        if (q->elevator) {
index b788f169cc9880d0d1ac2ce4930145d9862b306d..b4ffc5be1a93c1ff0bceb6b9a5cc3dc1b5101d97 100644 (file)
@@ -706,7 +706,7 @@ struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name,
 err:
                if (err != -EAGAIN)
                        break;
-               if (signal_pending(current)) {
+               if (fatal_signal_pending(current)) {
                        err = -EINTR;
                        break;
                }
index d130b41dbaea244000c35328d7eba7b463158bc8..59bf491fe3d8606acc4016c53182182615d32a21 100644 (file)
@@ -345,7 +345,7 @@ static void crypto_wait_for_test(struct crypto_larval *larval)
                crypto_alg_tested(larval->alg.cra_driver_name, 0);
        }
 
-       err = wait_for_completion_interruptible(&larval->completion);
+       err = wait_for_completion_killable(&larval->completion);
        WARN_ON(err);
 
 out:
index afe4610afc4b952d585ede5ba9cbd732f5aa3750..bbc147cb5dec87affad82510412459c075056f86 100644 (file)
@@ -172,7 +172,7 @@ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
        struct crypto_larval *larval = (void *)alg;
        long timeout;
 
-       timeout = wait_for_completion_interruptible_timeout(
+       timeout = wait_for_completion_killable_timeout(
                &larval->completion, 60 * HZ);
 
        alg = larval->adult;
@@ -445,7 +445,7 @@ struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
 err:
                if (err != -EAGAIN)
                        break;
-               if (signal_pending(current)) {
+               if (fatal_signal_pending(current)) {
                        err = -EINTR;
                        break;
                }
@@ -562,7 +562,7 @@ void *crypto_alloc_tfm(const char *alg_name,
 err:
                if (err != -EAGAIN)
                        break;
-               if (signal_pending(current)) {
+               if (fatal_signal_pending(current)) {
                        err = -EINTR;
                        break;
                }
index d94d99ffe8b9b6cecf2c8348241ea17738e9b457..237f3795cfaaa1f988fadf5b07eefe3c44609091 100644 (file)
@@ -375,7 +375,7 @@ static struct crypto_alg *crypto_user_skcipher_alg(const char *name, u32 type,
                err = PTR_ERR(alg);
                if (err != -EAGAIN)
                        break;
-               if (signal_pending(current)) {
+               if (fatal_signal_pending(current)) {
                        err = -EINTR;
                        break;
                }
index 950fff9ce45397024ac5751b452cdd96a6da9907..a12ff9863d7e116ba9f15e21fe9c6fa4070b0f22 100644 (file)
@@ -187,7 +187,7 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
  * global one. Requires architecture specific dev_get_cma_area() helper
  * function.
  */
-struct page *dma_alloc_from_contiguous(struct device *dev, int count,
+struct page *dma_alloc_from_contiguous(struct device *dev, size_t count,
                                       unsigned int align)
 {
        if (align > CONFIG_CMA_ALIGNMENT)
index 293495a75d3d8ce1e0f61e3571ddcc0c1fa14312..1b87623381e2b1183b5c9d57c870b7c10924f65e 100644 (file)
@@ -60,6 +60,7 @@ struct nbd_device {
        bool disconnect; /* a disconnect has been requested by user */
 
        struct timer_list timeout_timer;
+       spinlock_t tasks_lock;
        struct task_struct *task_recv;
        struct task_struct *task_send;
 
@@ -140,21 +141,23 @@ static void sock_shutdown(struct nbd_device *nbd)
 static void nbd_xmit_timeout(unsigned long arg)
 {
        struct nbd_device *nbd = (struct nbd_device *)arg;
-       struct task_struct *task;
+       unsigned long flags;
 
        if (list_empty(&nbd->queue_head))
                return;
 
        nbd->disconnect = true;
 
-       task = READ_ONCE(nbd->task_recv);
-       if (task)
-               force_sig(SIGKILL, task);
+       spin_lock_irqsave(&nbd->tasks_lock, flags);
+
+       if (nbd->task_recv)
+               force_sig(SIGKILL, nbd->task_recv);
 
-       task = READ_ONCE(nbd->task_send);
-       if (task)
+       if (nbd->task_send)
                force_sig(SIGKILL, nbd->task_send);
 
+       spin_unlock_irqrestore(&nbd->tasks_lock, flags);
+
        dev_err(nbd_to_dev(nbd), "Connection timed out, killed receiver and sender, shutting down connection\n");
 }
 
@@ -403,17 +406,24 @@ static int nbd_thread_recv(struct nbd_device *nbd)
 {
        struct request *req;
        int ret;
+       unsigned long flags;
 
        BUG_ON(nbd->magic != NBD_MAGIC);
 
        sk_set_memalloc(nbd->sock->sk);
 
+       spin_lock_irqsave(&nbd->tasks_lock, flags);
        nbd->task_recv = current;
+       spin_unlock_irqrestore(&nbd->tasks_lock, flags);
 
        ret = device_create_file(disk_to_dev(nbd->disk), &pid_attr);
        if (ret) {
                dev_err(disk_to_dev(nbd->disk), "device_create_file failed!\n");
+
+               spin_lock_irqsave(&nbd->tasks_lock, flags);
                nbd->task_recv = NULL;
+               spin_unlock_irqrestore(&nbd->tasks_lock, flags);
+
                return ret;
        }
 
@@ -429,7 +439,9 @@ static int nbd_thread_recv(struct nbd_device *nbd)
 
        device_remove_file(disk_to_dev(nbd->disk), &pid_attr);
 
+       spin_lock_irqsave(&nbd->tasks_lock, flags);
        nbd->task_recv = NULL;
+       spin_unlock_irqrestore(&nbd->tasks_lock, flags);
 
        if (signal_pending(current)) {
                siginfo_t info;
@@ -534,8 +546,11 @@ static int nbd_thread_send(void *data)
 {
        struct nbd_device *nbd = data;
        struct request *req;
+       unsigned long flags;
 
+       spin_lock_irqsave(&nbd->tasks_lock, flags);
        nbd->task_send = current;
+       spin_unlock_irqrestore(&nbd->tasks_lock, flags);
 
        set_user_nice(current, MIN_NICE);
        while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) {
@@ -572,7 +587,15 @@ static int nbd_thread_send(void *data)
                nbd_handle_req(nbd, req);
        }
 
+       spin_lock_irqsave(&nbd->tasks_lock, flags);
        nbd->task_send = NULL;
+       spin_unlock_irqrestore(&nbd->tasks_lock, flags);
+
+       /* Clear maybe pending signals */
+       if (signal_pending(current)) {
+               siginfo_t info;
+               dequeue_signal_lock(current, &current->blocked, &info);
+       }
 
        return 0;
 }
@@ -1052,6 +1075,7 @@ static int __init nbd_init(void)
                nbd_dev[i].magic = NBD_MAGIC;
                INIT_LIST_HEAD(&nbd_dev[i].waiting_queue);
                spin_lock_init(&nbd_dev[i].queue_lock);
+               spin_lock_init(&nbd_dev[i].tasks_lock);
                INIT_LIST_HEAD(&nbd_dev[i].queue_head);
                mutex_init(&nbd_dev[i].tx_lock);
                init_timer(&nbd_dev[i].timeout_timer);
index 6f04771f1019798cc2feabf73eff2ddbadc84b81..ccc0c1f93daa45fae2603dd8e36bd2dcc38a8217 100644 (file)
@@ -603,27 +603,31 @@ static void req_completion(struct nvme_queue *nvmeq, void *ctx,
        struct nvme_iod *iod = ctx;
        struct request *req = iod_get_private(iod);
        struct nvme_cmd_info *cmd_rq = blk_mq_rq_to_pdu(req);
-
        u16 status = le16_to_cpup(&cqe->status) >> 1;
+       bool requeue = false;
+       int error = 0;
 
        if (unlikely(status)) {
                if (!(status & NVME_SC_DNR || blk_noretry_request(req))
                    && (jiffies - req->start_time) < req->timeout) {
                        unsigned long flags;
 
+                       requeue = true;
                        blk_mq_requeue_request(req);
                        spin_lock_irqsave(req->q->queue_lock, flags);
                        if (!blk_queue_stopped(req->q))
                                blk_mq_kick_requeue_list(req->q);
                        spin_unlock_irqrestore(req->q->queue_lock, flags);
-                       return;
+                       goto release_iod;
                }
 
                if (req->cmd_type == REQ_TYPE_DRV_PRIV) {
                        if (cmd_rq->ctx == CMD_CTX_CANCELLED)
-                               status = -EINTR;
+                               error = -EINTR;
+                       else
+                               error = status;
                } else {
-                       status = nvme_error_status(status);
+                       error = nvme_error_status(status);
                }
        }
 
@@ -635,8 +639,9 @@ static void req_completion(struct nvme_queue *nvmeq, void *ctx,
        if (cmd_rq->aborted)
                dev_warn(nvmeq->dev->dev,
                        "completing aborted command with status:%04x\n",
-                       status);
+                       error);
 
+release_iod:
        if (iod->nents) {
                dma_unmap_sg(nvmeq->dev->dev, iod->sg, iod->nents,
                        rq_data_dir(req) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
@@ -649,7 +654,8 @@ static void req_completion(struct nvme_queue *nvmeq, void *ctx,
        }
        nvme_free_iod(nvmeq->dev, iod);
 
-       blk_mq_complete_request(req, status);
+       if (likely(!requeue))
+               blk_mq_complete_request(req, error);
 }
 
 /* length is in bytes.  gfp flags indicates whether we may sleep. */
@@ -1804,7 +1810,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
 
        length = (io.nblocks + 1) << ns->lba_shift;
        meta_len = (io.nblocks + 1) * ns->ms;
-       metadata = (void __user *)(unsigned long)io.metadata;
+       metadata = (void __user *)(uintptr_t)io.metadata;
        write = io.opcode & 1;
 
        if (ns->ext) {
@@ -1844,7 +1850,7 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
        c.rw.metadata = cpu_to_le64(meta_dma);
 
        status = __nvme_submit_sync_cmd(ns->queue, &c, NULL,
-                       (void __user *)io.addr, length, NULL, 0);
+                       (void __user *)(uintptr_t)io.addr, length, NULL, 0);
  unmap:
        if (meta) {
                if (status == NVME_SC_SUCCESS && !write) {
@@ -1886,7 +1892,7 @@ static int nvme_user_cmd(struct nvme_dev *dev, struct nvme_ns *ns,
                timeout = msecs_to_jiffies(cmd.timeout_ms);
 
        status = __nvme_submit_sync_cmd(ns ? ns->queue : dev->admin_q, &c,
-                       NULL, (void __user *)cmd.addr, cmd.data_len,
+                       NULL, (void __user *)(uintptr_t)cmd.addr, cmd.data_len,
                        &cmd.result, timeout);
        if (status >= 0) {
                if (put_user(cmd.result, &ucmd->result))
index f5e49b639818bd370357215dbd4cefc4bceb8e20..128e7df5b807222ba2d6f50148cb164919a308f7 100644 (file)
@@ -96,6 +96,8 @@ static int atomic_dec_return_safe(atomic_t *v)
 #define RBD_MINORS_PER_MAJOR           256
 #define RBD_SINGLE_MAJOR_PART_SHIFT    4
 
+#define RBD_MAX_PARENT_CHAIN_LEN       16
+
 #define RBD_SNAP_DEV_NAME_PREFIX       "snap_"
 #define RBD_MAX_SNAP_NAME_LEN  \
                        (NAME_MAX - (sizeof (RBD_SNAP_DEV_NAME_PREFIX) - 1))
@@ -426,7 +428,7 @@ static ssize_t rbd_add_single_major(struct bus_type *bus, const char *buf,
                                    size_t count);
 static ssize_t rbd_remove_single_major(struct bus_type *bus, const char *buf,
                                       size_t count);
-static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping);
+static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth);
 static void rbd_spec_put(struct rbd_spec *spec);
 
 static int rbd_dev_id_to_minor(int dev_id)
@@ -3778,6 +3780,9 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
        blk_queue_max_discard_sectors(q, segment_size / SECTOR_SIZE);
        q->limits.discard_zeroes_data = 1;
 
+       if (!ceph_test_opt(rbd_dev->rbd_client->client, NOCRC))
+               q->backing_dev_info.capabilities |= BDI_CAP_STABLE_WRITES;
+
        disk->queue = q;
 
        q->queuedata = rbd_dev;
@@ -5131,44 +5136,51 @@ out_err:
        return ret;
 }
 
-static int rbd_dev_probe_parent(struct rbd_device *rbd_dev)
+/*
+ * @depth is rbd_dev_image_probe() -> rbd_dev_probe_parent() ->
+ * rbd_dev_image_probe() recursion depth, which means it's also the
+ * length of the already discovered part of the parent chain.
+ */
+static int rbd_dev_probe_parent(struct rbd_device *rbd_dev, int depth)
 {
        struct rbd_device *parent = NULL;
-       struct rbd_spec *parent_spec;
-       struct rbd_client *rbdc;
        int ret;
 
        if (!rbd_dev->parent_spec)
                return 0;
-       /*
-        * We need to pass a reference to the client and the parent
-        * spec when creating the parent rbd_dev.  Images related by
-        * parent/child relationships always share both.
-        */
-       parent_spec = rbd_spec_get(rbd_dev->parent_spec);
-       rbdc = __rbd_get_client(rbd_dev->rbd_client);
 
-       ret = -ENOMEM;
-       parent = rbd_dev_create(rbdc, parent_spec, NULL);
-       if (!parent)
+       if (++depth > RBD_MAX_PARENT_CHAIN_LEN) {
+               pr_info("parent chain is too long (%d)\n", depth);
+               ret = -EINVAL;
                goto out_err;
+       }
 
-       ret = rbd_dev_image_probe(parent, false);
+       parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec,
+                               NULL);
+       if (!parent) {
+               ret = -ENOMEM;
+               goto out_err;
+       }
+
+       /*
+        * Images related by parent/child relationships always share
+        * rbd_client and spec/parent_spec, so bump their refcounts.
+        */
+       __rbd_get_client(rbd_dev->rbd_client);
+       rbd_spec_get(rbd_dev->parent_spec);
+
+       ret = rbd_dev_image_probe(parent, depth);
        if (ret < 0)
                goto out_err;
+
        rbd_dev->parent = parent;
        atomic_set(&rbd_dev->parent_ref, 1);
-
        return 0;
+
 out_err:
-       if (parent) {
-               rbd_dev_unparent(rbd_dev);
+       rbd_dev_unparent(rbd_dev);
+       if (parent)
                rbd_dev_destroy(parent);
-       } else {
-               rbd_put_client(rbdc);
-               rbd_spec_put(parent_spec);
-       }
-
        return ret;
 }
 
@@ -5286,7 +5298,7 @@ static void rbd_dev_image_release(struct rbd_device *rbd_dev)
  * parent), initiate a watch on its header object before using that
  * object to get detailed information about the rbd image.
  */
-static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
+static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
 {
        int ret;
 
@@ -5304,7 +5316,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
        if (ret)
                goto err_out_format;
 
-       if (mapping) {
+       if (!depth) {
                ret = rbd_dev_header_watch_sync(rbd_dev);
                if (ret) {
                        if (ret == -ENOENT)
@@ -5325,7 +5337,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
         * Otherwise this is a parent image, identified by pool, image
         * and snap ids - need to fill in names for those ids.
         */
-       if (mapping)
+       if (!depth)
                ret = rbd_spec_fill_snap_id(rbd_dev);
        else
                ret = rbd_spec_fill_names(rbd_dev);
@@ -5347,12 +5359,12 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
                 * Need to warn users if this image is the one being
                 * mapped and has a parent.
                 */
-               if (mapping && rbd_dev->parent_spec)
+               if (!depth && rbd_dev->parent_spec)
                        rbd_warn(rbd_dev,
                                 "WARNING: kernel layering is EXPERIMENTAL!");
        }
 
-       ret = rbd_dev_probe_parent(rbd_dev);
+       ret = rbd_dev_probe_parent(rbd_dev, depth);
        if (ret)
                goto err_out_probe;
 
@@ -5363,7 +5375,7 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev, bool mapping)
 err_out_probe:
        rbd_dev_unprobe(rbd_dev);
 err_out_watch:
-       if (mapping)
+       if (!depth)
                rbd_dev_header_unwatch_sync(rbd_dev);
 out_header_name:
        kfree(rbd_dev->header_name);
@@ -5426,7 +5438,7 @@ static ssize_t do_rbd_add(struct bus_type *bus,
        spec = NULL;            /* rbd_dev now owns this */
        rbd_opts = NULL;        /* rbd_dev now owns this */
 
-       rc = rbd_dev_image_probe(rbd_dev, true);
+       rc = rbd_dev_image_probe(rbd_dev, 0);
        if (rc < 0)
                goto err_out_rbd_dev;
 
index 611170896b8c94ce1d7494d62116ba1fde574fce..a69c02dadec05684f2a49eefe98033e8ebbc0c3e 100644 (file)
@@ -1956,7 +1956,8 @@ static void blkback_changed(struct xenbus_device *dev,
                        break;
                /* Missed the backend's Closing state -- fallthrough */
        case XenbusStateClosing:
-               blkfront_closing(info);
+               if (info)
+                       blkfront_closing(info);
                break;
        }
 }
index 7d9879e166cf4c4346402cb353ef3cd002483740..7082c7268845639399d9ceab44471937011e1705 100644 (file)
@@ -1184,11 +1184,12 @@ static int arm_ccn_pmu_cpu_notifier(struct notifier_block *nb,
                if (!cpumask_test_and_clear_cpu(cpu, &dt->cpu))
                        break;
                target = cpumask_any_but(cpu_online_mask, cpu);
-               if (target < 0)
+               if (target >= nr_cpu_ids)
                        break;
                perf_pmu_migrate_context(&dt->pmu, cpu, target);
                cpumask_set_cpu(target, &dt->cpu);
-               WARN_ON(irq_set_affinity(ccn->irq, &dt->cpu) != 0);
+               if (ccn->irq)
+                       WARN_ON(irq_set_affinity(ccn->irq, &dt->cpu) != 0);
        default:
                break;
        }
index c0eaf0973bd2bca88e269dbca7f44fd3fcdaf3c7..779b6ff0c7ad4040a680a2155964bd3016363767 100644 (file)
@@ -333,7 +333,8 @@ int clk_add_alias(const char *alias, const char *alias_dev_name,
        if (IS_ERR(r))
                return PTR_ERR(r);
 
-       l = clkdev_create(r, alias, "%s", alias_dev_name);
+       l = clkdev_create(r, alias, alias_dev_name ? "%s" : NULL,
+                         alias_dev_name);
        clk_put(r);
 
        return l ? 0 : -ENODEV;
index 6647fb26ef25ce21dba9bffb87cb31e5abe73d80..0d13e6368b96de2ace3b4373a7aebd20f5cd3826 100644 (file)
@@ -1654,6 +1654,7 @@ struct amdgpu_pm {
        u8                      fan_max_rpm;
        /* dpm */
        bool                    dpm_enabled;
+       bool                    sysfs_initialized;
        struct amdgpu_dpm       dpm;
        const struct firmware   *fw;    /* SMC firmware */
        uint32_t                fw_version;
index dc29ed8145c256c61c6c47da3671664175f4f30d..6c9e0902a41438920ddfcbdde9408b3792b41b0e 100644 (file)
@@ -184,10 +184,6 @@ int amdgpu_crtc_page_flip(struct drm_crtc *crtc,
                goto cleanup;
        }
 
-       fence_get(work->excl);
-       for (i = 0; i < work->shared_count; ++i)
-               fence_get(work->shared[i]);
-
        amdgpu_bo_get_tiling_flags(new_rbo, &tiling_flags);
        amdgpu_bo_unreserve(new_rbo);
 
index efed11509f4a2326cb5c22b68d20cac77c499705..22a8c7d3a3ab03e9dc3fb294c1f0eb818a6a4880 100644 (file)
@@ -294,10 +294,14 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
        struct amdgpu_device *adev = dev_get_drvdata(dev);
        umode_t effective_mode = attr->mode;
 
-       /* Skip limit attributes if DPM is not enabled */
+       /* Skip attributes if DPM is not enabled */
        if (!adev->pm.dpm_enabled &&
            (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr ||
-            attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))
+            attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
                return 0;
 
        /* Skip fan attributes if fan is not present */
@@ -691,6 +695,9 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
 {
        int ret;
 
+       if (adev->pm.sysfs_initialized)
+               return 0;
+
        if (adev->pm.funcs->get_temperature == NULL)
                return 0;
        adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev,
@@ -719,6 +726,8 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
                return ret;
        }
 
+       adev->pm.sysfs_initialized = true;
+
        return 0;
 }
 
index 9745ed3a9aef866443e269022142c52ec3fc3d65..7e9154c7f1dbbb7f9d3eee6791c0e4fcc835ea8d 100644 (file)
@@ -2997,6 +2997,9 @@ static int kv_dpm_late_init(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        int ret;
 
+       if (!amdgpu_dpm)
+               return 0;
+
        /* init the sysfs and debugfs files late */
        ret = amdgpu_pm_sysfs_init(adev);
        if (ret)
index 33d877c65ced6a3c138af9ab47c824038410be0b..8328e7059205d266a456710613628c64b097f787 100644 (file)
@@ -4105,7 +4105,7 @@ drm_property_create_blob(struct drm_device *dev, size_t length,
        struct drm_property_blob *blob;
        int ret;
 
-       if (!length)
+       if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob))
                return ERR_PTR(-EINVAL);
 
        blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
@@ -4454,7 +4454,7 @@ int drm_mode_createblob_ioctl(struct drm_device *dev,
         * not associated with any file_priv. */
        mutex_lock(&dev->mode_config.blob_lock);
        out_resp->blob_id = blob->base.id;
-       list_add_tail(&file_priv->blobs, &blob->head_file);
+       list_add_tail(&blob->head_file, &file_priv->blobs);
        mutex_unlock(&dev->mode_config.blob_lock);
 
        return 0;
index 5bca390d9ae26022df1be85d008ee7107d8aa9b8..809959d56d7826364b540204a16190aaf270f9c4 100644 (file)
@@ -1194,17 +1194,18 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_
 
                list_for_each_entry(port, &mstb->ports, next) {
                        if (port->port_num == port_num) {
-                               if (!port->mstb) {
+                               mstb = port->mstb;
+                               if (!mstb) {
                                        DRM_ERROR("failed to lookup MSTB with lct %d, rad %02x\n", lct, rad[0]);
-                                       return NULL;
+                                       goto out;
                                }
 
-                               mstb = port->mstb;
                                break;
                        }
                }
        }
        kref_get(&mstb->kref);
+out:
        mutex_unlock(&mgr->lock);
        return mstb;
 }
index f6ecbda2c60475297b36b1da6cff0766fb0fe833..674341708033b0aa2900ee0776db9a78424b2028 100644 (file)
@@ -143,7 +143,7 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
 }
 
 /**
- * i915_gem_shrink - Shrink buffer object caches completely
+ * i915_gem_shrink_all - Shrink buffer object caches completely
  * @dev_priv: i915 device
  *
  * This is a simple wraper around i915_gem_shrink() to aggressively shrink all
index 8fd431bcdfd3a33ffb6afda7a1584b44e33d8296..a96b9006a51e5a893eea071d1d638ef3c2cef6fb 100644 (file)
@@ -804,7 +804,10 @@ static const struct drm_i915_gem_object_ops i915_gem_userptr_ops = {
  * Also note, that the object created here is not currently a "first class"
  * object, in that several ioctls are banned. These are the CPU access
  * ioctls: mmap(), pwrite and pread. In practice, you are expected to use
- * direct access via your pointer rather than use those ioctls.
+ * direct access via your pointer rather than use those ioctls. Another
+ * restriction is that we do not allow userptr surfaces to be pinned to the
+ * hardware and so we reject any attempt to create a framebuffer out of a
+ * userptr.
  *
  * If you think this is a good interface to use to pass GPU memory between
  * drivers, please use dma-buf instead. In fact, wherever possible use
index cf418be7d30a52d0e25ac42201b61b0e42f16dbe..b2270d576979bd2acf42b6bec10d48eed947ab57 100644 (file)
@@ -1724,6 +1724,15 @@ static void i9xx_enable_pll(struct intel_crtc *crtc)
                           I915_READ(DPLL(!crtc->pipe)) | DPLL_DVO_2X_MODE);
        }
 
+       /*
+        * Apparently we need to have VGA mode enabled prior to changing
+        * the P1/P2 dividers. Otherwise the DPLL will keep using the old
+        * dividers, even though the register value does change.
+        */
+       I915_WRITE(reg, 0);
+
+       I915_WRITE(reg, dpll);
+
        /* Wait for the clocks to stabilize. */
        POSTING_READ(reg);
        udelay(150);
@@ -14107,6 +14116,11 @@ static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb,
        struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
        struct drm_i915_gem_object *obj = intel_fb->obj;
 
+       if (obj->userptr.mm) {
+               DRM_DEBUG("attempting to use a userptr for a framebuffer, denied\n");
+               return -EINVAL;
+       }
+
        return drm_gem_handle_create(file, &obj->base, handle);
 }
 
@@ -14897,9 +14911,19 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
        /* restore vblank interrupts to correct state */
        drm_crtc_vblank_reset(&crtc->base);
        if (crtc->active) {
+               struct intel_plane *plane;
+
                drm_calc_timestamping_constants(&crtc->base, &crtc->base.hwmode);
                update_scanline_offset(crtc);
                drm_crtc_vblank_on(&crtc->base);
+
+               /* Disable everything but the primary plane */
+               for_each_intel_plane_on_crtc(dev, crtc, plane) {
+                       if (plane->base.type == DRM_PLANE_TYPE_PRIMARY)
+                               continue;
+
+                       plane->disable_plane(&plane->base, &crtc->base);
+               }
        }
 
        /* We need to sanitize the plane -> pipe mapping first because this will
@@ -15067,38 +15091,25 @@ void i915_redisable_vga(struct drm_device *dev)
        i915_redisable_vga_power_on(dev);
 }
 
-static bool primary_get_hw_state(struct intel_crtc *crtc)
+static bool primary_get_hw_state(struct intel_plane *plane)
 {
-       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
 
-       return !!(I915_READ(DSPCNTR(crtc->plane)) & DISPLAY_PLANE_ENABLE);
+       return I915_READ(DSPCNTR(plane->plane)) & DISPLAY_PLANE_ENABLE;
 }
 
-static void readout_plane_state(struct intel_crtc *crtc,
-                               struct intel_crtc_state *crtc_state)
+/* FIXME read out full plane state for all planes */
+static void readout_plane_state(struct intel_crtc *crtc)
 {
-       struct intel_plane *p;
-       struct intel_plane_state *plane_state;
-       bool active = crtc_state->base.active;
-
-       for_each_intel_plane(crtc->base.dev, p) {
-               if (crtc->pipe != p->pipe)
-                       continue;
-
-               plane_state = to_intel_plane_state(p->base.state);
+       struct drm_plane *primary = crtc->base.primary;
+       struct intel_plane_state *plane_state =
+               to_intel_plane_state(primary->state);
 
-               if (p->base.type == DRM_PLANE_TYPE_PRIMARY) {
-                       plane_state->visible = primary_get_hw_state(crtc);
-                       if (plane_state->visible)
-                               crtc->base.state->plane_mask |=
-                                       1 << drm_plane_index(&p->base);
-               } else {
-                       if (active)
-                               p->disable_plane(&p->base, &crtc->base);
+       plane_state->visible =
+               primary_get_hw_state(to_intel_plane(primary));
 
-                       plane_state->visible = false;
-               }
-       }
+       if (plane_state->visible)
+               crtc->base.state->plane_mask |= 1 << drm_plane_index(primary);
 }
 
 static void intel_modeset_readout_hw_state(struct drm_device *dev)
@@ -15121,34 +15132,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                crtc->base.state->active = crtc->active;
                crtc->base.enabled = crtc->active;
 
-               memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
-               if (crtc->base.state->active) {
-                       intel_mode_from_pipe_config(&crtc->base.mode, crtc->config);
-                       intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config);
-                       WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode));
-
-                       /*
-                        * The initial mode needs to be set in order to keep
-                        * the atomic core happy. It wants a valid mode if the
-                        * crtc's enabled, so we do the above call.
-                        *
-                        * At this point some state updated by the connectors
-                        * in their ->detect() callback has not run yet, so
-                        * no recalculation can be done yet.
-                        *
-                        * Even if we could do a recalculation and modeset
-                        * right now it would cause a double modeset if
-                        * fbdev or userspace chooses a different initial mode.
-                        *
-                        * If that happens, someone indicated they wanted a
-                        * mode change, which means it's safe to do a full
-                        * recalculation.
-                        */
-                       crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
-               }
-
-               crtc->base.hwmode = crtc->config->base.adjusted_mode;
-               readout_plane_state(crtc, to_intel_crtc_state(crtc->base.state));
+               readout_plane_state(crtc);
 
                DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
                              crtc->base.base.id,
@@ -15207,6 +15191,36 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
                              connector->base.name,
                              connector->base.encoder ? "enabled" : "disabled");
        }
+
+       for_each_intel_crtc(dev, crtc) {
+               crtc->base.hwmode = crtc->config->base.adjusted_mode;
+
+               memset(&crtc->base.mode, 0, sizeof(crtc->base.mode));
+               if (crtc->base.state->active) {
+                       intel_mode_from_pipe_config(&crtc->base.mode, crtc->config);
+                       intel_mode_from_pipe_config(&crtc->base.state->adjusted_mode, crtc->config);
+                       WARN_ON(drm_atomic_set_mode_for_crtc(crtc->base.state, &crtc->base.mode));
+
+                       /*
+                        * The initial mode needs to be set in order to keep
+                        * the atomic core happy. It wants a valid mode if the
+                        * crtc's enabled, so we do the above call.
+                        *
+                        * At this point some state updated by the connectors
+                        * in their ->detect() callback has not run yet, so
+                        * no recalculation can be done yet.
+                        *
+                        * Even if we could do a recalculation and modeset
+                        * right now it would cause a double modeset if
+                        * fbdev or userspace chooses a different initial mode.
+                        *
+                        * If that happens, someone indicated they wanted a
+                        * mode change, which means it's safe to do a full
+                        * recalculation.
+                        */
+                       crtc->base.state->mode.private_flags = I915_MODE_FLAG_INHERITED;
+               }
+       }
 }
 
 /* Scan out the current hw modeset state,
index 7412caedcf7f98a2a5e494c41e2bad97f34d4e34..29dd4488dc49856b6518ba5fce760cbd4710a1e8 100644 (file)
@@ -1659,6 +1659,7 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request,
        if (flush_domains) {
                flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
                flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+               flags |= PIPE_CONTROL_FLUSH_ENABLE;
        }
 
        if (invalidate_domains) {
index 6e6b8db996ef2450c615a71ef10b7ffcbbc62479..61b451fbd09e6ec9de8a42b20a1bb11b6438496f 100644 (file)
@@ -347,6 +347,7 @@ gen7_render_ring_flush(struct drm_i915_gem_request *req,
        if (flush_domains) {
                flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
                flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+               flags |= PIPE_CONTROL_FLUSH_ENABLE;
        }
        if (invalidate_domains) {
                flags |= PIPE_CONTROL_TLB_INVALIDATE;
@@ -418,6 +419,7 @@ gen8_render_ring_flush(struct drm_i915_gem_request *req,
        if (flush_domains) {
                flags |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH;
                flags |= PIPE_CONTROL_DEPTH_CACHE_FLUSH;
+               flags |= PIPE_CONTROL_FLUSH_ENABLE;
        }
        if (invalidate_domains) {
                flags |= PIPE_CONTROL_TLB_INVALIDATE;
index 2c9981512d27b7702f6f196f64b54276acd8b86e..41be584147b936a921d0c6bdd4e5fe0b4251c70c 100644 (file)
@@ -227,11 +227,12 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
        struct nouveau_bo *nvbo = nouveau_gem_object(gem);
        struct nvkm_vma *vma;
 
-       if (nvbo->bo.mem.mem_type == TTM_PL_TT)
+       if (is_power_of_2(nvbo->valid_domains))
+               rep->domain = nvbo->valid_domains;
+       else if (nvbo->bo.mem.mem_type == TTM_PL_TT)
                rep->domain = NOUVEAU_GEM_DOMAIN_GART;
        else
                rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
-
        rep->offset = nvbo->bo.offset;
        if (cli->vm) {
                vma = nouveau_bo_vma_find(nvbo, cli->vm);
index 65adb9c723772d9f0011573d320182823b18d37a..bb292143997ee8ccce3e6e6898edba2a5eeb12b6 100644 (file)
@@ -237,6 +237,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
        backlight_update_status(bd);
 
        DRM_INFO("radeon atom DIG backlight initialized\n");
+       rdev->mode_info.bl_encoder = radeon_encoder;
 
        return;
 
@@ -1624,9 +1625,14 @@ radeon_atom_encoder_dpms_avivo(struct drm_encoder *encoder, int mode)
                } else
                        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
                if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
-                       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+                       if (rdev->mode_info.bl_encoder) {
+                               struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
 
-                       atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+                               atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+                       } else {
+                               args.ucAction = ATOM_LCD_BLON;
+                               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+                       }
                }
                break;
        case DRM_MODE_DPMS_STANDBY:
@@ -1706,8 +1712,13 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                        if (ASIC_IS_DCE4(rdev))
                                atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
                }
-               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
-                       atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+               if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
+                       if (rdev->mode_info.bl_encoder)
+                               atombios_set_backlight_level(radeon_encoder, dig->backlight_level);
+                       else
+                               atombios_dig_transmitter_setup(encoder,
+                                                              ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+               }
                if (ext_encoder)
                        atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
                break;
index f03b7eb152336d1f799ab33d1d195c1fba40b360..b6cbd816537e7e69bc920482961cdb47b6dfd68d 100644 (file)
@@ -1658,6 +1658,7 @@ struct radeon_pm {
        u8                      fan_max_rpm;
        /* dpm */
        bool                    dpm_enabled;
+       bool                    sysfs_initialized;
        struct radeon_dpm       dpm;
 };
 
index ef99917f000d96a7dcf3fc88f089bdf08e0afc28..c6ee80216cf4a71f510bf239fc4fdf6f67235f48 100644 (file)
@@ -194,7 +194,6 @@ static void radeon_encoder_add_backlight(struct radeon_encoder *radeon_encoder,
                        radeon_atom_backlight_init(radeon_encoder, connector);
                else
                        radeon_legacy_backlight_init(radeon_encoder, connector);
-               rdev->mode_info.bl_encoder = radeon_encoder;
        }
 }
 
index 45715307db7177a9af7393a697d255c8ed277344..30de43366eae806d0afd45192ce9da032c08490c 100644 (file)
@@ -441,6 +441,7 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
        backlight_update_status(bd);
 
        DRM_INFO("radeon legacy LVDS backlight initialized\n");
+       rdev->mode_info.bl_encoder = radeon_encoder;
 
        return;
 
index 44489cce7458402cf8a48a6176e3ed4625b603d5..5feee3b4c55741011ae3501f501f72df0e1311ac 100644 (file)
@@ -717,10 +717,14 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
        struct radeon_device *rdev = dev_get_drvdata(dev);
        umode_t effective_mode = attr->mode;
 
-       /* Skip limit attributes if DPM is not enabled */
+       /* Skip attributes if DPM is not enabled */
        if (rdev->pm.pm_method != PM_METHOD_DPM &&
            (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr ||
-            attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr))
+            attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
+            attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
                return 0;
 
        /* Skip fan attributes if fan is not present */
@@ -1524,19 +1528,23 @@ int radeon_pm_late_init(struct radeon_device *rdev)
 
        if (rdev->pm.pm_method == PM_METHOD_DPM) {
                if (rdev->pm.dpm_enabled) {
-                       ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
-                       if (ret)
-                               DRM_ERROR("failed to create device file for dpm state\n");
-                       ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
-                       if (ret)
-                               DRM_ERROR("failed to create device file for dpm state\n");
-                       /* XXX: these are noops for dpm but are here for backwards compat */
-                       ret = device_create_file(rdev->dev, &dev_attr_power_profile);
-                       if (ret)
-                               DRM_ERROR("failed to create device file for power profile\n");
-                       ret = device_create_file(rdev->dev, &dev_attr_power_method);
-                       if (ret)
-                               DRM_ERROR("failed to create device file for power method\n");
+                       if (!rdev->pm.sysfs_initialized) {
+                               ret = device_create_file(rdev->dev, &dev_attr_power_dpm_state);
+                               if (ret)
+                                       DRM_ERROR("failed to create device file for dpm state\n");
+                               ret = device_create_file(rdev->dev, &dev_attr_power_dpm_force_performance_level);
+                               if (ret)
+                                       DRM_ERROR("failed to create device file for dpm state\n");
+                               /* XXX: these are noops for dpm but are here for backwards compat */
+                               ret = device_create_file(rdev->dev, &dev_attr_power_profile);
+                               if (ret)
+                                       DRM_ERROR("failed to create device file for power profile\n");
+                               ret = device_create_file(rdev->dev, &dev_attr_power_method);
+                               if (ret)
+                                       DRM_ERROR("failed to create device file for power method\n");
+                               if (!ret)
+                                       rdev->pm.sysfs_initialized = true;
+                       }
 
                        mutex_lock(&rdev->pm.mutex);
                        ret = radeon_dpm_late_enable(rdev);
@@ -1552,7 +1560,8 @@ int radeon_pm_late_init(struct radeon_device *rdev)
                        }
                }
        } else {
-               if (rdev->pm.num_power_states > 1) {
+               if ((rdev->pm.num_power_states > 1) &&
+                   (!rdev->pm.sysfs_initialized)) {
                        /* where's the best place to put these? */
                        ret = device_create_file(rdev->dev, &dev_attr_power_profile);
                        if (ret)
@@ -1560,6 +1569,8 @@ int radeon_pm_late_init(struct radeon_device *rdev)
                        ret = device_create_file(rdev->dev, &dev_attr_power_method);
                        if (ret)
                                DRM_ERROR("failed to create device file for power method\n");
+                       if (!ret)
+                               rdev->pm.sysfs_initialized = true;
                }
        }
        return ret;
index 8a76821177a6c0c1a3cc9659b4f119943d48b3ce..6377e8151000f5401309133b635150acf128c2ad 100644 (file)
@@ -415,16 +415,16 @@ static void vmw_cmdbuf_ctx_process(struct vmw_cmdbuf_man *man,
  *
  * Calls vmw_cmdbuf_ctx_process() on all contexts. If any context has
  * command buffers left that are not submitted to hardware, Make sure
- * IRQ handling is turned on. Otherwise, make sure it's turned off. This
- * function may return -EAGAIN to indicate it should be rerun due to
- * possibly missed IRQs if IRQs has just been turned on.
+ * IRQ handling is turned on. Otherwise, make sure it's turned off.
  */
-static int vmw_cmdbuf_man_process(struct vmw_cmdbuf_man *man)
+static void vmw_cmdbuf_man_process(struct vmw_cmdbuf_man *man)
 {
-       int notempty = 0;
+       int notempty;
        struct vmw_cmdbuf_context *ctx;
        int i;
 
+retry:
+       notempty = 0;
        for_each_cmdbuf_ctx(man, i, ctx)
                vmw_cmdbuf_ctx_process(man, ctx, &notempty);
 
@@ -440,10 +440,8 @@ static int vmw_cmdbuf_man_process(struct vmw_cmdbuf_man *man)
                man->irq_on = true;
 
                /* Rerun in case we just missed an irq. */
-               return -EAGAIN;
+               goto retry;
        }
-
-       return 0;
 }
 
 /**
@@ -468,8 +466,7 @@ static void vmw_cmdbuf_ctx_add(struct vmw_cmdbuf_man *man,
        header->cb_context = cb_context;
        list_add_tail(&header->list, &man->ctx[cb_context].submitted);
 
-       if (vmw_cmdbuf_man_process(man) == -EAGAIN)
-               vmw_cmdbuf_man_process(man);
+       vmw_cmdbuf_man_process(man);
 }
 
 /**
@@ -488,8 +485,7 @@ static void vmw_cmdbuf_man_tasklet(unsigned long data)
        struct vmw_cmdbuf_man *man = (struct vmw_cmdbuf_man *) data;
 
        spin_lock(&man->lock);
-       if (vmw_cmdbuf_man_process(man) == -EAGAIN)
-               (void) vmw_cmdbuf_man_process(man);
+       vmw_cmdbuf_man_process(man);
        spin_unlock(&man->lock);
 }
 
@@ -507,6 +503,7 @@ static void vmw_cmdbuf_work_func(struct work_struct *work)
        struct vmw_cmdbuf_man *man =
                container_of(work, struct vmw_cmdbuf_man, work);
        struct vmw_cmdbuf_header *entry, *next;
+       uint32_t dummy;
        bool restart = false;
 
        spin_lock_bh(&man->lock);
@@ -523,6 +520,8 @@ static void vmw_cmdbuf_work_func(struct work_struct *work)
        if (restart && vmw_cmdbuf_startstop(man, true))
                DRM_ERROR("Failed restarting command buffer context 0.\n");
 
+       /* Send a new fence in case one was removed */
+       vmw_fifo_send_fence(man->dev_priv, &dummy);
 }
 
 /**
@@ -682,7 +681,7 @@ static bool vmw_cmdbuf_try_alloc(struct vmw_cmdbuf_man *man,
                                         DRM_MM_SEARCH_DEFAULT,
                                         DRM_MM_CREATE_DEFAULT);
        if (ret) {
-               (void) vmw_cmdbuf_man_process(man);
+               vmw_cmdbuf_man_process(man);
                ret = drm_mm_insert_node_generic(&man->mm, info->node,
                                                 info->page_size, 0, 0,
                                                 DRM_MM_SEARCH_DEFAULT,
@@ -1168,7 +1167,14 @@ int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man,
        drm_mm_init(&man->mm, 0, size >> PAGE_SHIFT);
 
        man->has_pool = true;
-       man->default_size = default_size;
+
+       /*
+        * For now, set the default size to VMW_CMDBUF_INLINE_SIZE to
+        * prevent deadlocks from happening when vmw_cmdbuf_space_pool()
+        * needs to wait for space and we block on further command
+        * submissions to be able to free up space.
+        */
+       man->default_size = VMW_CMDBUF_INLINE_SIZE;
        DRM_INFO("Using command buffers with %s pool.\n",
                 (man->using_mob) ? "MOB" : "DMA");
 
index 30059c1df2a3b57ea559fc984b559c79e2f06ce6..5801227b97ab089022f90608f6fc425ebd13cd87 100644 (file)
@@ -669,8 +669,6 @@ mv64xxx_i2c_can_offload(struct mv64xxx_i2c_data *drv_data)
        struct i2c_msg *msgs = drv_data->msgs;
        int num = drv_data->num_msgs;
 
-       return false;
-
        if (!drv_data->offload_enabled)
                return false;
 
index e814a36d9b78f26436cd8cf1745dd2aaa3b36db8..6f8b446be5b0e5787deede7f675044332d72f8cb 100644 (file)
@@ -600,7 +600,7 @@ static int i2c_pnx_controller_suspend(struct device *dev)
 {
        struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev);
 
-       clk_disable(alg_data->clk);
+       clk_disable_unprepare(alg_data->clk);
 
        return 0;
 }
@@ -609,7 +609,7 @@ static int i2c_pnx_controller_resume(struct device *dev)
 {
        struct i2c_pnx_algo_data *alg_data = dev_get_drvdata(dev);
 
-       return clk_enable(alg_data->clk);
+       return clk_prepare_enable(alg_data->clk);
 }
 
 static SIMPLE_DEV_PM_OPS(i2c_pnx_pm,
@@ -672,7 +672,7 @@ static int i2c_pnx_probe(struct platform_device *pdev)
        if (IS_ERR(alg_data->ioaddr))
                return PTR_ERR(alg_data->ioaddr);
 
-       ret = clk_enable(alg_data->clk);
+       ret = clk_prepare_enable(alg_data->clk);
        if (ret)
                return ret;
 
@@ -726,7 +726,7 @@ static int i2c_pnx_probe(struct platform_device *pdev)
        return 0;
 
 out_clock:
-       clk_disable(alg_data->clk);
+       clk_disable_unprepare(alg_data->clk);
        return ret;
 }
 
@@ -735,7 +735,7 @@ static int i2c_pnx_remove(struct platform_device *pdev)
        struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
 
        i2c_del_adapter(&alg_data->adapter);
-       clk_disable(alg_data->clk);
+       clk_disable_unprepare(alg_data->clk);
 
        return 0;
 }
index ff30f880688019fa099d79d7fce3f53b28cfb828..fb93111104249bcc93d390e7492c96f4c211ac27 100644 (file)
 #define ST_ACCEL_4_BDU_MASK                    0x40
 #define ST_ACCEL_4_DRDY_IRQ_ADDR               0x21
 #define ST_ACCEL_4_DRDY_IRQ_INT1_MASK          0x04
-#define ST_ACCEL_4_IG1_EN_ADDR                 0x21
-#define ST_ACCEL_4_IG1_EN_MASK                 0x08
 #define ST_ACCEL_4_MULTIREAD_BIT               true
 
 /* CUSTOM VALUES FOR SENSOR 5 */
@@ -489,10 +487,6 @@ static const struct st_sensor_settings st_accel_sensors_settings[] = {
                .drdy_irq = {
                        .addr = ST_ACCEL_4_DRDY_IRQ_ADDR,
                        .mask_int1 = ST_ACCEL_4_DRDY_IRQ_INT1_MASK,
-                       .ig1 = {
-                               .en_addr = ST_ACCEL_4_IG1_EN_ADDR,
-                               .en_mask = ST_ACCEL_4_IG1_EN_MASK,
-                       },
                },
                .multi_read_bit = ST_ACCEL_4_MULTIREAD_BIT,
                .bootime = 2, /* guess */
index ebe415f1064000c95c88f5d20da48a7f52f71d84..0c74869a540ad390a0f995a702ee953cf53e0669 100644 (file)
 #include <linux/types.h>
 #include <linux/gfp.h>
 #include <linux/err.h>
+#include <linux/regulator/consumer.h>
 
 #include <linux/iio/iio.h>
 
+#define TWL4030_USB_SEL_MADC_MCPC      (1<<3)
+#define TWL4030_USB_CARKIT_ANA_CTRL    0xBB
+
 /**
  * struct twl4030_madc_data - a container for madc info
  * @dev:               Pointer to device structure for madc
  * @lock:              Mutex protecting this data structure
+ * @regulator:         Pointer to bias regulator for madc
  * @requests:          Array of request struct corresponding to SW1, SW2 and RT
  * @use_second_irq:    IRQ selection (main or co-processor)
  * @imr:               Interrupt mask register of MADC
@@ -60,6 +65,7 @@
 struct twl4030_madc_data {
        struct device *dev;
        struct mutex lock;      /* mutex protecting this data structure */
+       struct regulator *usb3v1;
        struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
        bool use_second_irq;
        u8 imr;
@@ -841,6 +847,32 @@ static int twl4030_madc_probe(struct platform_device *pdev)
        }
        twl4030_madc = madc;
 
+       /* Configure MADC[3:6] */
+       ret = twl_i2c_read_u8(TWL_MODULE_USB, &regval,
+                       TWL4030_USB_CARKIT_ANA_CTRL);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to read reg CARKIT_ANA_CTRL  0x%X\n",
+                               TWL4030_USB_CARKIT_ANA_CTRL);
+               goto err_i2c;
+       }
+       regval |= TWL4030_USB_SEL_MADC_MCPC;
+       ret = twl_i2c_write_u8(TWL_MODULE_USB, regval,
+                                TWL4030_USB_CARKIT_ANA_CTRL);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to write reg CARKIT_ANA_CTRL 0x%X\n",
+                               TWL4030_USB_CARKIT_ANA_CTRL);
+               goto err_i2c;
+       }
+
+       /* Enable 3v1 bias regulator for MADC[3:6] */
+       madc->usb3v1 = devm_regulator_get(madc->dev, "vusb3v1");
+       if (IS_ERR(madc->usb3v1))
+               return -ENODEV;
+
+       ret = regulator_enable(madc->usb3v1);
+       if (ret)
+               dev_err(madc->dev, "could not enable 3v1 bias regulator\n");
+
        ret = iio_device_register(iio_dev);
        if (ret) {
                dev_err(&pdev->dev, "could not register iio device\n");
@@ -866,6 +898,8 @@ static int twl4030_madc_remove(struct platform_device *pdev)
        twl4030_madc_set_current_generator(madc, 0, 0);
        twl4030_madc_set_power(madc, 0);
 
+       regulator_disable(madc->usb3v1);
+
        return 0;
 }
 
index 8f66c67ff0df09380dc7c486dce44d92efac1f18..87471ef371986c11f59e6761e7566ebec78cc1cd 100644 (file)
@@ -508,12 +508,12 @@ void ib_cache_gid_set_default_gid(struct ib_device *ib_dev, u8 port,
        memset(&gid_attr, 0, sizeof(gid_attr));
        gid_attr.ndev = ndev;
 
+       mutex_lock(&table->lock);
        ix = find_gid(table, NULL, NULL, true, GID_ATTR_FIND_MASK_DEFAULT);
 
        /* Coudn't find default GID location */
        WARN_ON(ix < 0);
 
-       mutex_lock(&table->lock);
        if (!__ib_cache_gid_get(ib_dev, port, ix,
                                &current_gid, &current_gid_attr) &&
            mode == IB_CACHE_GID_DEFAULT_MODE_SET &&
index ea4db9c1d44fba56ea5798649f3744c78b148e87..4f918b929eca955532cd5dc0541bc842272a0a3b 100644 (file)
@@ -835,6 +835,11 @@ retest:
        case IB_CM_SIDR_REQ_RCVD:
                spin_unlock_irq(&cm_id_priv->lock);
                cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
+               spin_lock_irq(&cm.lock);
+               if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node))
+                       rb_erase(&cm_id_priv->sidr_id_node,
+                                &cm.remote_sidr_table);
+               spin_unlock_irq(&cm.lock);
                break;
        case IB_CM_REQ_SENT:
        case IB_CM_MRA_REQ_RCVD:
@@ -3172,7 +3177,10 @@ int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
        spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 
        spin_lock_irqsave(&cm.lock, flags);
-       rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
+       if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) {
+               rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
+               RB_CLEAR_NODE(&cm_id_priv->sidr_id_node);
+       }
        spin_unlock_irqrestore(&cm.lock, flags);
        return 0;
 
index 59a2dafc8c574df13b5d186f9b0987c06c8e58c6..36b12d560e17e5a862a2e37d1f56875b46425f4b 100644 (file)
@@ -1067,14 +1067,14 @@ static int cma_save_req_info(const struct ib_cm_event *ib_event,
                       sizeof(req->local_gid));
                req->has_gid    = true;
                req->service_id = req_param->primary_path->service_id;
-               req->pkey       = req_param->bth_pkey;
+               req->pkey       = be16_to_cpu(req_param->primary_path->pkey);
                break;
        case IB_CM_SIDR_REQ_RECEIVED:
                req->device     = sidr_param->listen_id->device;
                req->port       = sidr_param->port;
                req->has_gid    = false;
                req->service_id = sidr_param->service_id;
-               req->pkey       = sidr_param->bth_pkey;
+               req->pkey       = sidr_param->pkey;
                break;
        default:
                return -EINVAL;
@@ -1324,7 +1324,7 @@ static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id,
        bind_list = cma_ps_find(rdma_ps_from_service_id(req.service_id),
                                cma_port_from_service_id(req.service_id));
        id_priv = cma_find_listener(bind_list, cm_id, ib_event, &req, *net_dev);
-       if (IS_ERR(id_priv)) {
+       if (IS_ERR(id_priv) && *net_dev) {
                dev_put(*net_dev);
                *net_dev = NULL;
        }
index 6b24cba1e474df33002186275fb2a7ca81c83717..178f98482e13e217c16d447978a855a900808bc0 100644 (file)
@@ -250,25 +250,44 @@ static void enum_netdev_ipv4_ips(struct ib_device *ib_dev,
                                 u8 port, struct net_device *ndev)
 {
        struct in_device *in_dev;
+       struct sin_list {
+               struct list_head        list;
+               struct sockaddr_in      ip;
+       };
+       struct sin_list *sin_iter;
+       struct sin_list *sin_temp;
 
+       LIST_HEAD(sin_list);
        if (ndev->reg_state >= NETREG_UNREGISTERING)
                return;
 
-       in_dev = in_dev_get(ndev);
-       if (!in_dev)
+       rcu_read_lock();
+       in_dev = __in_dev_get_rcu(ndev);
+       if (!in_dev) {
+               rcu_read_unlock();
                return;
+       }
 
        for_ifa(in_dev) {
-               struct sockaddr_in ip;
+               struct sin_list *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 
-               ip.sin_family = AF_INET;
-               ip.sin_addr.s_addr = ifa->ifa_address;
-               update_gid_ip(GID_ADD, ib_dev, port, ndev,
-                             (struct sockaddr *)&ip);
+               if (!entry) {
+                       pr_warn("roce_gid_mgmt: couldn't allocate entry for IPv4 update\n");
+                       continue;
+               }
+               entry->ip.sin_family = AF_INET;
+               entry->ip.sin_addr.s_addr = ifa->ifa_address;
+               list_add_tail(&entry->list, &sin_list);
        }
        endfor_ifa(in_dev);
+       rcu_read_unlock();
 
-       in_dev_put(in_dev);
+       list_for_each_entry_safe(sin_iter, sin_temp, &sin_list, list) {
+               update_gid_ip(GID_ADD, ib_dev, port, ndev,
+                             (struct sockaddr *)&sin_iter->ip);
+               list_del(&sin_iter->list);
+               kfree(sin_iter);
+       }
 }
 
 static void enum_netdev_ipv6_ips(struct ib_device *ib_dev,
index a53fc9b01c69957cb6d45433c4a34a0a69a5c367..30467d10df91b170e40657864354356153545e76 100644 (file)
@@ -1624,11 +1624,16 @@ static int ucma_open(struct inode *inode, struct file *filp)
        if (!file)
                return -ENOMEM;
 
+       file->close_wq = create_singlethread_workqueue("ucma_close_id");
+       if (!file->close_wq) {
+               kfree(file);
+               return -ENOMEM;
+       }
+
        INIT_LIST_HEAD(&file->event_list);
        INIT_LIST_HEAD(&file->ctx_list);
        init_waitqueue_head(&file->poll_wait);
        mutex_init(&file->mut);
-       file->close_wq = create_singlethread_workqueue("ucma_close_id");
 
        filp->private_data = file;
        file->filp = filp;
index 4d246861d692b810f3074aa7917cda86893ac6c2..41e6cb501e6a1d5b07801463460fe4ebbaace887 100644 (file)
@@ -100,7 +100,7 @@ static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
 #define ALPS_FOUR_BUTTONS      0x40    /* 4 direction button present */
 #define ALPS_PS2_INTERLEAVED   0x80    /* 3-byte PS/2 packet interleaved with
                                           6-byte ALPS packet */
-#define ALPS_DELL              0x100   /* device is a Dell laptop */
+#define ALPS_STICK_BITS                0x100   /* separate stick button bits */
 #define ALPS_BUTTONPAD         0x200   /* device is a clickpad */
 
 static const struct alps_model_info alps_model_data[] = {
@@ -159,6 +159,43 @@ static const struct alps_protocol_info alps_v8_protocol_data = {
        ALPS_PROTO_V8, 0x18, 0x18, 0
 };
 
+/*
+ * Some v2 models report the stick buttons in separate bits
+ */
+static const struct dmi_system_id alps_dmi_has_separate_stick_buttons[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+       {
+               /* Extrapolated from other entries */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D420"),
+               },
+       },
+       {
+               /* Reported-by: Hans de Bruin <jmdebruin@xmsnet.nl> */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D430"),
+               },
+       },
+       {
+               /* Reported-by: Hans de Goede <hdegoede@redhat.com> */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D620"),
+               },
+       },
+       {
+               /* Extrapolated from other entries */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D630"),
+               },
+       },
+#endif
+       { }
+};
+
 static void alps_set_abs_params_st(struct alps_data *priv,
                                   struct input_dev *dev1);
 static void alps_set_abs_params_semi_mt(struct alps_data *priv,
@@ -253,9 +290,8 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse)
                return;
        }
 
-       /* Dell non interleaved V2 dualpoint has separate stick button bits */
-       if (priv->proto_version == ALPS_PROTO_V2 &&
-           priv->flags == (ALPS_DELL | ALPS_PASS | ALPS_DUALPOINT)) {
+       /* Some models have separate stick button bits */
+       if (priv->flags & ALPS_STICK_BITS) {
                left |= packet[0] & 1;
                right |= packet[0] & 2;
                middle |= packet[0] & 4;
@@ -2552,8 +2588,6 @@ static int alps_set_protocol(struct psmouse *psmouse,
        priv->byte0 = protocol->byte0;
        priv->mask0 = protocol->mask0;
        priv->flags = protocol->flags;
-       if (dmi_name_in_vendors("Dell"))
-               priv->flags |= ALPS_DELL;
 
        priv->x_max = 2000;
        priv->y_max = 1400;
@@ -2568,6 +2602,8 @@ static int alps_set_protocol(struct psmouse *psmouse,
                priv->set_abs_params = alps_set_abs_params_st;
                priv->x_max = 1023;
                priv->y_max = 767;
+               if (dmi_check_system(alps_dmi_has_separate_stick_buttons))
+                       priv->flags |= ALPS_STICK_BITS;
                break;
 
        case ALPS_PROTO_V3:
index 600dcceff5426aaf4f6fc7b20ce966960bf0aa92..deb14c12ae8b19a84c5ba8e0074f4bac43260ecc 100644 (file)
@@ -1006,6 +1006,7 @@ config TOUCHSCREEN_SUN4I
 config TOUCHSCREEN_SUR40
        tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
        depends on USB && MEDIA_USB_SUPPORT && HAS_DMA
+       depends on VIDEO_V4L2
        select INPUT_POLLDEV
        select VIDEOBUF2_DMA_SG
        help
index 24d704cd9f882fb8517d036b00d5f64d46787993..7fbb3b0c857150170a293981e1e7940d70478c3f 100644 (file)
@@ -139,14 +139,14 @@ static void lpc32xx_stop_tsc(struct lpc32xx_tsc *tsc)
                   tsc_readl(tsc, LPC32XX_TSC_CON) &
                             ~LPC32XX_TSC_ADCCON_AUTO_EN);
 
-       clk_disable(tsc->clk);
+       clk_disable_unprepare(tsc->clk);
 }
 
 static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc)
 {
        u32 tmp;
 
-       clk_enable(tsc->clk);
+       clk_prepare_enable(tsc->clk);
 
        tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP;
 
index 08d2775887f7add00e44858cc6bf4a5eece6e260..532e2a211fe1cf9b3d7ff71d36cbcfde49bd29df 100644 (file)
@@ -1974,8 +1974,8 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
 static void clear_dte_entry(u16 devid)
 {
        /* remove entry from the device table seen by the hardware */
-       amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV;
-       amd_iommu_dev_table[devid].data[1] = 0;
+       amd_iommu_dev_table[devid].data[0]  = IOMMU_PTE_P | IOMMU_PTE_TV;
+       amd_iommu_dev_table[devid].data[1] &= DTE_FLAG_MASK;
 
        amd_iommu_apply_erratum_63(devid);
 }
index f65908841be0184db61f049bc8e2b5a622ca2fbe..c9b64722f62309d76e56ad52c5a3691737ffd6ac 100644 (file)
 #define IOMMU_PTE_IR (1ULL << 61)
 #define IOMMU_PTE_IW (1ULL << 62)
 
+#define DTE_FLAG_MASK  (0x3ffULL << 32)
 #define DTE_FLAG_IOTLB (0x01UL << 32)
 #define DTE_FLAG_GV    (0x01ULL << 55)
 #define DTE_GLX_SHIFT  (56)
index 1131664b918b0a574c7cc654a6a3cd04107f8e81..d21d4edf7236abac49072c086290b76d2ae201b5 100644 (file)
@@ -516,6 +516,13 @@ static void do_fault(struct work_struct *work)
                goto out;
        }
 
+       if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) {
+               /* handle_mm_fault would BUG_ON() */
+               up_read(&mm->mmap_sem);
+               handle_fault_error(fault);
+               goto out;
+       }
+
        ret = handle_mm_fault(mm, vma, address, write);
        if (ret & VM_FAULT_ERROR) {
                /* failed to service fault */
index 35365f046923db7df50f43f318310711e7fd5e31..d65cf42399e8e5aa0f856a1ab6869c041adc0c48 100644 (file)
@@ -2115,15 +2115,19 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
                                return -ENOMEM;
                        /* It is large page*/
                        if (largepage_lvl > 1) {
+                               unsigned long nr_superpages, end_pfn;
+
                                pteval |= DMA_PTE_LARGE_PAGE;
                                lvl_pages = lvl_to_nr_pages(largepage_lvl);
+
+                               nr_superpages = sg_res / lvl_pages;
+                               end_pfn = iov_pfn + nr_superpages * lvl_pages - 1;
+
                                /*
                                 * Ensure that old small page tables are
-                                * removed to make room for superpage,
-                                * if they exist.
+                                * removed to make room for superpage(s).
                                 */
-                               dma_pte_free_pagetable(domain, iov_pfn,
-                                                      iov_pfn + lvl_pages - 1);
+                               dma_pte_free_pagetable(domain, iov_pfn, end_pfn);
                        } else {
                                pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
                        }
index 18accb0a79cc51dea2d1851fc9a27891e8d79d6f..c53a53f6efb6a136ec09075996bd89081e50e536 100644 (file)
@@ -1247,7 +1247,7 @@ static void
 l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
 {
        struct PStack *st = fi->userdata;
-       struct sk_buff *skb;
+       struct sk_buff *skb, *nskb;
        struct Layer2 *l2 = &st->l2;
        u_char header[MAX_HEADER_LEN];
        int i, hdr_space_needed;
@@ -1262,14 +1262,10 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
                return;
 
        hdr_space_needed = l2headersize(l2, 0);
-       if (hdr_space_needed > skb_headroom(skb)) {
-               struct sk_buff *orig_skb = skb;
-
-               skb = skb_realloc_headroom(skb, hdr_space_needed);
-               if (!skb) {
-                       dev_kfree_skb(orig_skb);
-                       return;
-               }
+       nskb = skb_realloc_headroom(skb, hdr_space_needed);
+       if (!nskb) {
+               skb_queue_head(&l2->i_queue, skb);
+               return;
        }
        spin_lock_irqsave(&l2->lock, flags);
        if (test_bit(FLG_MOD128, &l2->flag))
@@ -1282,7 +1278,7 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
                       p1);
                dev_kfree_skb(l2->windowar[p1]);
        }
-       l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC);
+       l2->windowar[p1] = skb;
 
        i = sethdraddr(&st->l2, header, CMD);
 
@@ -1295,8 +1291,8 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
                l2->vs = (l2->vs + 1) % 8;
        }
        spin_unlock_irqrestore(&l2->lock, flags);
-       memcpy(skb_push(skb, i), header, i);
-       st->l2.l2l1(st, PH_PULL | INDICATION, skb);
+       memcpy(skb_push(nskb, i), header, i);
+       st->l2.l2l1(st, PH_PULL | INDICATION, nskb);
        test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
        if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) {
                FsmDelTimer(&st->l2.t203, 13);
index 949cabb88f1c113c9606d26ff72627f6cf9db108..5eb380a2590394ba087e2f160281e1902112910f 100644 (file)
@@ -1476,7 +1476,7 @@ static void
 l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
 {
        struct layer2   *l2 = fi->userdata;
-       struct sk_buff  *skb, *nskb, *oskb;
+       struct sk_buff  *skb, *nskb;
        u_char          header[MAX_L2HEADER_LEN];
        u_int           i, p1;
 
@@ -1486,48 +1486,34 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
        skb = skb_dequeue(&l2->i_queue);
        if (!skb)
                return;
-
-       if (test_bit(FLG_MOD128, &l2->flag))
-               p1 = (l2->vs - l2->va) % 128;
-       else
-               p1 = (l2->vs - l2->va) % 8;
-       p1 = (p1 + l2->sow) % l2->window;
-       if (l2->windowar[p1]) {
-               printk(KERN_WARNING "%s: l2 try overwrite ack queue entry %d\n",
-                      mISDNDevName4ch(&l2->ch), p1);
-               dev_kfree_skb(l2->windowar[p1]);
-       }
-       l2->windowar[p1] = skb;
        i = sethdraddr(l2, header, CMD);
        if (test_bit(FLG_MOD128, &l2->flag)) {
                header[i++] = l2->vs << 1;
                header[i++] = l2->vr << 1;
+       } else
+               header[i++] = (l2->vr << 5) | (l2->vs << 1);
+       nskb = skb_realloc_headroom(skb, i);
+       if (!nskb) {
+               printk(KERN_WARNING "%s: no headroom(%d) copy for IFrame\n",
+                      mISDNDevName4ch(&l2->ch), i);
+               skb_queue_head(&l2->i_queue, skb);
+               return;
+       }
+       if (test_bit(FLG_MOD128, &l2->flag)) {
+               p1 = (l2->vs - l2->va) % 128;
                l2->vs = (l2->vs + 1) % 128;
        } else {
-               header[i++] = (l2->vr << 5) | (l2->vs << 1);
+               p1 = (l2->vs - l2->va) % 8;
                l2->vs = (l2->vs + 1) % 8;
        }
-
-       nskb = skb_clone(skb, GFP_ATOMIC);
-       p1 = skb_headroom(nskb);
-       if (p1 >= i)
-               memcpy(skb_push(nskb, i), header, i);
-       else {
-               printk(KERN_WARNING
-                      "%s: L2 pull_iqueue skb header(%d/%d) too short\n",
-                      mISDNDevName4ch(&l2->ch), i, p1);
-               oskb = nskb;
-               nskb = mI_alloc_skb(oskb->len + i, GFP_ATOMIC);
-               if (!nskb) {
-                       dev_kfree_skb(oskb);
-                       printk(KERN_WARNING "%s: no skb mem in %s\n",
-                              mISDNDevName4ch(&l2->ch), __func__);
-                       return;
-               }
-               memcpy(skb_put(nskb, i), header, i);
-               memcpy(skb_put(nskb, oskb->len), oskb->data, oskb->len);
-               dev_kfree_skb(oskb);
+       p1 = (p1 + l2->sow) % l2->window;
+       if (l2->windowar[p1]) {
+               printk(KERN_WARNING "%s: l2 try overwrite ack queue entry %d\n",
+                      mISDNDevName4ch(&l2->ch), p1);
+               dev_kfree_skb(l2->windowar[p1]);
        }
+       l2->windowar[p1] = skb;
+       memcpy(skb_push(nskb, i), header, i);
        l2down(l2, PH_DATA_REQ, l2_newid(l2), nskb);
        test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
        if (!test_and_set_bit(FLG_T200_RUN, &l2->flag)) {
index 20cc36b01b77895625adbe82a14923148d688edb..0a17d1b91a811d712a350c399d94cdc50322f0d0 100644 (file)
@@ -634,10 +634,10 @@ static int __commit_transaction(struct dm_cache_metadata *cmd,
 
        disk_super = dm_block_data(sblock);
 
+       disk_super->flags = cpu_to_le32(cmd->flags);
        if (mutator)
                update_flags(disk_super, mutator);
 
-       disk_super->flags = cpu_to_le32(cmd->flags);
        disk_super->mapping_root = cpu_to_le64(cmd->root);
        disk_super->hint_root = cpu_to_le64(cmd->hint_root);
        disk_super->discard_root = cpu_to_le64(cmd->discard_root);
index 421a36c593e3e7dedef785a5f78c12914c13d8b3..2e4c4cb79e4d939f0ed2638986d2ccc3ddd8b972 100644 (file)
@@ -301,11 +301,16 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
 {
        int s;
        uint32_t max_entries = le32_to_cpu(left->header.max_entries);
-       unsigned target = (nr_left + nr_center + nr_right) / 3;
-       BUG_ON(target > max_entries);
+       unsigned total = nr_left + nr_center + nr_right;
+       unsigned target_right = total / 3;
+       unsigned remainder = (target_right * 3) != total;
+       unsigned target_left = target_right + remainder;
+
+       BUG_ON(target_left > max_entries);
+       BUG_ON(target_right > max_entries);
 
        if (nr_left < nr_right) {
-               s = nr_left - target;
+               s = nr_left - target_left;
 
                if (s < 0 && nr_center < -s) {
                        /* not enough in central node */
@@ -316,10 +321,10 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
                } else
                        shift(left, center, s);
 
-               shift(center, right, target - nr_right);
+               shift(center, right, target_right - nr_right);
 
        } else {
-               s = target - nr_right;
+               s = target_right - nr_right;
                if (s > 0 && nr_center < s) {
                        /* not enough in central node */
                        shift(center, right, nr_center);
@@ -329,7 +334,7 @@ static void redistribute3(struct dm_btree_info *info, struct btree_node *parent,
                } else
                        shift(center, right, s);
 
-               shift(left, center, nr_left - target);
+               shift(left, center, nr_left - target_left);
        }
 
        *key_ptr(parent, c->index) = center->keys[0];
index b6cec258cc2138497b3c8875fc4defdb7523701f..0e09aef43998ac250cc296122247875eed23ceb2 100644 (file)
@@ -523,7 +523,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key)
 
        r = new_block(s->info, &right);
        if (r < 0) {
-               /* FIXME: put left */
+               unlock_block(s->info, left);
                return r;
        }
 
index b055319d532edd93ff85f5e68c57e4ae1ac9493a..c1e2d1834b782096ff3e35fefa3db8bb5c2bb786 100644 (file)
@@ -46,8 +46,8 @@ extern struct dvb_frontend *horus3a_attach(struct dvb_frontend *fe,
                                        const struct horus3a_config *config,
                                        struct i2c_adapter *i2c);
 #else
-static inline struct dvb_frontend *horus3a_attach(
-                                       const struct cxd2820r_config *config,
+static inline struct dvb_frontend *horus3a_attach(struct dvb_frontend *fe,
+                                       const struct horus3a_config *config,
                                        struct i2c_adapter *i2c)
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
index 69f30e21f6b31f96497c3d6acccc4a0000b7e822..1f329ef05accea6601a093e33078b5104ef2cfa2 100644 (file)
@@ -43,7 +43,7 @@ struct dvb_frontend *lnbh25_attach(
        struct lnbh25_config *cfg,
        struct i2c_adapter *i2c);
 #else
-static inline dvb_frontend *lnbh25_attach(
+static inline struct dvb_frontend *lnbh25_attach(
        struct dvb_frontend *fe,
        struct lnbh25_config *cfg,
        struct i2c_adapter *i2c)
index ff31e7a01ca9aba8f9746e61d5091d2d1f45c255..feeeb70d841ed92a485e4ec630b1133d51c75291 100644 (file)
 
 static struct dvb_frontend_ops m88ds3103_ops;
 
+/* write single register with mask */
+static int m88ds3103_update_bits(struct m88ds3103_dev *dev,
+                               u8 reg, u8 mask, u8 val)
+{
+       int ret;
+       u8 tmp;
+
+       /* no need for read if whole reg is written */
+       if (mask != 0xff) {
+               ret = regmap_bulk_read(dev->regmap, reg, &tmp, 1);
+               if (ret)
+                       return ret;
+
+               val &= mask;
+               tmp &= ~mask;
+               val |= tmp;
+       }
+
+       return regmap_bulk_write(dev->regmap, reg, &val, 1);
+}
+
 /* write reg val table using reg addr auto increment */
 static int m88ds3103_wr_reg_val_tab(struct m88ds3103_dev *dev,
                const struct m88ds3103_reg_val *tab, int tab_len)
@@ -394,10 +415,10 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
                        u8tmp2 = 0x00; /* 0b00 */
                        break;
                }
-               ret = regmap_update_bits(dev->regmap, 0x22, 0xc0, u8tmp1 << 6);
+               ret = m88ds3103_update_bits(dev, 0x22, 0xc0, u8tmp1 << 6);
                if (ret)
                        goto err;
-               ret = regmap_update_bits(dev->regmap, 0x24, 0xc0, u8tmp2 << 6);
+               ret = m88ds3103_update_bits(dev, 0x24, 0xc0, u8tmp2 << 6);
                if (ret)
                        goto err;
        }
@@ -455,13 +476,13 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
                        if (ret)
                                goto err;
                }
-               ret = regmap_update_bits(dev->regmap, 0x9d, 0x08, 0x08);
+               ret = m88ds3103_update_bits(dev, 0x9d, 0x08, 0x08);
                if (ret)
                        goto err;
                ret = regmap_write(dev->regmap, 0xf1, 0x01);
                if (ret)
                        goto err;
-               ret = regmap_update_bits(dev->regmap, 0x30, 0x80, 0x80);
+               ret = m88ds3103_update_bits(dev, 0x30, 0x80, 0x80);
                if (ret)
                        goto err;
        }
@@ -498,7 +519,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
        switch (dev->cfg->ts_mode) {
        case M88DS3103_TS_SERIAL:
        case M88DS3103_TS_SERIAL_D7:
-               ret = regmap_update_bits(dev->regmap, 0x29, 0x20, u8tmp1);
+               ret = m88ds3103_update_bits(dev, 0x29, 0x20, u8tmp1);
                if (ret)
                        goto err;
                u8tmp1 = 0;
@@ -567,11 +588,11 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe)
        if (ret)
                goto err;
 
-       ret = regmap_update_bits(dev->regmap, 0x4d, 0x02, dev->cfg->spec_inv << 1);
+       ret = m88ds3103_update_bits(dev, 0x4d, 0x02, dev->cfg->spec_inv << 1);
        if (ret)
                goto err;
 
-       ret = regmap_update_bits(dev->regmap, 0x30, 0x10, dev->cfg->agc_inv << 4);
+       ret = m88ds3103_update_bits(dev, 0x30, 0x10, dev->cfg->agc_inv << 4);
        if (ret)
                goto err;
 
@@ -625,13 +646,13 @@ static int m88ds3103_init(struct dvb_frontend *fe)
        dev->warm = false;
 
        /* wake up device from sleep */
-       ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x01);
+       ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x01);
        if (ret)
                goto err;
-       ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x00);
+       ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x00);
        if (ret)
                goto err;
-       ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x00);
+       ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x00);
        if (ret)
                goto err;
 
@@ -749,18 +770,18 @@ static int m88ds3103_sleep(struct dvb_frontend *fe)
                utmp = 0x29;
        else
                utmp = 0x27;
-       ret = regmap_update_bits(dev->regmap, utmp, 0x01, 0x00);
+       ret = m88ds3103_update_bits(dev, utmp, 0x01, 0x00);
        if (ret)
                goto err;
 
        /* sleep */
-       ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00);
+       ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x00);
        if (ret)
                goto err;
-       ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01);
+       ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x01);
        if (ret)
                goto err;
-       ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10);
+       ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x10);
        if (ret)
                goto err;
 
@@ -992,12 +1013,12 @@ static int m88ds3103_set_tone(struct dvb_frontend *fe,
        }
 
        utmp = tone << 7 | dev->cfg->envelope_mode << 5;
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
        if (ret)
                goto err;
 
        utmp = 1 << 2;
-       ret = regmap_update_bits(dev->regmap, 0xa1, reg_a1_mask, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa1, reg_a1_mask, utmp);
        if (ret)
                goto err;
 
@@ -1047,7 +1068,7 @@ static int m88ds3103_set_voltage(struct dvb_frontend *fe,
        voltage_dis ^= dev->cfg->lnb_en_pol;
 
        utmp = voltage_dis << 1 | voltage_sel << 0;
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0x03, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0x03, utmp);
        if (ret)
                goto err;
 
@@ -1080,7 +1101,7 @@ static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe,
        }
 
        utmp = dev->cfg->envelope_mode << 5;
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
        if (ret)
                goto err;
 
@@ -1115,12 +1136,12 @@ static int m88ds3103_diseqc_send_master_cmd(struct dvb_frontend *fe,
        } else {
                dev_dbg(&client->dev, "diseqc tx timeout\n");
 
-               ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40);
+               ret = m88ds3103_update_bits(dev, 0xa1, 0xc0, 0x40);
                if (ret)
                        goto err;
        }
 
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xc0, 0x80);
        if (ret)
                goto err;
 
@@ -1152,7 +1173,7 @@ static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe,
        }
 
        utmp = dev->cfg->envelope_mode << 5;
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xe0, utmp);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xe0, utmp);
        if (ret)
                goto err;
 
@@ -1194,12 +1215,12 @@ static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe,
        } else {
                dev_dbg(&client->dev, "diseqc tx timeout\n");
 
-               ret = regmap_update_bits(dev->regmap, 0xa1, 0xc0, 0x40);
+               ret = m88ds3103_update_bits(dev, 0xa1, 0xc0, 0x40);
                if (ret)
                        goto err;
        }
 
-       ret = regmap_update_bits(dev->regmap, 0xa2, 0xc0, 0x80);
+       ret = m88ds3103_update_bits(dev, 0xa2, 0xc0, 0x80);
        if (ret)
                goto err;
 
@@ -1435,13 +1456,13 @@ static int m88ds3103_probe(struct i2c_client *client,
                goto err_kfree;
 
        /* sleep */
-       ret = regmap_update_bits(dev->regmap, 0x08, 0x01, 0x00);
+       ret = m88ds3103_update_bits(dev, 0x08, 0x01, 0x00);
        if (ret)
                goto err_kfree;
-       ret = regmap_update_bits(dev->regmap, 0x04, 0x01, 0x01);
+       ret = m88ds3103_update_bits(dev, 0x04, 0x01, 0x01);
        if (ret)
                goto err_kfree;
-       ret = regmap_update_bits(dev->regmap, 0x23, 0x10, 0x10);
+       ret = m88ds3103_update_bits(dev, 0x23, 0x10, 0x10);
        if (ret)
                goto err_kfree;
 
index 81788c5a44d838dc1f6e27e7c060db174af56913..821a8f481507a14ec3857c66cd7c4744a6ac3efd 100644 (file)
@@ -502,6 +502,10 @@ static int si2168_init(struct dvb_frontend *fe)
                /* firmware is in the new format */
                for (remaining = fw->size; remaining > 0; remaining -= 17) {
                        len = fw->data[fw->size - remaining];
+                       if (len > SI2168_ARGLEN) {
+                               ret = -EINVAL;
+                               break;
+                       }
                        memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
                        cmd.wlen = len;
                        cmd.rlen = 1;
index f55b3276f28de0122c3f4e4385cb3a1736d0b430..56773f3893d40e02d6b9cde1a72fcf0108ad350d 100644 (file)
@@ -80,11 +80,9 @@ irqreturn_t netup_spi_interrupt(struct netup_spi *spi)
        u16 reg;
        unsigned long flags;
 
-       if (!spi) {
-               dev_dbg(&spi->master->dev,
-                       "%s(): SPI not initialized\n", __func__);
+       if (!spi)
                return IRQ_NONE;
-       }
+
        spin_lock_irqsave(&spi->lock, flags);
        reg = readw(&spi->regs->control_stat);
        if (!(reg & NETUP_SPI_CTRL_IRQ)) {
@@ -234,11 +232,9 @@ void netup_spi_release(struct netup_unidvb_dev *ndev)
        unsigned long flags;
        struct netup_spi *spi = ndev->spi;
 
-       if (!spi) {
-               dev_dbg(&spi->master->dev,
-                       "%s(): SPI not initialized\n", __func__);
+       if (!spi)
                return;
-       }
+
        spin_lock_irqsave(&spi->lock, flags);
        reg = readw(&spi->regs->control_stat);
        writew(reg | NETUP_SPI_CTRL_IRQ, &spi->regs->control_stat);
index 486aef50d99b23e4753cbd055221cd2dbb4f6097..f922f2e827bcbb2bfe8cd0606fac89d3ec8c5bd6 100644 (file)
@@ -1097,7 +1097,7 @@ static int load_slim_core_fw(const struct firmware *fw, void *context)
        Elf32_Ehdr *ehdr;
        Elf32_Phdr *phdr;
        u8 __iomem *dst;
-       int err, i;
+       int err = 0, i;
 
        if (!fw || !context)
                return -EINVAL;
@@ -1106,7 +1106,7 @@ static int load_slim_core_fw(const struct firmware *fw, void *context)
        phdr = (Elf32_Phdr *)(fw->data + ehdr->e_phoff);
 
        /* go through the available ELF segments */
-       for (i = 0; i < ehdr->e_phnum && !err; i++, phdr++) {
+       for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
 
                /* Only consider LOAD segments */
                if (phdr->p_type != PT_LOAD)
@@ -1192,7 +1192,6 @@ err:
 
 static int load_c8sectpfe_fw_step1(struct c8sectpfei *fei)
 {
-       int ret;
        int err;
 
        dev_info(fei->dev, "Loading firmware: %s\n", FIRMWARE_MEMDMA);
@@ -1207,7 +1206,7 @@ static int load_c8sectpfe_fw_step1(struct c8sectpfei *fei)
        if (err) {
                dev_err(fei->dev, "request_firmware_nowait err: %d.\n", err);
                complete_all(&fei->fw_ack);
-               return ret;
+               return err;
        }
 
        return 0;
index 1c087cb76815a3ab488cb53db85cf98b5b0cac80..d0549fba711c474a1d58e416bbff09dad9a2f328 100644 (file)
@@ -257,7 +257,7 @@ static int hix5hd2_ir_probe(struct platform_device *pdev)
                goto clkerr;
 
        if (devm_request_irq(dev, priv->irq, hix5hd2_ir_rx_interrupt,
-                            IRQF_NO_SUSPEND, pdev->name, priv) < 0) {
+                            0, pdev->name, priv) < 0) {
                dev_err(dev, "IRQ %d register failed\n", priv->irq);
                ret = -EINVAL;
                goto regerr;
index 507382160e5e7524022c782240c36f98c1b54871..ce157edd45fa1adb3dd382037dd421f8b8590091 100644 (file)
@@ -166,6 +166,10 @@ static int si2157_init(struct dvb_frontend *fe)
 
        for (remaining = fw->size; remaining > 0; remaining -= 17) {
                len = fw->data[fw->size - remaining];
+               if (len > SI2157_ARGLEN) {
+                       dev_err(&client->dev, "Bad firmware length\n");
+                       goto err_release_firmware;
+               }
                memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
                cmd.wlen = len;
                cmd.rlen = 1;
index c3cac4c12fb3c6c18315ab83941a3454dc5ce9bd..197a4f2e54d2a1c08a3c662b3f983b57bf8190dd 100644 (file)
@@ -34,6 +34,14 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
        unsigned int pipe;
        u8 requesttype;
 
+       mutex_lock(&d->usb_mutex);
+
+       if (req->size > sizeof(dev->buf)) {
+               dev_err(&d->intf->dev, "too large message %u\n", req->size);
+               ret = -EINVAL;
+               goto err_mutex_unlock;
+       }
+
        if (req->index & CMD_WR_FLAG) {
                /* write */
                memcpy(dev->buf, req->data, req->size);
@@ -50,14 +58,17 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
        dvb_usb_dbg_usb_control_msg(d->udev, 0, requesttype, req->value,
                        req->index, dev->buf, req->size);
        if (ret < 0)
-               goto err;
+               goto err_mutex_unlock;
 
        /* read request, copy returned data to return buf */
        if (requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
                memcpy(req->data, dev->buf, req->size);
 
+       mutex_unlock(&d->usb_mutex);
+
        return 0;
-err:
+err_mutex_unlock:
+       mutex_unlock(&d->usb_mutex);
        dev_dbg(&d->intf->dev, "failed=%d\n", ret);
        return ret;
 }
index 9f6115a2ee0166d509584d5b5c5fd0b62d5bff06..138062960a7367737521659acc607983c921a685 100644 (file)
@@ -71,7 +71,7 @@
 
 
 struct rtl28xxu_dev {
-       u8 buf[28];
+       u8 buf[128];
        u8 chip_id;
        u8 tuner;
        char *tuner_name;
index 82876a67f1449b62f02142f4a677aee8880c295a..9beece00869bf0e27a99fc641b8f926c0d3bad8f 100644 (file)
@@ -47,7 +47,7 @@ config V4L2_MEM2MEM_DEV
 # Used by LED subsystem flash drivers
 config V4L2_FLASH_LED_CLASS
        tristate "V4L2 flash API for LED flash class devices"
-       depends on VIDEO_V4L2_SUBDEV_API
+       depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
        depends on LEDS_CLASS_FLASH
        ---help---
          Say Y here to enable V4L2 flash API support for LED flash
index c6a644b22af44e53b5cee18fc596df48ff675835..6f3154613dc7174b04a7e91dff0af1d3aae9b31e 100644 (file)
@@ -58,12 +58,18 @@ config OMAP_GPMC
          memory drives like NOR, NAND, OneNAND, SRAM.
 
 config OMAP_GPMC_DEBUG
-       bool
+       bool "Enable GPMC debug output and skip reset of GPMC during init"
        depends on OMAP_GPMC
        help
          Enables verbose debugging mostly to decode the bootloader provided
-         timings. Enable this during development to configure devices
-         connected to the GPMC bus.
+         timings. To preserve the bootloader provided timings, the reset
+         of GPMC is skipped during init. Enable this during development to
+         configure devices connected to the GPMC bus.
+
+         NOTE: In addition to matching the register setup with the bootloader
+         you also need to match the GPMC FCLK frequency used by the
+         bootloader or else the GPMC timings won't be identical with the
+         bootloader timings.
 
 config MVEBU_DEVBUS
        bool "Marvell EBU Device Bus Controller"
index 32ac049f2bc4dbda4418587cc017cc074d5989c9..6515dfc2b805d6c5198756e17bacd23724689dac 100644 (file)
@@ -696,7 +696,6 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t,
        int div;
        u32 l;
 
-       gpmc_cs_show_timings(cs, "before gpmc_cs_set_timings");
        div = gpmc_calc_divider(t->sync_clk);
        if (div < 0)
                return div;
@@ -1988,6 +1987,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
        if (ret < 0)
                goto err;
 
+       gpmc_cs_show_timings(cs, "before gpmc_cs_program_settings");
        ret = gpmc_cs_program_settings(cs, &gpmc_s);
        if (ret < 0)
                goto err;
index b78cf5d403a33b74244a39245b9df6f9024c4d24..7fc9174d46191a13c77fa4e220bb476a32dfe05e 100644 (file)
@@ -2263,15 +2263,12 @@ static int mmc_test_profile_sglen_r_nonblock_perf(struct mmc_test_card *test)
 /*
  * eMMC hardware reset.
  */
-static int mmc_test_hw_reset(struct mmc_test_card *test)
+static int mmc_test_reset(struct mmc_test_card *test)
 {
        struct mmc_card *card = test->card;
        struct mmc_host *host = card->host;
        int err;
 
-       if (!mmc_card_mmc(card) || !mmc_can_reset(card))
-               return RESULT_UNSUP_CARD;
-
        err = mmc_hw_reset(host);
        if (!err)
                return RESULT_OK;
@@ -2605,8 +2602,8 @@ static const struct mmc_test_case mmc_test_cases[] = {
        },
 
        {
-               .name = "eMMC hardware reset",
-               .run = mmc_test_hw_reset,
+               .name = "Reset test",
+               .run = mmc_test_reset,
        },
 };
 
index e726903170a828cffd69a1cb2e7f80d59c0d5152..f6cd995dbe920392cce50062ff2e4f080634ee06 100644 (file)
@@ -1924,7 +1924,6 @@ EXPORT_SYMBOL(mmc_can_reset);
 static int mmc_reset(struct mmc_host *host)
 {
        struct mmc_card *card = host->card;
-       u32 status;
 
        if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset)
                return -EOPNOTSUPP;
@@ -1937,12 +1936,6 @@ static int mmc_reset(struct mmc_host *host)
 
        host->ops->hw_reset(host);
 
-       /* If the reset has happened, then a status command will fail */
-       if (!mmc_send_status(card, &status)) {
-               mmc_host_clk_release(host);
-               return -ENOSYS;
-       }
-
        /* Set initial state and call mmc_set_ios */
        mmc_set_initial_state(host);
        mmc_host_clk_release(host);
index e5fac368068a2320eb06d207934c4b969356237b..131026fbc2d77cbc3ccb5903daa10f8920f8ae17 100644 (file)
@@ -87,6 +87,7 @@ static const struct pci_device_id peak_pci_tbl[] = {
        {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_PCIE_OEM_ID, PCI_ANY_ID, PCI_ANY_ID,},
 #ifdef CONFIG_CAN_PEAK_PCIEC
        {PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
index 48ce83e443c2b12bbcbc2e2545c5ac6b1983f3d0..8d50314ac3eb1f308d1cc556270058aba05c7b60 100644 (file)
@@ -847,21 +847,25 @@ static int emac_probe(struct platform_device *pdev)
        if (ndev->irq == -ENXIO) {
                netdev_err(ndev, "No irq resource\n");
                ret = ndev->irq;
-               goto out;
+               goto out_iounmap;
        }
 
        db->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(db->clk)) {
                ret = PTR_ERR(db->clk);
-               goto out;
+               goto out_iounmap;
        }
 
-       clk_prepare_enable(db->clk);
+       ret = clk_prepare_enable(db->clk);
+       if (ret) {
+               dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret);
+               goto out_iounmap;
+       }
 
        ret = sunxi_sram_claim(&pdev->dev);
        if (ret) {
                dev_err(&pdev->dev, "Error couldn't map SRAM to device\n");
-               goto out;
+               goto out_clk_disable_unprepare;
        }
 
        db->phy_node = of_parse_phandle(np, "phy", 0);
@@ -910,6 +914,10 @@ static int emac_probe(struct platform_device *pdev)
 
 out_release_sram:
        sunxi_sram_release(&pdev->dev);
+out_clk_disable_unprepare:
+       clk_disable_unprepare(db->clk);
+out_iounmap:
+       iounmap(db->membase);
 out:
        dev_err(db->dev, "not found (%d).\n", ret);
 
@@ -921,8 +929,12 @@ out:
 static int emac_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
+       struct emac_board_info *db = netdev_priv(ndev);
 
        unregister_netdev(ndev);
+       sunxi_sram_release(&pdev->dev);
+       clk_disable_unprepare(db->clk);
+       iounmap(db->membase);
        free_netdev(ndev);
 
        dev_dbg(&pdev->dev, "released and freed device\n");
index 2c063b60db4b02bc48246887fb5d98f6b3de0394..96f485ab612e679dc7065b1e214cb9d73c690d43 100644 (file)
@@ -327,9 +327,13 @@ void xgbe_debugfs_init(struct xgbe_prv_data *pdata)
        pdata->debugfs_xpcs_reg = 0;
 
        buf = kasprintf(GFP_KERNEL, "amd-xgbe-%s", pdata->netdev->name);
+       if (!buf)
+               return;
+
        pdata->xgbe_debugfs = debugfs_create_dir(buf, NULL);
        if (!pdata->xgbe_debugfs) {
                netdev_err(pdata->netdev, "debugfs_create_dir failed\n");
+               kfree(buf);
                return;
        }
 
index a4473d8ff4fa0e1ec7bbdb511f9edd51f1871d71..f672dba345f7f73b028741ec60befa6ab012fd04 100644 (file)
@@ -1595,7 +1595,7 @@ static void xgbe_dev_xmit(struct xgbe_channel *channel)
                                  packet->rdesc_count, 1);
 
        /* Make sure ownership is written to the descriptor */
-       dma_wmb();
+       smp_wmb();
 
        ring->cur = cur_index + 1;
        if (!packet->skb->xmit_more ||
index aae9d5ecd1822b16a2812de3bee503f59113adaa..dde0486667e0cfab87c593283d80a71f873977d3 100644 (file)
@@ -1807,6 +1807,7 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
        struct netdev_queue *txq;
        int processed = 0;
        unsigned int tx_packets = 0, tx_bytes = 0;
+       unsigned int cur;
 
        DBGPR("-->xgbe_tx_poll\n");
 
@@ -1814,10 +1815,15 @@ static int xgbe_tx_poll(struct xgbe_channel *channel)
        if (!ring)
                return 0;
 
+       cur = ring->cur;
+
+       /* Be sure we get ring->cur before accessing descriptor data */
+       smp_rmb();
+
        txq = netdev_get_tx_queue(netdev, channel->queue_index);
 
        while ((processed < XGBE_TX_DESC_MAX_PROC) &&
-              (ring->dirty != ring->cur)) {
+              (ring->dirty != cur)) {
                rdata = XGBE_GET_DESC_DATA(ring, ring->dirty);
                rdesc = rdata->rdesc;
 
index a7f2cc3e485eebfae962fe24cfc1142021a74cde..4183c2abeeeb2dc206f2ca4aa90d88279e2eb6d9 100644 (file)
@@ -2049,7 +2049,7 @@ static void swphy_poll_timer(unsigned long data)
 
        for (i = 0; i < priv->num_ports; i++) {
                struct bcm63xx_enetsw_port *port;
-               int val, j, up, advertise, lpa, lpa2, speed, duplex, media;
+               int val, j, up, advertise, lpa, speed, duplex, media;
                int external_phy = bcm_enet_port_is_rgmii(i);
                u8 override;
 
@@ -2092,22 +2092,27 @@ static void swphy_poll_timer(unsigned long data)
                lpa = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id,
                                           MII_LPA);
 
-               lpa2 = bcmenet_sw_mdio_read(priv, external_phy, port->phy_id,
-                                           MII_STAT1000);
-
                /* figure out media and duplex from advertise and LPA values */
                media = mii_nway_result(lpa & advertise);
                duplex = (media & ADVERTISE_FULL) ? 1 : 0;
-               if (lpa2 & LPA_1000FULL)
-                       duplex = 1;
-
-               if (lpa2 & (LPA_1000FULL | LPA_1000HALF))
-                       speed = 1000;
-               else {
-                       if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
-                               speed = 100;
-                       else
-                               speed = 10;
+
+               if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
+                       speed = 100;
+               else
+                       speed = 10;
+
+               if (val & BMSR_ESTATEN) {
+                       advertise = bcmenet_sw_mdio_read(priv, external_phy,
+                                               port->phy_id, MII_CTRL1000);
+
+                       lpa = bcmenet_sw_mdio_read(priv, external_phy,
+                                               port->phy_id, MII_STAT1000);
+
+                       if (advertise & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)
+                                       && lpa & (LPA_1000FULL | LPA_1000HALF)) {
+                               speed = 1000;
+                               duplex = (lpa & LPA_1000FULL);
+                       }
                }
 
                dev_info(&priv->pdev->dev,
index aeb7ce64452e14cd3cbe49325f63bae2d99e3ef2..be628bd9fb18b6f0116125e5a3f9ea16ad1d3561 100644 (file)
@@ -3351,6 +3351,13 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info)
                        udp_rss_requested = 0;
                else
                        return -EINVAL;
+
+               if (CHIP_IS_E1x(bp) && udp_rss_requested) {
+                       DP(BNX2X_MSG_ETHTOOL,
+                          "57710, 57711 boards don't support RSS according to UDP 4-tuple\n");
+                       return -EINVAL;
+               }
+
                if ((info->flow_type == UDP_V4_FLOW) &&
                    (bp->rss_conf_obj.udp_rss_v4 != udp_rss_requested)) {
                        bp->rss_conf_obj.udp_rss_v4 = udp_rss_requested;
index 3bc701e4c59eb56cc19e11c917dd34c24062754e..1805541b4240e72c79445ea6f50bbc2a74ba13c7 100644 (file)
@@ -1683,6 +1683,24 @@ static void bcmgenet_intr_disable(struct bcmgenet_priv *priv)
        bcmgenet_intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
 }
 
+static void bcmgenet_link_intr_enable(struct bcmgenet_priv *priv)
+{
+       u32 int0_enable = 0;
+
+       /* Monitor cable plug/unplugged event for internal PHY, external PHY
+        * and MoCA PHY
+        */
+       if (priv->internal_phy) {
+               int0_enable |= UMAC_IRQ_LINK_EVENT;
+       } else if (priv->ext_phy) {
+               int0_enable |= UMAC_IRQ_LINK_EVENT;
+       } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
+               if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
+                       int0_enable |= UMAC_IRQ_LINK_EVENT;
+       }
+       bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);
+}
+
 static int init_umac(struct bcmgenet_priv *priv)
 {
        struct device *kdev = &priv->pdev->dev;
@@ -1723,15 +1741,8 @@ static int init_umac(struct bcmgenet_priv *priv)
        /* Enable Tx default queue 16 interrupts */
        int0_enable |= UMAC_IRQ_TXDMA_DONE;
 
-       /* Monitor cable plug/unplugged event for internal PHY */
-       if (priv->internal_phy) {
-               int0_enable |= UMAC_IRQ_LINK_EVENT;
-       } else if (priv->ext_phy) {
-               int0_enable |= UMAC_IRQ_LINK_EVENT;
-       } else if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
-               if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
-                       int0_enable |= UMAC_IRQ_LINK_EVENT;
-
+       /* Configure backpressure vectors for MoCA */
+       if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
                reg = bcmgenet_bp_mc_get(priv);
                reg |= BIT(priv->hw_params->bp_in_en_shift);
 
@@ -2645,6 +2656,9 @@ static void bcmgenet_netif_start(struct net_device *dev)
 
        netif_tx_start_all_queues(dev);
 
+       /* Monitor link interrupts now */
+       bcmgenet_link_intr_enable(priv);
+
        phy_start(priv->phydev);
 }
 
index 9b35d142f47accfbaec039f0d8100fb45d68bbf8..8fb84e69c30ec8ddfdf6be710cbfab0a3cd1aa60 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 config NET_VENDOR_CAVIUM
-       tristate "Cavium ethernet drivers"
+       bool "Cavium ethernet drivers"
        depends on PCI
        default y
        ---help---
index b3a5947a2cc03e1675e5895fef39e35b10ea04d0..c561fdcb79a730aeeb890c5a985b05cb873faa45 100644 (file)
@@ -22,7 +22,6 @@
 
 struct nicpf {
        struct pci_dev          *pdev;
-       u8                      rev_id;
        u8                      node;
        unsigned int            flags;
        u8                      num_vf_en;      /* No of VF enabled */
@@ -44,6 +43,7 @@ struct nicpf {
        u8                      duplex[MAX_LMAC];
        u32                     speed[MAX_LMAC];
        u16                     cpi_base[MAX_NUM_VFS_SUPPORTED];
+       u16                     rssi_base[MAX_NUM_VFS_SUPPORTED];
        u16                     rss_ind_tbl_size;
        bool                    mbx_lock[MAX_NUM_VFS_SUPPORTED];
 
@@ -54,6 +54,11 @@ struct nicpf {
        bool                    irq_allocated[NIC_PF_MSIX_VECTORS];
 };
 
+static inline bool pass1_silicon(struct nicpf *nic)
+{
+       return nic->pdev->revision < 8;
+}
+
 /* Supported devices */
 static const struct pci_device_id nic_id_table[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_THUNDER_NIC_PF) },
@@ -117,7 +122,7 @@ static void nic_send_msg_to_vf(struct nicpf *nic, int vf, union nic_mbx *mbx)
         * when PF writes to MBOX(1), in next revisions when
         * PF writes to MBOX(0)
         */
-       if (nic->rev_id == 0) {
+       if (pass1_silicon(nic)) {
                /* see the comment for nic_reg_write()/nic_reg_read()
                 * functions above
                 */
@@ -305,9 +310,6 @@ static void nic_init_hw(struct nicpf *nic)
 {
        int i;
 
-       /* Reset NIC, in case the driver is repeatedly inserted and removed */
-       nic_reg_write(nic, NIC_PF_SOFT_RESET, 1);
-
        /* Enable NIC HW block */
        nic_reg_write(nic, NIC_PF_CFG, 0x3);
 
@@ -395,8 +397,18 @@ static void nic_config_cpi(struct nicpf *nic, struct cpi_cfg_msg *cfg)
                        padd = cpi % 8; /* 3 bits CS out of 6bits DSCP */
 
                /* Leave RSS_SIZE as '0' to disable RSS */
-               nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3),
-                             (vnic << 24) | (padd << 16) | (rssi_base + rssi));
+               if (pass1_silicon(nic)) {
+                       nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3),
+                                     (vnic << 24) | (padd << 16) |
+                                     (rssi_base + rssi));
+               } else {
+                       /* Set MPI_ALG to '0' to disable MCAM parsing */
+                       nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi << 3),
+                                     (padd << 16));
+                       /* MPI index is same as CPI if MPI_ALG is not enabled */
+                       nic_reg_write(nic, NIC_PF_MPI_0_2047_CFG | (cpi << 3),
+                                     (vnic << 24) | (rssi_base + rssi));
+               }
 
                if ((rssi + 1) >= cfg->rq_cnt)
                        continue;
@@ -409,6 +421,7 @@ static void nic_config_cpi(struct nicpf *nic, struct cpi_cfg_msg *cfg)
                        rssi = ((cpi - cpi_base) & 0x38) >> 3;
        }
        nic->cpi_base[cfg->vf_id] = cpi_base;
+       nic->rssi_base[cfg->vf_id] = rssi_base;
 }
 
 /* Responsds to VF with its RSS indirection table size */
@@ -434,10 +447,9 @@ static void nic_config_rss(struct nicpf *nic, struct rss_cfg_msg *cfg)
 {
        u8  qset, idx = 0;
        u64 cpi_cfg, cpi_base, rssi_base, rssi;
+       u64 idx_addr;
 
-       cpi_base = nic->cpi_base[cfg->vf_id];
-       cpi_cfg = nic_reg_read(nic, NIC_PF_CPI_0_2047_CFG | (cpi_base << 3));
-       rssi_base = (cpi_cfg & 0x0FFF) + cfg->tbl_offset;
+       rssi_base = nic->rssi_base[cfg->vf_id] + cfg->tbl_offset;
 
        rssi = rssi_base;
        qset = cfg->vf_id;
@@ -454,9 +466,15 @@ static void nic_config_rss(struct nicpf *nic, struct rss_cfg_msg *cfg)
                idx++;
        }
 
+       cpi_base = nic->cpi_base[cfg->vf_id];
+       if (pass1_silicon(nic))
+               idx_addr = NIC_PF_CPI_0_2047_CFG;
+       else
+               idx_addr = NIC_PF_MPI_0_2047_CFG;
+       cpi_cfg = nic_reg_read(nic, idx_addr | (cpi_base << 3));
        cpi_cfg &= ~(0xFULL << 20);
        cpi_cfg |= (cfg->hash_bits << 20);
-       nic_reg_write(nic, NIC_PF_CPI_0_2047_CFG | (cpi_base << 3), cpi_cfg);
+       nic_reg_write(nic, idx_addr | (cpi_base << 3), cpi_cfg);
 }
 
 /* 4 level transmit side scheduler configutation
@@ -1001,8 +1019,6 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_release_regions;
        }
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &nic->rev_id);
-
        nic->node = nic_get_node_id(pdev);
 
        nic_set_lmac_vf_mapping(nic);
index 58197bb2f80528bf06de0daaa2c406b96d4fc0c4..dd536be20193119c3465cd772a4bff6d649e3319 100644 (file)
 #define   NIC_PF_ECC3_DBE_INT_W1S              (0x2708)
 #define   NIC_PF_ECC3_DBE_ENA_W1C              (0x2710)
 #define   NIC_PF_ECC3_DBE_ENA_W1S              (0x2718)
+#define   NIC_PF_MCAM_0_191_ENA                        (0x100000)
+#define   NIC_PF_MCAM_0_191_M_0_5_DATA         (0x110000)
+#define   NIC_PF_MCAM_CTRL                     (0x120000)
 #define   NIC_PF_CPI_0_2047_CFG                        (0x200000)
+#define   NIC_PF_MPI_0_2047_CFG                        (0x210000)
 #define   NIC_PF_RSSI_0_4097_RQ                        (0x220000)
 #define   NIC_PF_LMAC_0_7_CFG                  (0x240000)
 #define   NIC_PF_LMAC_0_7_SW_XOFF              (0x242000)
index b63e579aeb12d09bbe7f6e3de5badced5b2d44ba..a9377727c11c3fdb18a09f16ce8366ae4ef48057 100644 (file)
@@ -29,7 +29,7 @@
 static const struct pci_device_id nicvf_id_table[] = {
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM,
                         PCI_DEVICE_ID_THUNDER_NIC_VF,
-                        PCI_VENDOR_ID_CAVIUM, 0xA11E) },
+                        PCI_VENDOR_ID_CAVIUM, 0xA134) },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_CAVIUM,
                         PCI_DEVICE_ID_THUNDER_PASS1_NIC_VF,
                         PCI_VENDOR_ID_CAVIUM, 0xA11E) },
index 574c49278900943e5584fa9658f7eb6adb2d7452..180aa9fabf4820df042f18cba8c39d5ce1668e9d 100644 (file)
@@ -977,8 +977,10 @@ static int bgx_init_of_phy(struct bgx *bgx)
                SET_NETDEV_DEV(&bgx->lmac[lmac].netdev, &bgx->pdev->dev);
                bgx->lmac[lmac].lmacid = lmac;
                lmac++;
-               if (lmac == MAX_LMAC_PER_BGX)
+               if (lmac == MAX_LMAC_PER_BGX) {
+                       of_node_put(np_child);
                        break;
+               }
        }
        return 0;
 }
index 821540913343db10f59ae3a03835a084ca82063d..d463563e1f7039ee5176ca36abfdc6bae3f2ed46 100644 (file)
@@ -592,6 +592,7 @@ struct be_adapter {
        int be_get_temp_freq;
        struct be_hwmon hwmon_info;
        u8 pf_number;
+       u8 pci_func_num;
        struct rss_info rss_info;
        /* Filters for packets that need to be sent to BMC */
        u32 bmc_filt_mask;
index eb323913cd39fb981a8c0cc02140c0c7205ee4f8..1795c935ff023fcf795008a49a9a4cd0fce63d9c 100644 (file)
@@ -851,8 +851,10 @@ static int be_cmd_notify_wait(struct be_adapter *adapter,
                return status;
 
        dest_wrb = be_cmd_copy(adapter, wrb);
-       if (!dest_wrb)
-               return -EBUSY;
+       if (!dest_wrb) {
+               status = -EBUSY;
+               goto unlock;
+       }
 
        if (use_mcc(adapter))
                status = be_mcc_notify_wait(adapter);
@@ -862,6 +864,7 @@ static int be_cmd_notify_wait(struct be_adapter *adapter,
        if (!status)
                memcpy(wrb, dest_wrb, sizeof(*wrb));
 
+unlock:
        be_cmd_unlock(adapter);
        return status;
 }
@@ -1984,6 +1987,8 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
                         be_if_cap_flags(adapter));
        }
        flags &= be_if_cap_flags(adapter);
+       if (!flags)
+               return -ENOTSUPP;
 
        return __be_cmd_rx_filter(adapter, flags, value);
 }
@@ -2887,6 +2892,7 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
        if (!status) {
                attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr);
                adapter->hba_port_num = attribs->hba_attribs.phy_port;
+               adapter->pci_func_num = attribs->pci_func_num;
                serial_num = attribs->hba_attribs.controller_serial_number;
                for (i = 0; i < CNTL_SERIAL_NUM_WORDS; i++)
                        adapter->serial_num[i] = le32_to_cpu(serial_num[i]) &
@@ -3709,7 +3715,6 @@ int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res)
                        status = -EINVAL;
                        goto err;
                }
-
                adapter->pf_number = desc->pf_num;
                be_copy_nic_desc(res, desc);
        }
@@ -3721,7 +3726,10 @@ err:
        return status;
 }
 
-/* Will use MBOX only if MCCQ has not been created */
+/* Will use MBOX only if MCCQ has not been created
+ * non-zero domain => a PF is querying this on behalf of a VF
+ * zero domain => a PF or a VF is querying this for itself
+ */
 int be_cmd_get_profile_config(struct be_adapter *adapter,
                              struct be_resources *res, u8 query, u8 domain)
 {
@@ -3748,10 +3756,15 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
                               OPCODE_COMMON_GET_PROFILE_CONFIG,
                               cmd.size, &wrb, &cmd);
 
-       req->hdr.domain = domain;
        if (!lancer_chip(adapter))
                req->hdr.version = 1;
        req->type = ACTIVE_PROFILE_TYPE;
+       /* When a function is querying profile information relating to
+        * itself hdr.pf_number must be set to it's pci_func_num + 1
+        */
+       req->hdr.domain = domain;
+       if (domain == 0)
+               req->hdr.pf_num = adapter->pci_func_num + 1;
 
        /* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the
         * descriptors with all bits set to "1" for the fields which can be
@@ -3921,12 +3934,16 @@ static void be_fill_vf_res_template(struct be_adapter *adapter,
                        vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS |
                                             BE_IF_FLAGS_DEFQ_RSS);
                }
-
-               nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags);
        } else {
                num_vf_qs = 1;
        }
 
+       if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) {
+               nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT);
+               vf_if_cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS;
+       }
+
+       nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags);
        nic_vft->rq_count = cpu_to_le16(num_vf_qs);
        nic_vft->txq_count = cpu_to_le16(num_vf_qs);
        nic_vft->rssq_count = cpu_to_le16(num_vf_qs);
index 7d178bdb112eb7d14d5a62d74ea21ecaa30ba0e9..91155ea74f342e2663f18848c9fe5546635e7c05 100644 (file)
@@ -289,7 +289,9 @@ struct be_cmd_req_hdr {
        u32 timeout;            /* dword 1 */
        u32 request_length;     /* dword 2 */
        u8 version;             /* dword 3 */
-       u8 rsvd[3];             /* dword 3 */
+       u8 rsvd1;               /* dword 3 */
+       u8 pf_num;              /* dword 3 */
+       u8 rsvd2;               /* dword 3 */
 };
 
 #define RESP_HDR_INFO_OPCODE_SHIFT     0       /* bits 0 - 7 */
@@ -1652,7 +1654,11 @@ struct mgmt_hba_attribs {
 
 struct mgmt_controller_attrib {
        struct mgmt_hba_attribs hba_attribs;
-       u32 rsvd0[10];
+       u32 rsvd0[2];
+       u16 rsvd1;
+       u8 pci_func_num;
+       u8 rsvd2;
+       u32 rsvd3[7];
 } __packed;
 
 struct be_cmd_req_cntl_attribs {
index 7bf51a1a0a77e12a4812662767dd21767813dc1b..eb48a977f8daabe78d6d5b6a94f6607bf19287b8 100644 (file)
@@ -1123,11 +1123,12 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
                                           struct sk_buff *skb,
                                           struct be_wrb_params *wrb_params)
 {
-       /* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or
-        * less may cause a transmit stall on that port. So the work-around is
-        * to pad short packets (<= 32 bytes) to a 36-byte length.
+       /* Lancer, SH and BE3 in SRIOV mode have a bug wherein
+        * packets that are 32b or less may cause a transmit stall
+        * on that port. The workaround is to pad such packets
+        * (len <= 32 bytes) to a minimum length of 36b.
         */
-       if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) {
+       if (skb->len <= 32) {
                if (skb_put_padto(skb, 36))
                        return NULL;
        }
@@ -4205,10 +4206,6 @@ static int be_get_config(struct be_adapter *adapter)
        int status, level;
        u16 profile_id;
 
-       status = be_cmd_get_cntl_attributes(adapter);
-       if (status)
-               return status;
-
        status = be_cmd_query_fw_cfg(adapter);
        if (status)
                return status;
@@ -4407,6 +4404,11 @@ static int be_setup(struct be_adapter *adapter)
        if (!lancer_chip(adapter))
                be_cmd_req_native_mode(adapter);
 
+       /* Need to invoke this cmd first to get the PCI Function Number */
+       status = be_cmd_get_cntl_attributes(adapter);
+       if (status)
+               return status;
+
        if (!BE2_chip(adapter) && be_physfn(adapter))
                be_alloc_sriov_res(adapter);
 
@@ -4999,7 +5001,15 @@ static bool be_check_ufi_compatibility(struct be_adapter *adapter,
                return false;
        }
 
-       return (fhdr->asic_type_rev >= adapter->asic_rev);
+       /* In BE3 FW images the "asic_type_rev" field doesn't track the
+        * asic_rev of the chips it is compatible with.
+        * When asic_type_rev is 0 the image is compatible only with
+        * pre-BE3-R chips (asic_rev < 0x10)
+        */
+       if (BEx_chip(adapter) && fhdr->asic_type_rev == 0)
+               return adapter->asic_rev < 0x10;
+       else
+               return (fhdr->asic_type_rev >= adapter->asic_rev);
 }
 
 static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
index 3c40f6b9922436a32d255aa627e9d94db45f8477..55c36230e17634c3e063bdb20f4bb6a896bce4a6 100644 (file)
@@ -198,17 +198,28 @@ static int fsl_pq_mdio_reset(struct mii_bus *bus)
 
 #if defined(CONFIG_GIANFAR) || defined(CONFIG_GIANFAR_MODULE)
 /*
+ * Return the TBIPA address, starting from the address
+ * of the mapped GFAR MDIO registers (struct gfar)
  * This is mildly evil, but so is our hardware for doing this.
  * Also, we have to cast back to struct gfar because of
  * definition weirdness done in gianfar.h.
  */
-static uint32_t __iomem *get_gfar_tbipa(void __iomem *p)
+static uint32_t __iomem *get_gfar_tbipa_from_mdio(void __iomem *p)
 {
        struct gfar __iomem *enet_regs = p;
 
        return &enet_regs->tbipa;
 }
 
+/*
+ * Return the TBIPA address, starting from the address
+ * of the mapped GFAR MII registers (gfar_mii_regs[] within struct gfar)
+ */
+static uint32_t __iomem *get_gfar_tbipa_from_mii(void __iomem *p)
+{
+       return get_gfar_tbipa_from_mdio(container_of(p, struct gfar, gfar_mii_regs));
+}
+
 /*
  * Return the TBIPAR address for an eTSEC2 node
  */
@@ -220,11 +231,12 @@ static uint32_t __iomem *get_etsec_tbipa(void __iomem *p)
 
 #if defined(CONFIG_UCC_GETH) || defined(CONFIG_UCC_GETH_MODULE)
 /*
- * Return the TBIPAR address for a QE MDIO node
+ * Return the TBIPAR address for a QE MDIO node, starting from the address
+ * of the mapped MII registers (struct fsl_pq_mii)
  */
 static uint32_t __iomem *get_ucc_tbipa(void __iomem *p)
 {
-       struct fsl_pq_mdio __iomem *mdio = p;
+       struct fsl_pq_mdio __iomem *mdio = container_of(p, struct fsl_pq_mdio, mii);
 
        return &mdio->utbipar;
 }
@@ -300,14 +312,14 @@ static const struct of_device_id fsl_pq_mdio_match[] = {
                .compatible = "fsl,gianfar-tbi",
                .data = &(struct fsl_pq_mdio_data) {
                        .mii_offset = 0,
-                       .get_tbipa = get_gfar_tbipa,
+                       .get_tbipa = get_gfar_tbipa_from_mii,
                },
        },
        {
                .compatible = "fsl,gianfar-mdio",
                .data = &(struct fsl_pq_mdio_data) {
                        .mii_offset = 0,
-                       .get_tbipa = get_gfar_tbipa,
+                       .get_tbipa = get_gfar_tbipa_from_mii,
                },
        },
        {
@@ -315,7 +327,7 @@ static const struct of_device_id fsl_pq_mdio_match[] = {
                .compatible = "gianfar",
                .data = &(struct fsl_pq_mdio_data) {
                        .mii_offset = offsetof(struct fsl_pq_mdio, mii),
-                       .get_tbipa = get_gfar_tbipa,
+                       .get_tbipa = get_gfar_tbipa_from_mdio,
                },
        },
        {
@@ -445,6 +457,16 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)
 
                        tbipa = data->get_tbipa(priv->map);
 
+                       /*
+                        * Add consistency check to make sure TBI is contained
+                        * within the mapped range (not because we would get a
+                        * segfault, rather to catch bugs in computing TBI
+                        * address). Print error message but continue anyway.
+                        */
+                       if ((void *)tbipa > priv->map + resource_size(&res) - 4)
+                               dev_err(&pdev->dev, "invalid register map (should be at least 0x%04x to contain TBI address)\n",
+                                       ((void *)tbipa - priv->map) + 4);
+
                        iowrite32be(be32_to_cpup(prop), tbipa);
                }
        }
index 710715fcb23dea7765ce3fc579c88fcd29ecb0da..ce38d266f931c506503b37749823eb388f1dd380 100644 (file)
@@ -341,7 +341,7 @@ static void gfar_rx_offload_en(struct gfar_private *priv)
        if (priv->ndev->features & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX))
                priv->uses_rxfcb = 1;
 
-       if (priv->hwts_rx_en)
+       if (priv->hwts_rx_en || priv->rx_filer_enable)
                priv->uses_rxfcb = 1;
 }
 
@@ -351,7 +351,7 @@ static void gfar_mac_rx_config(struct gfar_private *priv)
        u32 rctrl = 0;
 
        if (priv->rx_filer_enable) {
-               rctrl |= RCTRL_FILREN;
+               rctrl |= RCTRL_FILREN | RCTRL_PRSDEP_INIT;
                /* Program the RIR0 reg with the required distribution */
                if (priv->poll_mode == GFAR_SQ_POLLING)
                        gfar_write(&regs->rir0, DEFAULT_2RXQ_RIR0);
@@ -3462,11 +3462,9 @@ static irqreturn_t gfar_error(int irq, void *grp_id)
                netif_dbg(priv, tx_err, dev, "Transmit Error\n");
        }
        if (events & IEVENT_BSY) {
-               dev->stats.rx_errors++;
+               dev->stats.rx_over_errors++;
                atomic64_inc(&priv->extra_stats.rx_bsy);
 
-               gfar_receive(irq, grp_id);
-
                netif_dbg(priv, rx_err, dev, "busy error (rstat: %x)\n",
                          gfar_read(&regs->rstat));
        }
index 6bdc89179b72d6487d031ecda8551453b9268cd4..a33e4a8296015d10906b4b0d02d72e6f5b048277 100644 (file)
@@ -676,14 +676,14 @@ static void ethflow_to_filer_rules (struct gfar_private *priv, u64 ethflow)
        u32 fcr = 0x0, fpr = FPR_FILER_MASK;
 
        if (ethflow & RXH_L2DA) {
-               fcr = RQFCR_PID_DAH |RQFCR_CMP_NOMATCH |
+               fcr = RQFCR_PID_DAH | RQFCR_CMP_NOMATCH |
                      RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0;
                priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
                priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
                gfar_write_filer(priv, priv->cur_filer_idx, fcr, fpr);
                priv->cur_filer_idx = priv->cur_filer_idx - 1;
 
-               fcr = RQFCR_PID_DAL | RQFCR_AND | RQFCR_CMP_NOMATCH |
+               fcr = RQFCR_PID_DAL | RQFCR_CMP_NOMATCH |
                      RQFCR_HASH | RQFCR_AND | RQFCR_HASHTBL_0;
                priv->ftp_rqfpr[priv->cur_filer_idx] = fpr;
                priv->ftp_rqfcr[priv->cur_filer_idx] = fcr;
index 62488a67149d1f0ac38279517427853ebbcec6fc..c0e943aecd1394262757e790b04a6ce1eccda72a 100644 (file)
@@ -386,7 +386,6 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw)
 
        hw->aq.asq.next_to_use = 0;
        hw->aq.asq.next_to_clean = 0;
-       hw->aq.asq.count = hw->aq.num_asq_entries;
 
        /* allocate the ring memory */
        ret_code = i40e_alloc_adminq_asq_ring(hw);
@@ -404,6 +403,7 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw)
                goto init_adminq_free_rings;
 
        /* success! */
+       hw->aq.asq.count = hw->aq.num_asq_entries;
        goto init_adminq_exit;
 
 init_adminq_free_rings:
@@ -445,7 +445,6 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw)
 
        hw->aq.arq.next_to_use = 0;
        hw->aq.arq.next_to_clean = 0;
-       hw->aq.arq.count = hw->aq.num_arq_entries;
 
        /* allocate the ring memory */
        ret_code = i40e_alloc_adminq_arq_ring(hw);
@@ -463,6 +462,7 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw)
                goto init_adminq_free_rings;
 
        /* success! */
+       hw->aq.arq.count = hw->aq.num_arq_entries;
        goto init_adminq_exit;
 
 init_adminq_free_rings:
index e972b5ecbf0b6e1bfb2f11ca93a3f13a18438715..13a5d4cf494bc76e98fd500afe856951703bf244 100644 (file)
@@ -1344,6 +1344,12 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,
                        data[i++] = (i40e_gstrings_veb_stats[j].sizeof_stat ==
                                     sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
                }
+               for (j = 0; j < I40E_MAX_TRAFFIC_CLASS; j++) {
+                       data[i++] = veb->tc_stats.tc_tx_packets[j];
+                       data[i++] = veb->tc_stats.tc_tx_bytes[j];
+                       data[i++] = veb->tc_stats.tc_rx_packets[j];
+                       data[i++] = veb->tc_stats.tc_rx_bytes[j];
+               }
        }
        for (j = 0; j < I40E_GLOBAL_STATS_LEN; j++) {
                p = (char *)pf + i40e_gstrings_stats[j].stat_offset;
index 2fdf978ae6a5d10a6751f3ec702ef3636fca543f..3dd26cdd0bf27365ec60d084c027800bee128f93 100644 (file)
@@ -7911,6 +7911,7 @@ static int i40e_sw_init(struct i40e_pf *pf)
        if (pf->hw.func_caps.vmdq) {
                pf->num_vmdq_vsis = I40E_DEFAULT_NUM_VMDQ_VSI;
                pf->flags |= I40E_FLAG_VMDQ_ENABLED;
+               pf->num_vmdq_qps = i40e_default_queues_per_vmdq(pf);
        }
 
 #ifdef I40E_FCOE
@@ -8389,6 +8390,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
 
        netdev->hw_enc_features |= NETIF_F_IP_CSUM       |
                                  NETIF_F_GSO_UDP_TUNNEL |
+                                 NETIF_F_GSO_GRE        |
                                  NETIF_F_TSO;
 
        netdev->features = NETIF_F_SG                  |
@@ -8396,6 +8398,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
                           NETIF_F_SCTP_CSUM           |
                           NETIF_F_HIGHDMA             |
                           NETIF_F_GSO_UDP_TUNNEL      |
+                          NETIF_F_GSO_GRE             |
                           NETIF_F_HW_VLAN_CTAG_TX     |
                           NETIF_F_HW_VLAN_CTAG_RX     |
                           NETIF_F_HW_VLAN_CTAG_FILTER |
index 929d47152bf271b1ddba3d8dc284d1941131261a..a23ebfd5cd254014cd0632979aa441a2a6f6eadf 100644 (file)
@@ -373,7 +373,6 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw)
 
        hw->aq.asq.next_to_use = 0;
        hw->aq.asq.next_to_clean = 0;
-       hw->aq.asq.count = hw->aq.num_asq_entries;
 
        /* allocate the ring memory */
        ret_code = i40e_alloc_adminq_asq_ring(hw);
@@ -391,6 +390,7 @@ static i40e_status i40e_init_asq(struct i40e_hw *hw)
                goto init_adminq_free_rings;
 
        /* success! */
+       hw->aq.asq.count = hw->aq.num_asq_entries;
        goto init_adminq_exit;
 
 init_adminq_free_rings:
@@ -432,7 +432,6 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw)
 
        hw->aq.arq.next_to_use = 0;
        hw->aq.arq.next_to_clean = 0;
-       hw->aq.arq.count = hw->aq.num_arq_entries;
 
        /* allocate the ring memory */
        ret_code = i40e_alloc_adminq_arq_ring(hw);
@@ -450,6 +449,7 @@ static i40e_status i40e_init_arq(struct i40e_hw *hw)
                goto init_adminq_free_rings;
 
        /* success! */
+       hw->aq.arq.count = hw->aq.num_arq_entries;
        goto init_adminq_exit;
 
 init_adminq_free_rings:
index 960169efe636a659241f7e8fae10706fd0503939..dfb6d5f79a1002a0101e4ae7fe2d7bf466f49c6f 100644 (file)
@@ -759,11 +759,23 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq,
 
        desc->l4i_chk = 0;
        desc->byte_cnt = length;
-       desc->buf_ptr = dma_map_single(dev->dev.parent, data,
-                                      length, DMA_TO_DEVICE);
-       if (unlikely(dma_mapping_error(dev->dev.parent, desc->buf_ptr))) {
-               WARN(1, "dma_map_single failed!\n");
-               return -ENOMEM;
+
+       if (length <= 8 && (uintptr_t)data & 0x7) {
+               /* Copy unaligned small data fragment to TSO header data area */
+               memcpy(txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE,
+                      data, length);
+               desc->buf_ptr = txq->tso_hdrs_dma
+                       + txq->tx_curr_desc * TSO_HEADER_SIZE;
+       } else {
+               /* Alignment is okay, map buffer and hand off to hardware */
+               txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE;
+               desc->buf_ptr = dma_map_single(dev->dev.parent, data,
+                       length, DMA_TO_DEVICE);
+               if (unlikely(dma_mapping_error(dev->dev.parent,
+                                              desc->buf_ptr))) {
+                       WARN(1, "dma_map_single failed!\n");
+                       return -ENOMEM;
+               }
        }
 
        cmd_sts = BUFFER_OWNED_BY_DMA;
@@ -779,7 +791,8 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq,
 }
 
 static inline void
-txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length)
+txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length,
+               u32 *first_cmd_sts, bool first_desc)
 {
        struct mv643xx_eth_private *mp = txq_to_mp(txq);
        int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
@@ -788,6 +801,7 @@ txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length)
        int ret;
        u32 cmd_csum = 0;
        u16 l4i_chk = 0;
+       u32 cmd_sts;
 
        tx_index = txq->tx_curr_desc;
        desc = &txq->tx_desc_area[tx_index];
@@ -803,9 +817,17 @@ txq_put_hdr_tso(struct sk_buff *skb, struct tx_queue *txq, int length)
        desc->byte_cnt = hdr_len;
        desc->buf_ptr = txq->tso_hdrs_dma +
                        txq->tx_curr_desc * TSO_HEADER_SIZE;
-       desc->cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA  | TX_FIRST_DESC |
+       cmd_sts = cmd_csum | BUFFER_OWNED_BY_DMA  | TX_FIRST_DESC |
                                   GEN_CRC;
 
+       /* Defer updating the first command descriptor until all
+        * following descriptors have been written.
+        */
+       if (first_desc)
+               *first_cmd_sts = cmd_sts;
+       else
+               desc->cmd_sts = cmd_sts;
+
        txq->tx_curr_desc++;
        if (txq->tx_curr_desc == txq->tx_ring_size)
                txq->tx_curr_desc = 0;
@@ -819,6 +841,8 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
        int desc_count = 0;
        struct tso_t tso;
        int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+       struct tx_desc *first_tx_desc;
+       u32 first_cmd_sts = 0;
 
        /* Count needed descriptors */
        if ((txq->tx_desc_count + tso_count_descs(skb)) >= txq->tx_ring_size) {
@@ -826,11 +850,14 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
                return -EBUSY;
        }
 
+       first_tx_desc = &txq->tx_desc_area[txq->tx_curr_desc];
+
        /* Initialize the TSO handler, and prepare the first payload */
        tso_start(skb, &tso);
 
        total_len = skb->len - hdr_len;
        while (total_len > 0) {
+               bool first_desc = (desc_count == 0);
                char *hdr;
 
                data_left = min_t(int, skb_shinfo(skb)->gso_size, total_len);
@@ -840,7 +867,8 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
                /* prepare packet headers: MAC + IP + TCP */
                hdr = txq->tso_hdrs + txq->tx_curr_desc * TSO_HEADER_SIZE;
                tso_build_hdr(skb, hdr, &tso, data_left, total_len == 0);
-               txq_put_hdr_tso(skb, txq, data_left);
+               txq_put_hdr_tso(skb, txq, data_left, &first_cmd_sts,
+                               first_desc);
 
                while (data_left > 0) {
                        int size;
@@ -860,6 +888,10 @@ static int txq_submit_tso(struct tx_queue *txq, struct sk_buff *skb,
        __skb_queue_tail(&txq->tx_skb, skb);
        skb_tx_timestamp(skb);
 
+       /* ensure all other descriptors are written before first cmd_sts */
+       wmb();
+       first_tx_desc->cmd_sts = first_cmd_sts;
+
        /* clear TX_END status */
        mp->work_tx_end &= ~(1 << txq->index);
 
@@ -2785,8 +2817,10 @@ static int mv643xx_eth_shared_of_probe(struct platform_device *pdev)
 
        for_each_available_child_of_node(np, pnp) {
                ret = mv643xx_eth_shared_of_add_port(pdev, pnp);
-               if (ret)
+               if (ret) {
+                       of_node_put(pnp);
                        return ret;
+               }
        }
        return 0;
 }
index 0a3202047569c707a28f62376466e72fdcd8cd00..2177e56ed0be7d18ee40d2428b69003bd6f8cca5 100644 (file)
@@ -2398,7 +2398,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
                        }
                }
 
-               memset(&priv->mfunc.master.cmd_eqe, 0, dev->caps.eqe_size);
+               memset(&priv->mfunc.master.cmd_eqe, 0, sizeof(struct mlx4_eqe));
                priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD;
                INIT_WORK(&priv->mfunc.master.comm_work,
                          mlx4_master_comm_channel);
index 494e7762fdb19efb83d76f187b88fd37d422d5b5..4421bf5463f67159618c3a4c572b4e9ebc04dd7b 100644 (file)
@@ -964,6 +964,8 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
                        tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_SVLAN;
                else if (vlan_proto == ETH_P_8021Q)
                        tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_CVLAN;
+               else
+                       tx_desc->ctrl.ins_vlan = 0;
 
                tx_desc->ctrl.fence_size = real_size;
 
index 8e81e53c370e7d54e6367c012212cccc73ee26fd..603d1c3d3b2ea1a8a98de110f1e777f1d751e649 100644 (file)
@@ -196,7 +196,7 @@ static void slave_event(struct mlx4_dev *dev, u8 slave, struct mlx4_eqe *eqe)
                return;
        }
 
-       memcpy(s_eqe, eqe, dev->caps.eqe_size - 1);
+       memcpy(s_eqe, eqe, sizeof(struct mlx4_eqe) - 1);
        s_eqe->slave_id = slave;
        /* ensure all information is written before setting the ownersip bit */
        dma_wmb();
@@ -1364,6 +1364,10 @@ int mlx4_test_interrupts(struct mlx4_dev *dev)
         * and performing a NOP command
         */
        for(i = 0; !err && (i < dev->caps.num_comp_vectors); ++i) {
+               /* Make sure request_irq was called */
+               if (!priv->eq_table.eq[i].have_irq)
+                       continue;
+
                /* Temporary use polling for command completions */
                mlx4_cmd_use_polling(dev);
 
index 006757f80988bcb71cfc352542305b61310ef40f..cc3a9897574c542ee368ab067c109128ce89b290 100644 (file)
@@ -2669,14 +2669,11 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
 
        if (msi_x) {
                int nreq = dev->caps.num_ports * num_online_cpus() + 1;
-               bool shared_ports = false;
 
                nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
                             nreq);
-               if (nreq > MAX_MSIX) {
+               if (nreq > MAX_MSIX)
                        nreq = MAX_MSIX;
-                       shared_ports = true;
-               }
 
                entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
                if (!entries)
@@ -2699,9 +2696,6 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
                bitmap_zero(priv->eq_table.eq[MLX4_EQ_ASYNC].actv_ports.ports,
                            dev->caps.num_ports);
 
-               if (MLX4_IS_LEGACY_EQ_MODE(dev->caps))
-                       shared_ports = true;
-
                for (i = 0; i < dev->caps.num_comp_vectors + 1; i++) {
                        if (i == MLX4_EQ_ASYNC)
                                continue;
@@ -2709,7 +2703,7 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
                        priv->eq_table.eq[i].irq =
                                entries[i + 1 - !!(i > MLX4_EQ_ASYNC)].vector;
 
-                       if (shared_ports) {
+                       if (MLX4_IS_LEGACY_EQ_MODE(dev->caps)) {
                                bitmap_fill(priv->eq_table.eq[i].actv_ports.ports,
                                            dev->caps.num_ports);
                                /* We don't set affinity hint when there
index e71563ce05d1bc34123fd4aa63348d569adf4c57..22d603f7827333e2dce6eab7be6ed6acd5a14cdb 100644 (file)
@@ -598,6 +598,8 @@ void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv)
                return;
 
        priv->vlan.filter_disabled = false;
+       if (priv->netdev->flags & IFF_PROMISC)
+               return;
        mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
 }
 
@@ -607,6 +609,8 @@ void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv)
                return;
 
        priv->vlan.filter_disabled = true;
+       if (priv->netdev->flags & IFF_PROMISC)
+               return;
        mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID, 0);
 }
 
@@ -717,8 +721,12 @@ void mlx5e_set_rx_mode_work(struct work_struct *work)
        bool enable_broadcast  = !ea->broadcast_enabled &&  broadcast_enabled;
        bool disable_broadcast =  ea->broadcast_enabled && !broadcast_enabled;
 
-       if (enable_promisc)
+       if (enable_promisc) {
                mlx5e_add_eth_addr_rule(priv, &ea->promisc, MLX5E_PROMISC);
+               if (!priv->vlan.filter_disabled)
+                       mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
+                                           0);
+       }
        if (enable_allmulti)
                mlx5e_add_eth_addr_rule(priv, &ea->allmulti, MLX5E_ALLMULTI);
        if (enable_broadcast)
@@ -730,8 +738,12 @@ void mlx5e_set_rx_mode_work(struct work_struct *work)
                mlx5e_del_eth_addr_from_flow_table(priv, &ea->broadcast);
        if (disable_allmulti)
                mlx5e_del_eth_addr_from_flow_table(priv, &ea->allmulti);
-       if (disable_promisc)
+       if (disable_promisc) {
+               if (!priv->vlan.filter_disabled)
+                       mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_VID,
+                                           0);
                mlx5e_del_eth_addr_from_flow_table(priv, &ea->promisc);
+       }
 
        ea->promisc_enabled   = promisc_enabled;
        ea->allmulti_enabled  = allmulti_enabled;
index 821caaab9bfb04697fb0424cb8498bdc9eacabed..3b9480fa3403dee018931c16b678f5ec6c98e913 100644 (file)
@@ -311,7 +311,7 @@ static int mlx5_query_port_pvlc(struct mlx5_core_dev *dev, u32 *pvlc,
        int err;
 
        memset(in, 0, sizeof(in));
-       MLX5_SET(ptys_reg, in, local_port, local_port);
+       MLX5_SET(pvlc_reg, in, local_port, local_port);
 
        err = mlx5_core_access_reg(dev, in, sizeof(in), pvlc,
                                   pvlc_size, MLX5_REG_PVLC, 0, 0);
index dbcaf5df8967e828f85648de4edce281860f2a61..28c19cc1a17c5f44a7b15103ce168651502843d8 100644 (file)
@@ -374,26 +374,31 @@ static int __mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core,
        int err;
        int ret;
 
+       mlxsw_core->emad.trans_active = true;
+
        err = mlxsw_core_skb_transmit(mlxsw_core->driver_priv, skb, tx_info);
        if (err) {
                dev_err(mlxsw_core->bus_info->dev, "Failed to transmit EMAD (tid=%llx)\n",
                        mlxsw_core->emad.tid);
                dev_kfree_skb(skb);
-               return err;
+               goto trans_inactive_out;
        }
 
-       mlxsw_core->emad.trans_active = true;
        ret = wait_event_timeout(mlxsw_core->emad.wait,
                                 !(mlxsw_core->emad.trans_active),
                                 msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_MS));
        if (!ret) {
                dev_warn(mlxsw_core->bus_info->dev, "EMAD timed-out (tid=%llx)\n",
                         mlxsw_core->emad.tid);
-               mlxsw_core->emad.trans_active = false;
-               return -EIO;
+               err = -EIO;
+               goto trans_inactive_out;
        }
 
        return 0;
+
+trans_inactive_out:
+       mlxsw_core->emad.trans_active = false;
+       return err;
 }
 
 static int mlxsw_emad_process_status(struct mlxsw_core *mlxsw_core,
index ffd55d030ce28dbf902f6990a0dfb7f96b08a766..36fb1cec53c98e9c7dad0cb7b9b59051d7e0c352 100644 (file)
@@ -187,6 +187,7 @@ __mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift)
 {
        u16 max_index, be_index;
        u16 offset;             /* byte offset inside the array */
+       u8 in_byte_index;
 
        BUG_ON(index && !item->element_size);
        if (item->offset % sizeof(u32) != 0 ||
@@ -199,7 +200,8 @@ __mlxsw_item_bit_array_offset(struct mlxsw_item *item, u16 index, u8 *shift)
        max_index = (item->size.bytes << 3) / item->element_size - 1;
        be_index = max_index - index;
        offset = be_index * item->element_size >> 3;
-       *shift = index % (BITS_PER_BYTE / item->element_size) << 1;
+       in_byte_index  = index % (BITS_PER_BYTE / item->element_size);
+       *shift = in_byte_index * item->element_size;
 
        return item->offset + offset;
 }
index 462cea31ecbb7be6387512dc741286d7fb56658e..cef866c37648ca0c93d4f109eb9d4f3671fcd890 100644 (file)
@@ -1582,11 +1582,11 @@ static int mlxsw_pci_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod,
 
        if (in_mbox)
                memcpy(mlxsw_pci->cmd.in_mbox.buf, in_mbox, in_mbox_size);
-       mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_HI, in_mapaddr >> 32);
-       mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_LO, in_mapaddr);
+       mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_HI, upper_32_bits(in_mapaddr));
+       mlxsw_pci_write32(mlxsw_pci, CIR_IN_PARAM_LO, lower_32_bits(in_mapaddr));
 
-       mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_HI, out_mapaddr >> 32);
-       mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_LO, out_mapaddr);
+       mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_HI, upper_32_bits(out_mapaddr));
+       mlxsw_pci_write32(mlxsw_pci, CIR_OUT_PARAM_LO, lower_32_bits(out_mapaddr));
 
        mlxsw_pci_write32(mlxsw_pci, CIR_IN_MODIFIER, in_mod);
        mlxsw_pci_write32(mlxsw_pci, CIR_TOKEN, 0);
index 3e52ee93438c00188d0efe6482cfbd9f686b8ee9..62cbbd1ada8da6a5d8343beb394b67dc5af6a81c 100644 (file)
@@ -1069,9 +1069,9 @@ static int mlxsw_sx_port_create(struct mlxsw_sx *mlxsw_sx, u8 local_port)
        return 0;
 
 err_register_netdev:
-err_port_admin_status_set:
 err_port_mac_learning_mode_set:
 err_port_stp_state_set:
+err_port_admin_status_set:
 err_port_mtu_set:
 err_port_speed_set:
 err_port_swid_set:
index a41bb5e6b954f0e6b40375b76a52ed8a254cdb18..75e88f4c15315c84c20106022f38edc1dccf75e7 100644 (file)
@@ -4076,6 +4076,8 @@ static void nv_do_nic_poll(unsigned long data)
        struct fe_priv *np = netdev_priv(dev);
        u8 __iomem *base = get_hwbase(dev);
        u32 mask = 0;
+       unsigned long flags;
+       unsigned int irq = 0;
 
        /*
         * First disable irq(s) and then
@@ -4085,25 +4087,27 @@ static void nv_do_nic_poll(unsigned long data)
 
        if (!using_multi_irqs(dev)) {
                if (np->msi_flags & NV_MSI_X_ENABLED)
-                       disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
+                       irq = np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector;
                else
-                       disable_irq_lockdep(np->pci_dev->irq);
+                       irq = np->pci_dev->irq;
                mask = np->irqmask;
        } else {
                if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
-                       disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+                       irq = np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector;
                        mask |= NVREG_IRQ_RX_ALL;
                }
                if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) {
-                       disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
+                       irq = np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector;
                        mask |= NVREG_IRQ_TX_ALL;
                }
                if (np->nic_poll_irq & NVREG_IRQ_OTHER) {
-                       disable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
+                       irq = np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector;
                        mask |= NVREG_IRQ_OTHER;
                }
        }
-       /* disable_irq() contains synchronize_irq, thus no irq handler can run now */
+
+       disable_irq_nosync_lockdep_irqsave(irq, &flags);
+       synchronize_irq(irq);
 
        if (np->recover_error) {
                np->recover_error = 0;
@@ -4156,28 +4160,22 @@ static void nv_do_nic_poll(unsigned long data)
                        nv_nic_irq_optimized(0, dev);
                else
                        nv_nic_irq(0, dev);
-               if (np->msi_flags & NV_MSI_X_ENABLED)
-                       enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector);
-               else
-                       enable_irq_lockdep(np->pci_dev->irq);
        } else {
                if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) {
                        np->nic_poll_irq &= ~NVREG_IRQ_RX_ALL;
                        nv_nic_irq_rx(0, dev);
-                       enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
                }
                if (np->nic_poll_irq & NVREG_IRQ_TX_ALL) {
                        np->nic_poll_irq &= ~NVREG_IRQ_TX_ALL;
                        nv_nic_irq_tx(0, dev);
-                       enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector);
                }
                if (np->nic_poll_irq & NVREG_IRQ_OTHER) {
                        np->nic_poll_irq &= ~NVREG_IRQ_OTHER;
                        nv_nic_irq_other(0, dev);
-                       enable_irq_lockdep(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector);
                }
        }
 
+       enable_irq_lockdep_irqrestore(irq, &flags);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
index 66fd868152e579a4ba3483fd4726f0e9d9662436..b159ef8303cc3e65d1e374367d19ca590d934901 100644 (file)
@@ -476,13 +476,12 @@ static void __lpc_get_mac(struct netdata_local *pldat, u8 *mac)
        mac[5] = tmp >> 8;
 }
 
-static void __lpc_eth_clock_enable(struct netdata_local *pldat,
-                                  bool enable)
+static void __lpc_eth_clock_enable(struct netdata_local *pldat, bool enable)
 {
        if (enable)
-               clk_enable(pldat->clk);
+               clk_prepare_enable(pldat->clk);
        else
-               clk_disable(pldat->clk);
+               clk_disable_unprepare(pldat->clk);
 }
 
 static void __lpc_params_setup(struct netdata_local *pldat)
@@ -1494,7 +1493,7 @@ err_out_free_irq:
 err_out_iounmap:
        iounmap(pldat->net_base);
 err_out_disable_clocks:
-       clk_disable(pldat->clk);
+       clk_disable_unprepare(pldat->clk);
        clk_put(pldat->clk);
 err_out_free_dev:
        free_netdev(ndev);
@@ -1519,7 +1518,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
        iounmap(pldat->net_base);
        mdiobus_unregister(pldat->mii_bus);
        mdiobus_free(pldat->mii_bus);
-       clk_disable(pldat->clk);
+       clk_disable_unprepare(pldat->clk);
        clk_put(pldat->clk);
        free_netdev(ndev);
 
@@ -1540,7 +1539,7 @@ static int lpc_eth_drv_suspend(struct platform_device *pdev,
                if (netif_running(ndev)) {
                        netif_device_detach(ndev);
                        __lpc_eth_shutdown(pldat);
-                       clk_disable(pldat->clk);
+                       clk_disable_unprepare(pldat->clk);
 
                        /*
                         * Reset again now clock is disable to be sure
index 257ea713b4c1564fa680acfcf7ad760268ea0df6..a484d8beb8557935b30251dc70bf3ef3d3b64dbc 100644 (file)
@@ -1127,7 +1127,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
        struct sh_eth_txdesc *txdesc = NULL;
        int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring;
        int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring;
-       int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1;
+       int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN + 32 - 1;
        dma_addr_t dma_addr;
 
        mdp->cur_rx = 0;
@@ -1148,8 +1148,8 @@ static void sh_eth_ring_format(struct net_device *ndev)
 
                /* RX descriptor */
                rxdesc = &mdp->rx_ring[i];
-               /* The size of the buffer is a multiple of 16 bytes. */
-               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
+               /* The size of the buffer is a multiple of 32 bytes. */
+               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 32);
                dma_addr = dma_map_single(&ndev->dev, skb->data,
                                          rxdesc->buffer_length,
                                          DMA_FROM_DEVICE);
@@ -1450,7 +1450,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
        struct sk_buff *skb;
        u16 pkt_len = 0;
        u32 desc_status;
-       int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1;
+       int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN + 32 - 1;
        dma_addr_t dma_addr;
 
        boguscnt = min(boguscnt, *quota);
@@ -1506,7 +1506,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                        if (mdp->cd->rpadir)
                                skb_reserve(skb, NET_IP_ALIGN);
                        dma_unmap_single(&ndev->dev, rxdesc->addr,
-                                        ALIGN(mdp->rx_buf_sz, 16),
+                                        ALIGN(mdp->rx_buf_sz, 32),
                                         DMA_FROM_DEVICE);
                        skb_put(skb, pkt_len);
                        skb->protocol = eth_type_trans(skb, ndev);
@@ -1524,8 +1524,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
        for (; mdp->cur_rx - mdp->dirty_rx > 0; mdp->dirty_rx++) {
                entry = mdp->dirty_rx % mdp->num_rx_ring;
                rxdesc = &mdp->rx_ring[entry];
-               /* The size of the buffer is 16 byte boundary. */
-               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
+               /* The size of the buffer is 32 byte boundary. */
+               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 32);
 
                if (mdp->rx_skbuff[entry] == NULL) {
                        skb = netdev_alloc_skb(ndev, skbuff_size);
index 8fc90f1c872c6fe5afe2105aae62c54d8283800f..874fb297e96c563525a5d275a8e2239b6ab41725 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
+#include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/of_device.h>
 #include <linux/if_vlan.h>
@@ -365,6 +366,7 @@ struct cpsw_priv {
        spinlock_t                      lock;
        struct platform_device          *pdev;
        struct net_device               *ndev;
+       struct device_node              *phy_node;
        struct napi_struct              napi_rx;
        struct napi_struct              napi_tx;
        struct device                   *dev;
@@ -1145,7 +1147,11 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
                cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
                                   1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
 
-       slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
+       if (priv->phy_node)
+               slave->phy = of_phy_connect(priv->ndev, priv->phy_node,
+                                &cpsw_adjust_link, 0, slave->data->phy_if);
+       else
+               slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
                                 &cpsw_adjust_link, slave->data->phy_if);
        if (IS_ERR(slave->phy)) {
                dev_err(priv->dev, "phy %s not found on slave %d\n",
@@ -1934,11 +1940,12 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
        slave->port_vlan = data->dual_emac_res_vlan;
 }
 
-static int cpsw_probe_dt(struct cpsw_platform_data *data,
+static int cpsw_probe_dt(struct cpsw_priv *priv,
                         struct platform_device *pdev)
 {
        struct device_node *node = pdev->dev.of_node;
        struct device_node *slave_node;
+       struct cpsw_platform_data *data = &priv->data;
        int i = 0, ret;
        u32 prop;
 
@@ -2029,6 +2036,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                if (strcmp(slave_node->name, "slave"))
                        continue;
 
+               priv->phy_node = of_parse_phandle(slave_node, "phy-handle", 0);
                parp = of_get_property(slave_node, "phy_id", &lenp);
                if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) {
                        dev_err(&pdev->dev, "Missing slave[%d] phy_id property\n", i);
@@ -2044,7 +2052,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                }
                snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
                         PHY_ID_FMT, mdio->name, phyid);
-
                slave_data->phy_if = of_get_phy_mode(slave_node);
                if (slave_data->phy_if < 0) {
                        dev_err(&pdev->dev, "Missing or malformed slave[%d] phy-mode property\n",
@@ -2240,7 +2247,7 @@ static int cpsw_probe(struct platform_device *pdev)
        /* Select default pin state */
        pinctrl_pm_select_default_state(&pdev->dev);
 
-       if (cpsw_probe_dt(&priv->data, pdev)) {
+       if (cpsw_probe_dt(priv, pdev)) {
                dev_err(&pdev->dev, "cpsw: platform data missing\n");
                ret = -ENODEV;
                goto clean_runtime_disable_ret;
index 6bff8d82ceab7a428e73048504a5dd63f4a1c1bd..4e70e7586a0918a045008b7e54e807f0f11e2de9 100644 (file)
@@ -2637,8 +2637,10 @@ static void init_secondary_ports(struct gbe_priv *gbe_dev,
                        mac_phy_link = true;
 
                slave->open = true;
-               if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves)
+               if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) {
+                       of_node_put(port);
                        break;
+               }
        }
 
        /* of_phy_connect() is needed only for MAC-PHY interface */
@@ -3137,8 +3139,10 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
                        continue;
                }
                gbe_dev->num_slaves++;
-               if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves)
+               if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves) {
+                       of_node_put(interface);
                        break;
+               }
        }
        of_node_put(interfaces);
 
index a83263743665411eacb0ca845e23f52db612866c..2b7550c43f7800fe36e54fafacabfcd921c408f4 100644 (file)
@@ -2134,10 +2134,11 @@ static int rhine_rx(struct net_device *dev, int limit)
                        }
 
                        skb_put(skb, pkt_len);
-                       skb->protocol = eth_type_trans(skb, dev);
 
                        rhine_rx_vlan_tag(skb, desc, data_size);
 
+                       skb->protocol = eth_type_trans(skb, dev);
+
                        netif_receive_skb(skb);
 
                        u64_stats_update_begin(&rp->rx_stats.syncp);
index 8f5c02eed47de09883b43b8b587717993064ef0b..445071c163cb3b45412af65e58353a7eae26842a 100644 (file)
@@ -594,14 +594,12 @@ static struct rtable *geneve_get_rt(struct sk_buff *skb,
        rt = ip_route_output_key(geneve->net, fl4);
        if (IS_ERR(rt)) {
                netdev_dbg(dev, "no route to %pI4\n", &fl4->daddr);
-               dev->stats.tx_carrier_errors++;
-               return rt;
+               return ERR_PTR(-ENETUNREACH);
        }
        if (rt->dst.dev == dev) { /* is this necessary? */
                netdev_dbg(dev, "circular route to %pI4\n", &fl4->daddr);
-               dev->stats.collisions++;
                ip_rt_put(rt);
-               return ERR_PTR(-EINVAL);
+               return ERR_PTR(-ELOOP);
        }
        return rt;
 }
@@ -627,12 +625,12 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
        struct ip_tunnel_info *info = NULL;
        struct rtable *rt = NULL;
        const struct iphdr *iip; /* interior IP header */
+       int err = -EINVAL;
        struct flowi4 fl4;
        __u8 tos, ttl;
        __be16 sport;
        bool udp_csum;
        __be16 df;
-       int err;
 
        if (geneve->collect_md) {
                info = skb_tunnel_info(skb);
@@ -647,7 +645,7 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
        rt = geneve_get_rt(skb, dev, &fl4, info);
        if (IS_ERR(rt)) {
                netdev_dbg(dev, "no route to %pI4\n", &fl4.daddr);
-               dev->stats.tx_carrier_errors++;
+               err = PTR_ERR(rt);
                goto tx_error;
        }
 
@@ -699,10 +697,37 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
 tx_error:
        dev_kfree_skb(skb);
 err:
-       dev->stats.tx_errors++;
+       if (err == -ELOOP)
+               dev->stats.collisions++;
+       else if (err == -ENETUNREACH)
+               dev->stats.tx_carrier_errors++;
+       else
+               dev->stats.tx_errors++;
        return NETDEV_TX_OK;
 }
 
+static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct ip_tunnel_info *info = skb_tunnel_info(skb);
+       struct geneve_dev *geneve = netdev_priv(dev);
+       struct rtable *rt;
+       struct flowi4 fl4;
+
+       if (ip_tunnel_info_af(info) != AF_INET)
+               return -EINVAL;
+
+       rt = geneve_get_rt(skb, dev, &fl4, info);
+       if (IS_ERR(rt))
+               return PTR_ERR(rt);
+
+       ip_rt_put(rt);
+       info->key.u.ipv4.src = fl4.saddr;
+       info->key.tp_src = udp_flow_src_port(geneve->net, skb,
+                                            1, USHRT_MAX, true);
+       info->key.tp_dst = geneve->dst_port;
+       return 0;
+}
+
 static const struct net_device_ops geneve_netdev_ops = {
        .ndo_init               = geneve_init,
        .ndo_uninit             = geneve_uninit,
@@ -713,6 +738,7 @@ static const struct net_device_ops geneve_netdev_ops = {
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_fill_metadata_dst  = geneve_fill_metadata_dst,
 };
 
 static void geneve_get_drvinfo(struct net_device *dev,
@@ -870,14 +896,14 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
        __be16 dst_port = htons(GENEVE_UDP_PORT);
        __u8 ttl = 0, tos = 0;
        bool metadata = false;
-       __be32 rem_addr;
-       __u32 vni;
+       __be32 rem_addr = 0;
+       __u32 vni = 0;
 
-       if (!data[IFLA_GENEVE_ID] || !data[IFLA_GENEVE_REMOTE])
-               return -EINVAL;
+       if (data[IFLA_GENEVE_ID])
+               vni = nla_get_u32(data[IFLA_GENEVE_ID]);
 
-       vni = nla_get_u32(data[IFLA_GENEVE_ID]);
-       rem_addr = nla_get_in_addr(data[IFLA_GENEVE_REMOTE]);
+       if (data[IFLA_GENEVE_REMOTE])
+               rem_addr = nla_get_in_addr(data[IFLA_GENEVE_REMOTE]);
 
        if (data[IFLA_GENEVE_TTL])
                ttl = nla_get_u8(data[IFLA_GENEVE_TTL]);
index 248478c6f6e49522681a3eeb8a80fd8eaefd32fc..197c93937c2d577e56cf7fab8dcef07313bf75f4 100644 (file)
@@ -137,7 +137,7 @@ static const struct proto_ops macvtap_socket_ops;
 #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
                      NETIF_F_TSO6 | NETIF_F_UFO)
 #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
-#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG)
+#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG | NETIF_F_FRAGLIST)
 
 static struct macvlan_dev *macvtap_get_vlan_rcu(const struct net_device *dev)
 {
index c5ad98ace5d0abeff5d6ef8f3f028e537b241a8e..436972b2a746a23d27bac9ebb4e23d17b6d54715 100644 (file)
@@ -122,6 +122,11 @@ config MICREL_PHY
        ---help---
          Supports the KSZ9021, VSC8201, KS8001 PHYs.
 
+config DP83848_PHY
+       tristate "Driver for Texas Instruments DP83848 PHY"
+       ---help---
+         Supports the DP83848 PHY.
+
 config DP83867_PHY
        tristate "Drivers for Texas Instruments DP83867 Gigabit PHY"
        ---help---
@@ -168,8 +173,6 @@ config MDIO_OCTEON
          busses. It is required by the Octeon and ThunderX ethernet device
          drivers.
 
-         If in doubt, say Y.
-
 config MDIO_SUN4I
        tristate "Allwinner sun4i MDIO interface support"
        depends on ARCH_SUNXI
index 87f079c4b2c7ab16e5577b0b86fdd8509f9b7c8f..b74822463930051f60151beec04c5ccfe0e7bd0b 100644 (file)
@@ -24,6 +24,7 @@ obj-$(CONFIG_MDIO_BITBANG)    += mdio-bitbang.o
 obj-$(CONFIG_MDIO_GPIO)                += mdio-gpio.o
 obj-$(CONFIG_NATIONAL_PHY)     += national.o
 obj-$(CONFIG_DP83640_PHY)      += dp83640.o
+obj-$(CONFIG_DP83848_PHY)      += dp83848.o
 obj-$(CONFIG_DP83867_PHY)      += dp83867.o
 obj-$(CONFIG_STE10XP)          += ste10Xp.o
 obj-$(CONFIG_MICREL_PHY)       += micrel.o
diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c
new file mode 100644 (file)
index 0000000..5ce9bef
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Driver for the Texas Instruments DP83848 PHY
+ *
+ * Copyright (C) 2015 Texas Instruments Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/phy.h>
+
+#define DP83848_PHY_ID                 0x20005c90
+
+/* Registers */
+#define DP83848_MICR                   0x11
+#define DP83848_MISR                   0x12
+
+/* MICR Register Fields */
+#define DP83848_MICR_INT_OE            BIT(0) /* Interrupt Output Enable */
+#define DP83848_MICR_INTEN             BIT(1) /* Interrupt Enable */
+
+/* MISR Register Fields */
+#define DP83848_MISR_RHF_INT_EN                BIT(0) /* Receive Error Counter */
+#define DP83848_MISR_FHF_INT_EN                BIT(1) /* False Carrier Counter */
+#define DP83848_MISR_ANC_INT_EN                BIT(2) /* Auto-negotiation complete */
+#define DP83848_MISR_DUP_INT_EN                BIT(3) /* Duplex Status */
+#define DP83848_MISR_SPD_INT_EN                BIT(4) /* Speed status */
+#define DP83848_MISR_LINK_INT_EN       BIT(5) /* Link status */
+#define DP83848_MISR_ED_INT_EN         BIT(6) /* Energy detect */
+#define DP83848_MISR_LQM_INT_EN                BIT(7) /* Link Quality Monitor */
+
+static int dp83848_ack_interrupt(struct phy_device *phydev)
+{
+       int err = phy_read(phydev, DP83848_MISR);
+
+       return err < 0 ? err : 0;
+}
+
+static int dp83848_config_intr(struct phy_device *phydev)
+{
+       int err;
+
+       if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+               err = phy_write(phydev, DP83848_MICR,
+                               DP83848_MICR_INT_OE |
+                               DP83848_MICR_INTEN);
+               if (err < 0)
+                       return err;
+
+               return phy_write(phydev, DP83848_MISR,
+                                DP83848_MISR_ANC_INT_EN |
+                                DP83848_MISR_DUP_INT_EN |
+                                DP83848_MISR_SPD_INT_EN |
+                                DP83848_MISR_LINK_INT_EN);
+       }
+
+       return phy_write(phydev, DP83848_MICR, 0x0);
+}
+
+static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
+       { DP83848_PHY_ID, 0xfffffff0 },
+       { }
+};
+MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
+
+static struct phy_driver dp83848_driver[] = {
+       {
+               .phy_id         = DP83848_PHY_ID,
+               .phy_id_mask    = 0xfffffff0,
+               .name           = "TI DP83848",
+               .features       = PHY_BASIC_FEATURES,
+               .flags          = PHY_HAS_INTERRUPT,
+
+               .soft_reset     = genphy_soft_reset,
+               .config_init    = genphy_config_init,
+               .suspend        = genphy_suspend,
+               .resume         = genphy_resume,
+               .config_aneg    = genphy_config_aneg,
+               .read_status    = genphy_read_status,
+
+               /* IRQ related */
+               .ack_interrupt  = dp83848_ack_interrupt,
+               .config_intr    = dp83848_config_intr,
+
+               .driver         = { .owner = THIS_MODULE, },
+       },
+};
+module_phy_driver(dp83848_driver);
+
+MODULE_DESCRIPTION("Texas Instruments DP83848 PHY driver");
+MODULE_AUTHOR("Andrew F. Davis <afd@ti.com");
+MODULE_LICENSE("GPL");
index 2377c1341172f6ac6fb56eeaf835b7fc577e1593..7fde454fbc4f1762b2c0bb35cf41f60580fd16ed 100644 (file)
@@ -113,12 +113,14 @@ static int mdio_mux_mmioreg_probe(struct platform_device *pdev)
                if (!iprop || len != sizeof(uint32_t)) {
                        dev_err(&pdev->dev, "mdio-mux child node %s is "
                                "missing a 'reg' property\n", np2->full_name);
+                       of_node_put(np2);
                        return -ENODEV;
                }
                if (be32_to_cpup(iprop) & ~s->mask) {
                        dev_err(&pdev->dev, "mdio-mux child node %s has "
                                "a 'reg' value with unmasked bits\n",
                                np2->full_name);
+                       of_node_put(np2);
                        return -ENODEV;
                }
        }
index 280c7c311f72442c4877815ece73c2a36745be49..908e8d4863429fb6c11f4a625449500f3be36ce1 100644 (file)
@@ -144,6 +144,7 @@ int mdio_mux_init(struct device *dev,
                        dev_err(dev,
                                "Error: Failed to allocate memory for child\n");
                        ret_val = -ENOMEM;
+                       of_node_put(child_bus_node);
                        break;
                }
                cb->bus_number = v;
index 499185eaf413ba08b1447fbebf1f60080c643329..cf6312fafea545fbc3efb96e8ff6c63b35c7420e 100644 (file)
@@ -514,6 +514,27 @@ static int ksz8873mll_read_status(struct phy_device *phydev)
        return 0;
 }
 
+static int ksz9031_read_status(struct phy_device *phydev)
+{
+       int err;
+       int regval;
+
+       err = genphy_read_status(phydev);
+       if (err)
+               return err;
+
+       /* Make sure the PHY is not broken. Read idle error count,
+        * and reset the PHY if it is maxed out.
+        */
+       regval = phy_read(phydev, MII_STAT1000);
+       if ((regval & 0xFF) == 0xFF) {
+               phy_init_hw(phydev);
+               phydev->link = 0;
+       }
+
+       return 0;
+}
+
 static int ksz8873mll_config_aneg(struct phy_device *phydev)
 {
        return 0;
@@ -772,7 +793,7 @@ static struct phy_driver ksphy_driver[] = {
        .driver_data    = &ksz9021_type,
        .config_init    = ksz9031_config_init,
        .config_aneg    = genphy_config_aneg,
-       .read_status    = genphy_read_status,
+       .read_status    = ksz9031_read_status,
        .ack_interrupt  = kszphy_ack_interrupt,
        .config_intr    = kszphy_config_intr,
        .suspend        = genphy_suspend,
index 70b08958763a129fff47ad00a1db130c1334f254..dc2da87709185870f808ef626e8446893c658db6 100644 (file)
@@ -43,16 +43,25 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev)
 
 static int smsc_phy_config_init(struct phy_device *phydev)
 {
+       int __maybe_unused len;
+       struct device *dev __maybe_unused = &phydev->dev;
+       struct device_node *of_node __maybe_unused = dev->of_node;
        int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+       int enable_energy = 1;
 
        if (rc < 0)
                return rc;
 
-       /* Enable energy detect mode for this SMSC Transceivers */
-       rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
-                      rc | MII_LAN83C185_EDPWRDOWN);
-       if (rc < 0)
-               return rc;
+       if (of_find_property(of_node, "smsc,disable-energy-detect", &len))
+               enable_energy = 0;
+
+       if (enable_energy) {
+               /* Enable energy detect mode for this SMSC Transceivers */
+               rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
+                              rc | MII_LAN83C185_EDPWRDOWN);
+               if (rc < 0)
+                       return rc;
+       }
 
        return smsc_phy_ack_interrupt(phydev);
 }
index 3837ae344f63b9d69a5dd958d0e7b7dc202ff316..5e0b43283bce2c4f5251e5c5db982ca679526d07 100644 (file)
@@ -313,7 +313,6 @@ static void pppoe_flush_dev(struct net_device *dev)
                        if (po->pppoe_dev == dev &&
                            sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
                                pppox_unbind_sock(sk);
-                               sk->sk_state = PPPOX_ZOMBIE;
                                sk->sk_state_change(sk);
                                po->pppoe_dev = NULL;
                                dev_put(dev);
@@ -590,7 +589,7 @@ static int pppoe_release(struct socket *sock)
 
        po = pppox_sk(sk);
 
-       if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
+       if (po->pppoe_dev) {
                dev_put(po->pppoe_dev);
                po->pppoe_dev = NULL;
        }
index fbb9325d1f6e539421f2ad592d718bcede68acea..e66805eeffb45f014a9c61d20e0bd6f3b473098b 100644 (file)
@@ -164,6 +164,7 @@ config USB_NET_AX8817X
            * Aten UC210T
            * ASIX AX88172
            * Billionton Systems, USB2AR
+           * Billionton Systems, GUSB2AM-1G-B
            * Buffalo LUA-U2-KTX
            * Corega FEther USB2-TX
            * D-Link DUB-E100
index 75d6f26729a30e34cdaaf8334a9cc0aaa2a01c82..079069a060a62fdb42cb9dff9acbcd55148277b8 100644 (file)
@@ -91,8 +91,10 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb,
                        }
                        rx->ax_skb = netdev_alloc_skb_ip_align(dev->net,
                                                               rx->size);
-                       if (!rx->ax_skb)
+                       if (!rx->ax_skb) {
+                               rx->size = 0;
                                return 0;
+                       }
                }
 
                if (rx->size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) {
index 1173a24feda38c3af236c84acaf8982f39c0e0b1..5cabefc2349438f26cddde0022d52acf6e967116 100644 (file)
@@ -958,6 +958,10 @@ static const struct usb_device_id  products [] = {
        // Billionton Systems, USB2AR
        USB_DEVICE (0x08dd, 0x90ff),
        .driver_info =  (unsigned long) &ax8817x_info,
+}, {
+       // Billionton Systems, GUSB2AM-1G-B
+       USB_DEVICE(0x08dd, 0x0114),
+       .driver_info =  (unsigned long) &ax88178_info,
 }, {
        // ATEN UC210T
        USB_DEVICE (0x0557, 0x2009),
index 355842b85ee906a434477b325f32199ec315eae8..2a7c1be23c4f2aea38e2ec99384be91e7f9d0f62 100644 (file)
@@ -765,6 +765,10 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1199, 0x9056, 8)},    /* Sierra Wireless Modem */
        {QMI_FIXED_INTF(0x1199, 0x9057, 8)},
        {QMI_FIXED_INTF(0x1199, 0x9061, 8)},    /* Sierra Wireless Modem */
+       {QMI_FIXED_INTF(0x1199, 0x9070, 8)},    /* Sierra Wireless MC74xx/EM74xx */
+       {QMI_FIXED_INTF(0x1199, 0x9070, 10)},   /* Sierra Wireless MC74xx/EM74xx */
+       {QMI_FIXED_INTF(0x1199, 0x9071, 8)},    /* Sierra Wireless MC74xx/EM74xx */
+       {QMI_FIXED_INTF(0x1199, 0x9071, 10)},   /* Sierra Wireless MC74xx/EM74xx */
        {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},    /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
        {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)},    /* Alcatel L800MA */
        {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
index bbac1d35ed4e37450a3282b4b7f9dc41dabcd4e8..c1587ece28cfffeb3c7c3011bf087215edb77662 100644 (file)
@@ -2337,6 +2337,46 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
+static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb,
+                               struct ip_tunnel_info *info,
+                               __be16 sport, __be16 dport)
+{
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct rtable *rt;
+       struct flowi4 fl4;
+
+       memset(&fl4, 0, sizeof(fl4));
+       fl4.flowi4_tos = RT_TOS(info->key.tos);
+       fl4.flowi4_mark = skb->mark;
+       fl4.flowi4_proto = IPPROTO_UDP;
+       fl4.daddr = info->key.u.ipv4.dst;
+
+       rt = ip_route_output_key(vxlan->net, &fl4);
+       if (IS_ERR(rt))
+               return PTR_ERR(rt);
+       ip_rt_put(rt);
+
+       info->key.u.ipv4.src = fl4.saddr;
+       info->key.tp_src = sport;
+       info->key.tp_dst = dport;
+       return 0;
+}
+
+static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct ip_tunnel_info *info = skb_tunnel_info(skb);
+       __be16 sport, dport;
+
+       sport = udp_flow_src_port(dev_net(dev), skb, vxlan->cfg.port_min,
+                                 vxlan->cfg.port_max, true);
+       dport = info->key.tp_dst ? : vxlan->cfg.dst_port;
+
+       if (ip_tunnel_info_af(info) == AF_INET)
+               return egress_ipv4_tun_info(dev, skb, info, sport, dport);
+       return -EINVAL;
+}
+
 static const struct net_device_ops vxlan_netdev_ops = {
        .ndo_init               = vxlan_init,
        .ndo_uninit             = vxlan_uninit,
@@ -2351,6 +2391,7 @@ static const struct net_device_ops vxlan_netdev_ops = {
        .ndo_fdb_add            = vxlan_fdb_add,
        .ndo_fdb_del            = vxlan_fdb_delete,
        .ndo_fdb_dump           = vxlan_fdb_dump,
+       .ndo_fill_metadata_dst  = vxlan_fill_metadata_dst,
 };
 
 /* Info for udev, that this is a virtual tunnel endpoint */
@@ -2745,11 +2786,10 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
        struct vxlan_config conf;
        int err;
 
-       if (!data[IFLA_VXLAN_ID])
-               return -EINVAL;
-
        memset(&conf, 0, sizeof(conf));
-       conf.vni = nla_get_u32(data[IFLA_VXLAN_ID]);
+
+       if (data[IFLA_VXLAN_ID])
+               conf.vni = nla_get_u32(data[IFLA_VXLAN_ID]);
 
        if (data[IFLA_VXLAN_GROUP]) {
                conf.remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]);
index 23afcda2de967637d73c7039d0f2cdb5f3b777ff..678d72af4a9df73976b7513d9af17888bc1ef7d1 100644 (file)
@@ -337,7 +337,7 @@ enum ath10k_hw_rate_cck {
 #define TARGET_10X_MAX_FRAG_ENTRIES            0
 
 /* 10.2 parameters */
-#define TARGET_10_2_DMA_BURST_SIZE             1
+#define TARGET_10_2_DMA_BURST_SIZE             0
 
 /* Target specific defines for WMI-TLV firmware */
 #define TARGET_TLV_NUM_VDEVS                   4
@@ -391,7 +391,7 @@ enum ath10k_hw_rate_cck {
 
 #define TARGET_10_4_TX_DBG_LOG_SIZE            1024
 #define TARGET_10_4_NUM_WDS_ENTRIES            32
-#define TARGET_10_4_DMA_BURST_SIZE             1
+#define TARGET_10_4_DMA_BURST_SIZE             0
 #define TARGET_10_4_MAC_AGGR_DELIM             0
 #define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1
 #define TARGET_10_4_VOW_CONFIG                 0
index 6e473fa4b13cae0df30a33fd9162729afaf76f6b..12241b1c57cd28023d0278c57f347457583bc017 100644 (file)
@@ -715,6 +715,7 @@ static bool check_device_tree(struct ath6kl *ar)
                                   board_filename, ret);
                        continue;
                }
+               of_node_put(node);
                return true;
        }
        return false;
index 57f95f2dca5b072ac294b2c76122ec1b952a2a80..90eb75012e4f4818a03481d98cb9b137a89393fa 100644 (file)
@@ -880,6 +880,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
        hw->max_rate_tries = 10;
        hw->sta_data_size = sizeof(struct ath_node);
        hw->vif_data_size = sizeof(struct ath_vif);
+       hw->extra_tx_headroom = 4;
 
        hw->wiphy->available_antennas_rx = BIT(ah->caps.max_rxchains) - 1;
        hw->wiphy->available_antennas_tx = BIT(ah->caps.max_txchains) - 1;
index 28490702124a0da53bb2834f1ca880a452d6523b..71d3e9adbf3c02b4d5ff50843a2b4b06cd96b6a5 100644 (file)
@@ -120,6 +120,7 @@ MODULE_PARM_DESC(allhwsupport, "Enable support for all hardware (even it if over
 #ifdef CONFIG_B43_BCMA
 static const struct bcma_device_id b43_bcma_tbl[] = {
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
+       BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x15, BCMA_ANY_CLASS),
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
        BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1C, BCMA_ANY_CLASS),
index ab45819c1fbbf6d0080813c26090bb095082672d..e18629a16fb0260dff9b3486c572f4bfd2166fcd 100644 (file)
@@ -1020,7 +1020,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
                        u8 *pn = seq.ccmp.pn;
 
                        ieee80211_get_key_rx_seq(key, i, &seq);
-                       aes_sc->pn = cpu_to_le64(
+                       aes_sc[i].pn = cpu_to_le64(
                                        (u64)pn[5] |
                                        ((u64)pn[4] << 8) |
                                        ((u64)pn[3] << 16) |
index 6951aba620eb74a13f6fc2c2da36a043272d8a43..3fb327d5a911aeba53e4ac71ad6bb2ad419d06b0 100644 (file)
@@ -348,6 +348,6 @@ const struct iwl_cfg iwl7265d_n_cfg = {
 };
 
 MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
-MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
+MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
 MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
 MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
index 04264e417c1c644e2b362e9bf29760489cfcae4f..576187611e614adc3a92ca50c4e1f2ab3a7bb7e1 100644 (file)
@@ -274,18 +274,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
                break;
        case WLAN_CIPHER_SUITE_CCMP:
                if (sta) {
-                       u8 *pn = seq.ccmp.pn;
+                       u64 pn64;
 
                        aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc;
                        aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc;
 
-                       ieee80211_get_key_tx_seq(key, &seq);
-                       aes_tx_sc->pn = cpu_to_le64((u64)pn[5] |
-                                                   ((u64)pn[4] << 8) |
-                                                   ((u64)pn[3] << 16) |
-                                                   ((u64)pn[2] << 24) |
-                                                   ((u64)pn[1] << 32) |
-                                                   ((u64)pn[0] << 40));
+                       pn64 = atomic64_read(&key->tx_pn);
+                       aes_tx_sc->pn = cpu_to_le64(pn64);
                } else {
                        aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc;
                }
@@ -298,12 +293,12 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
                        u8 *pn = seq.ccmp.pn;
 
                        ieee80211_get_key_rx_seq(key, i, &seq);
-                       aes_sc->pn = cpu_to_le64((u64)pn[5] |
-                                                ((u64)pn[4] << 8) |
-                                                ((u64)pn[3] << 16) |
-                                                ((u64)pn[2] << 24) |
-                                                ((u64)pn[1] << 32) |
-                                                ((u64)pn[0] << 40));
+                       aes_sc[i].pn = cpu_to_le64((u64)pn[5] |
+                                                  ((u64)pn[4] << 8) |
+                                                  ((u64)pn[3] << 16) |
+                                                  ((u64)pn[2] << 24) |
+                                                  ((u64)pn[1] << 32) |
+                                                  ((u64)pn[0] << 40));
                }
                data->use_rsc_tsc = true;
                break;
@@ -1453,15 +1448,15 @@ static void iwl_mvm_d3_update_gtks(struct ieee80211_hw *hw,
 
                switch (key->cipher) {
                case WLAN_CIPHER_SUITE_CCMP:
-                       iwl_mvm_aes_sc_to_seq(&sc->aes.tsc, &seq);
                        iwl_mvm_set_aes_rx_seq(sc->aes.unicast_rsc, key);
+                       atomic64_set(&key->tx_pn, le64_to_cpu(sc->aes.tsc.pn));
                        break;
                case WLAN_CIPHER_SUITE_TKIP:
                        iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq);
                        iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key);
+                       ieee80211_set_key_tx_seq(key, &seq);
                        break;
                }
-               ieee80211_set_key_tx_seq(key, &seq);
 
                /* that's it for this key */
                return;
index 4a0ce83315bdd212d1714956af8900ea271f62b6..5c7f7cc9ffcc2aa1d81cbf1ff5b2d33f46133727 100644 (file)
@@ -703,7 +703,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
         * abort after reading the nvm in case RF Kill is on, we will complete
         * the init seq later when RF kill will switch to off
         */
-       if (iwl_mvm_is_radio_killed(mvm)) {
+       if (iwl_mvm_is_radio_hw_killed(mvm)) {
                IWL_DEBUG_RF_KILL(mvm,
                                  "jump over all phy activities due to RF kill\n");
                iwl_remove_notification(&mvm->notif_wait, &calib_wait);
@@ -736,7 +736,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
        ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait,
                        MVM_UCODE_CALIB_TIMEOUT);
 
-       if (ret && iwl_mvm_is_radio_killed(mvm)) {
+       if (ret && iwl_mvm_is_radio_hw_killed(mvm)) {
                IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n");
                ret = 1;
        }
index aa8c2b7f23c73862f0526f109ad647cc0c80a259..7c2944a72470b92acdca39a6f7c13b845b34842a 100644 (file)
@@ -2388,6 +2388,7 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
                iwl_mvm_remove_time_event(mvm, mvmvif,
                                          &mvmvif->time_event_data);
                RCU_INIT_POINTER(mvm->csa_vif, NULL);
+               mvmvif->csa_countdown = false;
        }
 
        if (rcu_access_pointer(mvm->csa_tx_blocked_vif) == vif) {
index b95a07ec9e362bf031f960dee35dc52c97221ed0..c754051a4ceacf138d4e6399c9cc679d8a9979c0 100644 (file)
@@ -860,6 +860,11 @@ static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
               test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status);
 }
 
+static inline bool iwl_mvm_is_radio_hw_killed(struct iwl_mvm *mvm)
+{
+       return test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
+}
+
 /* Must be called with rcu_read_lock() held and it can only be
  * released when mvmsta is not needed anymore.
  */
index a37de3f410a01e0b594f41d43bfda4360273e324..f0cb092f980ec26b26e9ca3c6cadf813f39de853 100644 (file)
@@ -590,6 +590,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        ieee80211_unregister_hw(mvm->hw);
        iwl_mvm_leds_exit(mvm);
  out_free:
+       flush_delayed_work(&mvm->fw_dump_wk);
        iwl_phy_db_free(mvm->phy_db);
        kfree(mvm->scan_cmd);
        if (!cfg->no_power_up_nic_in_init || !mvm->nvm_file_name)
index b0825c402c732c0514637b3b21b26288a7275444..644b58bc5226c52b3cdee0a24b9a392c25e8ac02 100644 (file)
@@ -414,6 +414,11 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
        {IWL_PCI_DEVICE(0x095A, 0x5590, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095B, 0x5290, iwl7265_2ac_cfg)},
        {IWL_PCI_DEVICE(0x095A, 0x5490, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x5F10, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x5212, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095B, 0x520A, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9000, iwl7265_2ac_cfg)},
+       {IWL_PCI_DEVICE(0x095A, 0x9400, iwl7265_2ac_cfg)},
 
 /* 8000 Series */
        {IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)},
index 5932306084fd305a6f45ccf03d8957b771eaaa13..bf9afbf46c1bbbc1220bad06e429d2622a1f9f58 100644 (file)
@@ -1114,6 +1114,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
        { USB_DEVICE(0x0db0, 0x871c) },
        { USB_DEVICE(0x0db0, 0x899a) },
        /* Ovislink */
+       { USB_DEVICE(0x1b75, 0x3070) },
        { USB_DEVICE(0x1b75, 0x3071) },
        { USB_DEVICE(0x1b75, 0x3072) },
        { USB_DEVICE(0x1b75, 0xa200) },
index d4567d12e07ebd13f17f0097baeec41a25702d31..5da6703942d9dd08017d896070404fdbe29a96e4 100644 (file)
@@ -247,6 +247,8 @@ struct rtl_pci {
        /* MSI support */
        bool msi_support;
        bool using_msi;
+       /* interrupt clear before set */
+       bool int_clear;
 };
 
 struct mp_adapter {
index b7f18e2155eb18358cf4d4f9f3f82774f9b6f522..6e9418ed90c289bee5b7f2dfc478f847dfc7ca68 100644 (file)
@@ -2253,11 +2253,28 @@ void rtl8821ae_set_qos(struct ieee80211_hw *hw, int aci)
        }
 }
 
+static void rtl8821ae_clear_interrupt(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       u32 tmp = rtl_read_dword(rtlpriv, REG_HISR);
+
+       rtl_write_dword(rtlpriv, REG_HISR, tmp);
+
+       tmp = rtl_read_dword(rtlpriv, REG_HISRE);
+       rtl_write_dword(rtlpriv, REG_HISRE, tmp);
+
+       tmp = rtl_read_dword(rtlpriv, REG_HSISR);
+       rtl_write_dword(rtlpriv, REG_HSISR, tmp);
+}
+
 void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 
+       if (!rtlpci->int_clear)
+               rtl8821ae_clear_interrupt(hw);/*clear it here first*/
+
        rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
        rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
        rtlpci->irq_enabled = true;
index a4988121e1ab6a20bad5ad9b5934c166a41f36d6..8ee141a55bc5cc6b566e79dde58cdb05583e7fdf 100644 (file)
@@ -96,6 +96,7 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
 
        rtl8821ae_bt_reg_init(hw);
        rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+       rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear;
        rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
 
        rtlpriv->dm.dm_initialgain_enable = 1;
@@ -167,6 +168,7 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
        rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
        rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
        rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+       rtlpci->msi_support = rtlpriv->cfg->mod_params->int_clear;
        if (rtlpriv->cfg->mod_params->disable_watchdog)
                pr_info("watchdog disabled\n");
        rtlpriv->psc.reg_fwctrl_lps = 3;
@@ -308,6 +310,7 @@ static struct rtl_mod_params rtl8821ae_mod_params = {
        .swctrl_lps = false,
        .fwctrl_lps = true,
        .msi_support = true,
+       .int_clear = true,
        .debug = DBG_EMERG,
        .disable_watchdog = 0,
 };
@@ -437,6 +440,7 @@ module_param_named(fwlps, rtl8821ae_mod_params.fwctrl_lps, bool, 0444);
 module_param_named(msi, rtl8821ae_mod_params.msi_support, bool, 0444);
 module_param_named(disable_watchdog, rtl8821ae_mod_params.disable_watchdog,
                   bool, 0444);
+module_param_named(int_clear, rtl8821ae_mod_params.int_clear, bool, 0444);
 MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
 MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
 MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
@@ -444,6 +448,7 @@ MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
 MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 1)\n");
 MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
 MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n");
+MODULE_PARM_DESC(int_clear, "Set to 1 to disable interrupt clear before set (default 0)\n");
 
 static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
 
index b90ca618b123209a1724bc808c4fdfe8ea330a69..4544752a2ba83ca173f7cb4f14abc72538b73beb 100644 (file)
@@ -2249,6 +2249,9 @@ struct rtl_mod_params {
 
        /* default 0: 1 means disable */
        bool disable_watchdog;
+
+       /* default 0: 1 means do not disable interrupts */
+       bool int_clear;
 };
 
 struct rtl_hal_usbint_cfg {
index 929a6e7e5ecfe9249569c0059516e531fb0b79eb..56ebd8267386e6a91cabf506962e15f5d83531ec 100644 (file)
@@ -788,6 +788,12 @@ static void connect(struct backend_info *be)
        /* Use the number of queues requested by the frontend */
        be->vif->queues = vzalloc(requested_num_queues *
                                  sizeof(struct xenvif_queue));
+       if (!be->vif->queues) {
+               xenbus_dev_fatal(dev, -ENOMEM,
+                                "allocating queues");
+               return;
+       }
+
        be->vif->num_queues = requested_num_queues;
        be->vif->stalled_queues = requested_num_queues;
 
index f821a97d78278feed765d08d886a4665d8795bd5..6febc053a37febc069d241e6811d904f18890f45 100644 (file)
@@ -1706,19 +1706,19 @@ static void xennet_destroy_queues(struct netfront_info *info)
 }
 
 static int xennet_create_queues(struct netfront_info *info,
-                               unsigned int num_queues)
+                               unsigned int *num_queues)
 {
        unsigned int i;
        int ret;
 
-       info->queues = kcalloc(num_queues, sizeof(struct netfront_queue),
+       info->queues = kcalloc(*num_queues, sizeof(struct netfront_queue),
                               GFP_KERNEL);
        if (!info->queues)
                return -ENOMEM;
 
        rtnl_lock();
 
-       for (i = 0; i < num_queues; i++) {
+       for (i = 0; i < *num_queues; i++) {
                struct netfront_queue *queue = &info->queues[i];
 
                queue->id = i;
@@ -1728,7 +1728,7 @@ static int xennet_create_queues(struct netfront_info *info,
                if (ret < 0) {
                        dev_warn(&info->netdev->dev,
                                 "only created %d queues\n", i);
-                       num_queues = i;
+                       *num_queues = i;
                        break;
                }
 
@@ -1738,11 +1738,11 @@ static int xennet_create_queues(struct netfront_info *info,
                        napi_enable(&queue->napi);
        }
 
-       netif_set_real_num_tx_queues(info->netdev, num_queues);
+       netif_set_real_num_tx_queues(info->netdev, *num_queues);
 
        rtnl_unlock();
 
-       if (num_queues == 0) {
+       if (*num_queues == 0) {
                dev_err(&info->netdev->dev, "no queues\n");
                return -EINVAL;
        }
@@ -1788,7 +1788,7 @@ static int talk_to_netback(struct xenbus_device *dev,
        if (info->queues)
                xennet_destroy_queues(info);
 
-       err = xennet_create_queues(info, num_queues);
+       err = xennet_create_queues(info, &num_queues);
        if (err < 0)
                goto destroy_ring;
 
index 312f23a8429cd9331b45afaf72a278e84bd41d83..92618686604cb9d314aa1e6bf833363cfbaaa1b5 100644 (file)
@@ -216,7 +216,7 @@ static ssize_t numa_node_store(struct device *dev,
        if (ret)
                return ret;
 
-       if (!node_online(node))
+       if (node >= MAX_NUMNODES || !node_online(node))
                return -EINVAL;
 
        add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
index 2365a32a595e42b8ddf43c2dc32603749cf990d7..be3755c973e96d4c6ee48f0459c751ba6d225665 100644 (file)
@@ -823,9 +823,15 @@ static int of_pmu_irq_cfg(struct arm_pmu *pmu)
                }
 
                /* Now look up the logical CPU number */
-               for_each_possible_cpu(cpu)
-                       if (dn == of_cpu_device_node_get(cpu))
+               for_each_possible_cpu(cpu) {
+                       struct device_node *cpu_dn;
+
+                       cpu_dn = of_cpu_device_node_get(cpu);
+                       of_node_put(cpu_dn);
+
+                       if (dn == cpu_dn)
                                break;
+               }
 
                if (cpu >= nr_cpu_ids) {
                        pr_warn("Failed to find logical CPU for %s\n",
index 23685e74917e2a5c3f3ab6dc6542f48d5ecbb2a9..bd2c69f85949ba6ce40b80c588a2e6a4036964a2 100644 (file)
@@ -116,7 +116,7 @@ static int sca3000_read_first_n_hw_rb(struct iio_buffer *r,
        if (ret)
                goto error_ret;
 
-       for (i = 0; i < num_read; i++)
+       for (i = 0; i < num_read / sizeof(u16); i++)
                *(((u16 *)rx) + i) = be16_to_cpup((__be16 *)rx + i);
 
        if (copy_to_user(buf, rx, num_read))
index 3f7715c9968b83b25d6d1a4f6099c29b051db5fd..47fc00a3f63bc9e5106f0c77354c7cf8e309f36e 100644 (file)
@@ -915,11 +915,12 @@ static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
        case IIO_CHAN_INFO_OFFSET:
                if (chan->type == IIO_TEMP) {
                        /* The calculated value from the ADC is in Kelvin, we
-                        * want Celsius for hwmon so the offset is
-                        * -272.15 * scale
+                        * want Celsius for hwmon so the offset is -273.15
+                        * The offset is applied before scaling so it is
+                        * actually -213.15 * 4 / 1.012 = -1079.644268
                         */
-                       *val = -1075;
-                       *val2 = 691699;
+                       *val = -1079;
+                       *val2 = 644268;
 
                        return IIO_VAL_INT_PLUS_MICRO;
                }
index 0bae8cc6c23a0be622b2addf1479830e838cb243..ca920b0ecf8f8688763426ba2d6b253a3620a1b6 100644 (file)
@@ -932,7 +932,7 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
 
        if (data->soc == SOC_ARCH_EXYNOS5260)
                emul_con = EXYNOS5260_EMUL_CON;
-       if (data->soc == SOC_ARCH_EXYNOS5433)
+       else if (data->soc == SOC_ARCH_EXYNOS5433)
                emul_con = EXYNOS5433_TMU_EMUL_CON;
        else if (data->soc == SOC_ARCH_EXYNOS7)
                emul_con = EXYNOS7_TMU_REG_EMUL_CON;
index 21d01a491405a2c52cd1ec02f3198fa4c6b8f10c..e508939daea3f3128a2ada1e696a5f751d212077 100644 (file)
@@ -80,10 +80,6 @@ int serial8250_tx_dma(struct uart_8250_port *p)
                return 0;
 
        dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
-       if (dma->tx_size < p->port.fifosize) {
-               ret = -EINVAL;
-               goto err;
-       }
 
        desc = dmaengine_prep_slave_single(dma->txchan,
                                           dma->tx_addr + xmit->tail,
index c79d33676672daca6047ebead9d8afb70a49007d..c47d3e48058659230e8d48ed342f9c163b08732d 100644 (file)
@@ -147,6 +147,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
                pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
+               xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
        }
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
                (pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
index 43291f93afeb59a90a3b39cbb045a26b3bd1ad5b..97ffe39972735109f1ca1f86e003fe2550e4f936 100644 (file)
@@ -2191,6 +2191,10 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
                }
        /* Fast path - was this the last TRB in the TD for this URB? */
        } else if (event_trb == td->last_trb) {
+               if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX)
+                       return finish_td(xhci, td, event_trb, event, ep,
+                                        status, false);
+
                if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
                        td->urb->actual_length =
                                td->urb->transfer_buffer_length -
@@ -2242,6 +2246,12 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
                        td->urb->actual_length +=
                                TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
                                EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+
+               if (trb_comp_code == COMP_SHORT_TX) {
+                       xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n");
+                       td->urb_length_set = true;
+                       return 0;
+               }
        }
 
        return finish_td(xhci, td, event_trb, event, ep, status, false);
@@ -2274,6 +2284,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
        u32 trb_comp_code;
        int ret = 0;
        int td_num = 0;
+       bool handling_skipped_tds = false;
 
        slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
        xdev = xhci->devs[slot_id];
@@ -2410,6 +2421,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                ep->skip = true;
                xhci_dbg(xhci, "Miss service interval error, set skip flag\n");
                goto cleanup;
+       case COMP_PING_ERR:
+               ep->skip = true;
+               xhci_dbg(xhci, "No Ping response error, Skip one Isoc TD\n");
+               goto cleanup;
        default:
                if (xhci_is_vendor_info_code(xhci, trb_comp_code)) {
                        status = 0;
@@ -2546,13 +2561,18 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                                                 ep, &status);
 
 cleanup:
+
+
+               handling_skipped_tds = ep->skip &&
+                       trb_comp_code != COMP_MISSED_INT &&
+                       trb_comp_code != COMP_PING_ERR;
+
                /*
-                * Do not update event ring dequeue pointer if ep->skip is set.
-                * Will roll back to continue process missed tds.
+                * Do not update event ring dequeue pointer if we're in a loop
+                * processing missed tds.
                 */
-               if (trb_comp_code == COMP_MISSED_INT || !ep->skip) {
+               if (!handling_skipped_tds)
                        inc_deq(xhci, xhci->event_ring);
-               }
 
                if (ret) {
                        urb = td->urb;
@@ -2587,7 +2607,7 @@ cleanup:
         * Process them as short transfer until reach the td pointed by
         * the event.
         */
-       } while (ep->skip && trb_comp_code != COMP_MISSED_INT);
+       } while (handling_skipped_tds);
 
        return 0;
 }
index 4772862b71a744091efef2216d9deaeca54567d1..d3f767448a72c75f468afe6b922e9306c35e5011 100644 (file)
@@ -183,10 +183,17 @@ static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit)
        return vq->acked_features & (1ULL << bit);
 }
 
+#ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY
 static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
 {
        return vq->is_le;
 }
+#else
+static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
+{
+       return virtio_legacy_is_little_endian() || vq->is_le;
+}
+#endif
 
 /* Memory accessors */
 static inline u16 vhost16_to_cpu(struct vhost_virtqueue *vq, __virtio16 val)
index 1aaf89300621abc811f57f549c25b9a540a21d99..92f394927f241bef338a293170e4a09b9f45c647 100644 (file)
@@ -1093,6 +1093,7 @@ static void fbcon_init(struct vc_data *vc, int init)
                con_copy_unimap(vc, svc);
 
        ops = info->fbcon_par;
+       ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
        p->con_rotate = initial_rotation;
        set_blitting_type(vc, info);
 
index b823fac91c9289bc67d3bb5191f4ce96e38294ac..8c6f247ba81d4e84c6a7d3d00d0348c974c1b049 100644 (file)
@@ -2584,7 +2584,7 @@ static long btrfs_fallocate(struct file *file, int mode,
                                        alloc_start);
                if (ret)
                        goto out;
-       } else {
+       } else if (offset + len > inode->i_size) {
                /*
                 * If we are fallocating from the end of the file onward we
                 * need to zero out the end of the page if i_size lands in the
index 3e3e6130637fa7268e6834c6fafe129de84345a7..8d20f3b1cab0abfa7b5f2bc4b8646c094a9353a5 100644 (file)
@@ -4641,7 +4641,7 @@ locked:
 
        if (bctl->flags & ~(BTRFS_BALANCE_ARGS_MASK | BTRFS_BALANCE_TYPE_MASK)) {
                ret = -EINVAL;
-               goto out_bargs;
+               goto out_bctl;
        }
 
 do_balance:
@@ -4655,12 +4655,15 @@ do_balance:
        need_unlock = false;
 
        ret = btrfs_balance(bctl, bargs);
+       bctl = NULL;
 
        if (arg) {
                if (copy_to_user(arg, bargs, sizeof(*bargs)))
                        ret = -EFAULT;
        }
 
+out_bctl:
+       kfree(bctl);
 out_bargs:
        kfree(bargs);
 out_unlock:
index 091a36444972fa0b746118b0cc58ca2a3dcaa97f..29e4599f6fc1c20b73acb2c580ce8383e169c5f2 100644 (file)
@@ -778,19 +778,24 @@ static void bdi_split_work_to_wbs(struct backing_dev_info *bdi,
                                  struct wb_writeback_work *base_work,
                                  bool skip_if_busy)
 {
-       int next_memcg_id = 0;
-       struct bdi_writeback *wb;
-       struct wb_iter iter;
+       struct bdi_writeback *last_wb = NULL;
+       struct bdi_writeback *wb = list_entry_rcu(&bdi->wb_list,
+                                               struct bdi_writeback, bdi_node);
 
        might_sleep();
 restart:
        rcu_read_lock();
-       bdi_for_each_wb(wb, bdi, &iter, next_memcg_id) {
+       list_for_each_entry_continue_rcu(wb, &bdi->wb_list, bdi_node) {
                DEFINE_WB_COMPLETION_ONSTACK(fallback_work_done);
                struct wb_writeback_work fallback_work;
                struct wb_writeback_work *work;
                long nr_pages;
 
+               if (last_wb) {
+                       wb_put(last_wb);
+                       last_wb = NULL;
+               }
+
                /* SYNC_ALL writes out I_DIRTY_TIME too */
                if (!wb_has_dirty_io(wb) &&
                    (base_work->sync_mode == WB_SYNC_NONE ||
@@ -819,12 +824,22 @@ restart:
 
                wb_queue_work(wb, work);
 
-               next_memcg_id = wb->memcg_css->id + 1;
+               /*
+                * Pin @wb so that it stays on @bdi->wb_list.  This allows
+                * continuing iteration from @wb after dropping and
+                * regrabbing rcu read lock.
+                */
+               wb_get(wb);
+               last_wb = wb;
+
                rcu_read_unlock();
                wb_wait_for_completion(bdi, &fallback_work_done);
                goto restart;
        }
        rcu_read_unlock();
+
+       if (last_wb)
+               wb_put(last_wb);
 }
 
 #else  /* CONFIG_CGROUP_WRITEBACK */
@@ -1857,12 +1872,11 @@ void wakeup_flusher_threads(long nr_pages, enum wb_reason reason)
        rcu_read_lock();
        list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
                struct bdi_writeback *wb;
-               struct wb_iter iter;
 
                if (!bdi_has_dirty_io(bdi))
                        continue;
 
-               bdi_for_each_wb(wb, bdi, &iter, 0)
+               list_for_each_entry_rcu(wb, &bdi->wb_list, bdi_node)
                        wb_start_writeback(wb, wb_split_bdi_pages(wb, nr_pages),
                                           false, reason);
        }
@@ -1894,11 +1908,10 @@ static void wakeup_dirtytime_writeback(struct work_struct *w)
        rcu_read_lock();
        list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) {
                struct bdi_writeback *wb;
-               struct wb_iter iter;
 
-               bdi_for_each_wb(wb, bdi, &iter, 0)
-                       if (!list_empty(&bdi->wb.b_dirty_time))
-                               wb_wakeup(&bdi->wb);
+               list_for_each_entry_rcu(wb, &bdi->wb_list, bdi_node)
+                       if (!list_empty(&wb->b_dirty_time))
+                               wb_wakeup(wb);
        }
        rcu_read_unlock();
        schedule_delayed_work(&dirtytime_work, dirtytime_expire_interval * HZ);
index ee5aa4daaea0dbf6c1840649ac505f60313aa8dd..ce38b4ccc9ab6c52c796a148b496bab0d8d46510 100644 (file)
@@ -1658,12 +1658,13 @@ send_response:
                if (ret < 0) {
                        mlog(ML_ERROR, "failed to dispatch assert master work\n");
                        response = DLM_MASTER_RESP_ERROR;
+                       spin_unlock(&res->spinlock);
                        dlm_lockres_put(res);
                } else {
                        dispatched = 1;
                        __dlm_lockres_grab_inflight_worker(dlm, res);
+                       spin_unlock(&res->spinlock);
                }
-               spin_unlock(&res->spinlock);
        } else {
                if (res)
                        dlm_lockres_put(res);
index 3d90ad7ff91fe4748386218807f7131bd61d7d69..58eaa5c0d387051301a089f0d234d4b69bf18d51 100644 (file)
@@ -1723,8 +1723,8 @@ int dlm_master_requery_handler(struct o2net_msg *msg, u32 len, void *data,
                        } else {
                                dispatched = 1;
                                __dlm_lockres_grab_inflight_worker(dlm, res);
+                               spin_unlock(&res->spinlock);
                        }
-                       spin_unlock(&res->spinlock);
                } else {
                        /* put.. incase we are not the master */
                        spin_unlock(&res->spinlock);
index 84d693d374284b580208fec3b8eb3c57bdd4195c..871fcb67be9741f2aab81f3d6552306dedf4c967 100644 (file)
@@ -81,11 +81,11 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)
        if (len == 0)
                return 0;
 
-       old_file = ovl_path_open(old, O_RDONLY);
+       old_file = ovl_path_open(old, O_LARGEFILE | O_RDONLY);
        if (IS_ERR(old_file))
                return PTR_ERR(old_file);
 
-       new_file = ovl_path_open(new, O_WRONLY);
+       new_file = ovl_path_open(new, O_LARGEFILE | O_WRONLY);
        if (IS_ERR(new_file)) {
                error = PTR_ERR(new_file);
                goto out_fput;
@@ -267,7 +267,7 @@ out:
 
 out_cleanup:
        ovl_cleanup(wdir, newdentry);
-       goto out;
+       goto out2;
 }
 
 /*
index d9da5a4e93821ddbee9f2fb449666c207417e523..ec0c2a050043afbb3eff4c7451930dc6d86006ec 100644 (file)
@@ -363,6 +363,9 @@ struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags)
                ovl_path_upper(dentry, &realpath);
        }
 
+       if (realpath.dentry->d_flags & DCACHE_OP_SELECT_INODE)
+               return realpath.dentry->d_op->d_select_inode(realpath.dentry, file_flags);
+
        return d_backing_inode(realpath.dentry);
 }
 
index 79073d68b475d71b0f87902550b3eeef945885b5..e38ee0fed24a2f7a343f294a793b6abea93f6f97 100644 (file)
@@ -544,6 +544,7 @@ static void ovl_put_super(struct super_block *sb)
        mntput(ufs->upper_mnt);
        for (i = 0; i < ufs->numlower; i++)
                mntput(ufs->lower_mnt[i]);
+       kfree(ufs->lower_mnt);
 
        kfree(ufs->config.lowerdir);
        kfree(ufs->config.upperdir);
@@ -1048,6 +1049,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
                oe->lowerstack[i].dentry = stack[i].dentry;
                oe->lowerstack[i].mnt = ufs->lower_mnt[i];
        }
+       kfree(stack);
 
        root_dentry->d_fsdata = oe;
 
index a23209b43842106c6a74de8a51d6b4b752613157..1b4d69f68c33cc73ad99a1136b2408c71e763fb8 100644 (file)
@@ -116,6 +116,8 @@ struct bdi_writeback {
        struct list_head work_list;
        struct delayed_work dwork;      /* work item used for writeback */
 
+       struct list_head bdi_node;      /* anchored at bdi->wb_list */
+
 #ifdef CONFIG_CGROUP_WRITEBACK
        struct percpu_ref refcnt;       /* used only for !root wb's */
        struct fprop_local_percpu memcg_completions;
@@ -150,6 +152,7 @@ struct backing_dev_info {
        atomic_long_t tot_write_bandwidth;
 
        struct bdi_writeback wb;  /* the root writeback info for this bdi */
+       struct list_head wb_list; /* list of all wbs */
 #ifdef CONFIG_CGROUP_WRITEBACK
        struct radix_tree_root cgwb_tree; /* radix tree of active cgroup wbs */
        struct rb_root cgwb_congested_tree; /* their congested states */
index d5eb4ad1c534a8074b64ee75d4b597563e36e89a..c85f74946a8bab65ff3f16cddea6a4446b0a4799 100644 (file)
 #include <linux/slab.h>
 
 int __must_check bdi_init(struct backing_dev_info *bdi);
-void bdi_destroy(struct backing_dev_info *bdi);
+void bdi_exit(struct backing_dev_info *bdi);
 
 __printf(3, 4)
 int bdi_register(struct backing_dev_info *bdi, struct device *parent,
                const char *fmt, ...);
 int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
+void bdi_unregister(struct backing_dev_info *bdi);
+
 int __must_check bdi_setup_and_register(struct backing_dev_info *, char *);
+void bdi_destroy(struct backing_dev_info *bdi);
+
 void wb_start_writeback(struct bdi_writeback *wb, long nr_pages,
                        bool range_cyclic, enum wb_reason reason);
 void wb_start_background_writeback(struct bdi_writeback *wb);
@@ -408,61 +412,6 @@ static inline void unlocked_inode_to_wb_end(struct inode *inode, bool locked)
        rcu_read_unlock();
 }
 
-struct wb_iter {
-       int                     start_memcg_id;
-       struct radix_tree_iter  tree_iter;
-       void                    **slot;
-};
-
-static inline struct bdi_writeback *__wb_iter_next(struct wb_iter *iter,
-                                                  struct backing_dev_info *bdi)
-{
-       struct radix_tree_iter *titer = &iter->tree_iter;
-
-       WARN_ON_ONCE(!rcu_read_lock_held());
-
-       if (iter->start_memcg_id >= 0) {
-               iter->slot = radix_tree_iter_init(titer, iter->start_memcg_id);
-               iter->start_memcg_id = -1;
-       } else {
-               iter->slot = radix_tree_next_slot(iter->slot, titer, 0);
-       }
-
-       if (!iter->slot)
-               iter->slot = radix_tree_next_chunk(&bdi->cgwb_tree, titer, 0);
-       if (iter->slot)
-               return *iter->slot;
-       return NULL;
-}
-
-static inline struct bdi_writeback *__wb_iter_init(struct wb_iter *iter,
-                                                  struct backing_dev_info *bdi,
-                                                  int start_memcg_id)
-{
-       iter->start_memcg_id = start_memcg_id;
-
-       if (start_memcg_id)
-               return __wb_iter_next(iter, bdi);
-       else
-               return &bdi->wb;
-}
-
-/**
- * bdi_for_each_wb - walk all wb's of a bdi in ascending memcg ID order
- * @wb_cur: cursor struct bdi_writeback pointer
- * @bdi: bdi to walk wb's of
- * @iter: pointer to struct wb_iter to be used as iteration buffer
- * @start_memcg_id: memcg ID to start iteration from
- *
- * Iterate @wb_cur through the wb's (bdi_writeback's) of @bdi in ascending
- * memcg ID order starting from @start_memcg_id.  @iter is struct wb_iter
- * to be used as temp storage during iteration.  rcu_read_lock() must be
- * held throughout iteration.
- */
-#define bdi_for_each_wb(wb_cur, bdi, iter, start_memcg_id)             \
-       for ((wb_cur) = __wb_iter_init(iter, bdi, start_memcg_id);      \
-            (wb_cur); (wb_cur) = __wb_iter_next(iter, bdi))
-
 #else  /* CONFIG_CGROUP_WRITEBACK */
 
 static inline bool inode_cgwb_enabled(struct inode *inode)
@@ -522,14 +471,6 @@ static inline void wb_blkcg_offline(struct blkcg *blkcg)
 {
 }
 
-struct wb_iter {
-       int             next_id;
-};
-
-#define bdi_for_each_wb(wb_cur, bdi, iter, start_blkcg_id)             \
-       for ((iter)->next_id = (start_blkcg_id);                        \
-            ({ (wb_cur) = !(iter)->next_id++ ? &(bdi)->wb : NULL; }); )
-
 static inline int inode_congested(struct inode *inode, int cong_bits)
 {
        return wb_congested(&inode_to_bdi(inode)->wb, cong_bits);
index 0a5cc7a1109b9b2c655020c6c849960506f1cbc6..c02e669945e9279bceb796eb9a1adb938ebf863b 100644 (file)
@@ -713,9 +713,9 @@ static inline bool blkcg_bio_issue_check(struct request_queue *q,
 
        if (!throtl) {
                blkg = blkg ?: q->root_blkg;
-               blkg_rwstat_add(&blkg->stat_bytes, bio->bi_flags,
+               blkg_rwstat_add(&blkg->stat_bytes, bio->bi_rw,
                                bio->bi_iter.bi_size);
-               blkg_rwstat_add(&blkg->stat_ios, bio->bi_flags, 1);
+               blkg_rwstat_add(&blkg->stat_ios, bio->bi_rw, 1);
        }
 
        rcu_read_unlock();
index f7ef093ec49a2bbdd637aae6ab0f1bf0fa4e1e32..29f9e774ab76ef5c1deb019a142af3027a43ebce 100644 (file)
@@ -26,6 +26,6 @@ extern int __init cma_declare_contiguous(phys_addr_t base,
 extern int cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
                                        unsigned int order_per_bit,
                                        struct cma **res_cma);
-extern struct page *cma_alloc(struct cma *cma, unsigned int count, unsigned int align);
+extern struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align);
 extern bool cma_release(struct cma *cma, const struct page *pages, unsigned int count);
 #endif
index dfaa7b3e9ae900676b61dc7c3f693c78de97e8cd..8efb40e61d6e48021d68f93635eea8d3ab3e8c0b 100644 (file)
 #define KASAN_ABI_VERSION 3
 #endif
 
+#if GCC_VERSION >= 40902
+/*
+ * Tell the compiler that address safety instrumentation (KASAN)
+ * should not be applied to that function.
+ * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
+ */
+#define __no_sanitize_address __attribute__((no_sanitize_address))
+#endif
+
 #endif /* gcc version >= 40000 specific checks */
 
 #if !defined(__noclone)
 #define __noclone      /* not needed */
 #endif
 
+#if !defined(__no_sanitize_address)
+#define __no_sanitize_address
+#endif
+
 /*
  * A trick to suppress uninitialized variable warning without generating any
  * code
index c836eb2dc44d5b3a4d5e98dfbbd274c4448daa90..3d7810341b579795398e36cb15597feb344bb912 100644 (file)
@@ -198,19 +198,45 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
 
 #include <uapi/linux/types.h>
 
-static __always_inline void __read_once_size(const volatile void *p, void *res, int size)
+#define __READ_ONCE_SIZE                                               \
+({                                                                     \
+       switch (size) {                                                 \
+       case 1: *(__u8 *)res = *(volatile __u8 *)p; break;              \
+       case 2: *(__u16 *)res = *(volatile __u16 *)p; break;            \
+       case 4: *(__u32 *)res = *(volatile __u32 *)p; break;            \
+       case 8: *(__u64 *)res = *(volatile __u64 *)p; break;            \
+       default:                                                        \
+               barrier();                                              \
+               __builtin_memcpy((void *)res, (const void *)p, size);   \
+               barrier();                                              \
+       }                                                               \
+})
+
+static __always_inline
+void __read_once_size(const volatile void *p, void *res, int size)
 {
-       switch (size) {
-       case 1: *(__u8 *)res = *(volatile __u8 *)p; break;
-       case 2: *(__u16 *)res = *(volatile __u16 *)p; break;
-       case 4: *(__u32 *)res = *(volatile __u32 *)p; break;
-       case 8: *(__u64 *)res = *(volatile __u64 *)p; break;
-       default:
-               barrier();
-               __builtin_memcpy((void *)res, (const void *)p, size);
-               barrier();
-       }
+       __READ_ONCE_SIZE;
+}
+
+#ifdef CONFIG_KASAN
+/*
+ * This function is not 'inline' because __no_sanitize_address confilcts
+ * with inlining. Attempt to inline it may cause a build failure.
+ *     https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
+ * '__maybe_unused' allows us to avoid defined-but-not-used warnings.
+ */
+static __no_sanitize_address __maybe_unused
+void __read_once_size_nocheck(const volatile void *p, void *res, int size)
+{
+       __READ_ONCE_SIZE;
+}
+#else
+static __always_inline
+void __read_once_size_nocheck(const volatile void *p, void *res, int size)
+{
+       __READ_ONCE_SIZE;
 }
+#endif
 
 static __always_inline void __write_once_size(volatile void *p, void *res, int size)
 {
@@ -248,8 +274,22 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
  * required ordering.
  */
 
-#define READ_ONCE(x) \
-       ({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
+#define __READ_ONCE(x, check)                                          \
+({                                                                     \
+       union { typeof(x) __val; char __c[1]; } __u;                    \
+       if (check)                                                      \
+               __read_once_size(&(x), __u.__c, sizeof(x));             \
+       else                                                            \
+               __read_once_size_nocheck(&(x), __u.__c, sizeof(x));     \
+       __u.__val;                                                      \
+})
+#define READ_ONCE(x) __READ_ONCE(x, 1)
+
+/*
+ * Use READ_ONCE_NOCHECK() instead of READ_ONCE() if you need
+ * to hide memory access from KASAN.
+ */
+#define READ_ONCE_NOCHECK(x) __READ_ONCE(x, 0)
 
 #define WRITE_ONCE(x, val) \
 ({                                                     \
index 569bbd039896f330923d53b4a6231ba1c73e70cc..fec734df1524799e1e7137e943098c907d0fce8c 100644 (file)
@@ -111,7 +111,7 @@ static inline int dma_declare_contiguous(struct device *dev, phys_addr_t size,
        return ret;
 }
 
-struct page *dma_alloc_from_contiguous(struct device *dev, int count,
+struct page *dma_alloc_from_contiguous(struct device *dev, size_t count,
                                       unsigned int order);
 bool dma_release_from_contiguous(struct device *dev, struct page *pages,
                                 int count);
@@ -144,7 +144,7 @@ int dma_declare_contiguous(struct device *dev, phys_addr_t size,
 }
 
 static inline
-struct page *dma_alloc_from_contiguous(struct device *dev, int count,
+struct page *dma_alloc_from_contiguous(struct device *dev, size_t count,
                                       unsigned int order)
 {
        return NULL;
index 6452ff4c463fd8715edc9a5043bc812521a18d6a..3e3318ddfc0e3e09a0e15825f78eb6052d628d78 100644 (file)
@@ -676,8 +676,9 @@ enum {
 
 struct list_head *mem_cgroup_cgwb_list(struct mem_cgroup *memcg);
 struct wb_domain *mem_cgroup_wb_domain(struct bdi_writeback *wb);
-void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pavail,
-                        unsigned long *pdirty, unsigned long *pwriteback);
+void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pfilepages,
+                        unsigned long *pheadroom, unsigned long *pdirty,
+                        unsigned long *pwriteback);
 
 #else  /* CONFIG_CGROUP_WRITEBACK */
 
@@ -687,7 +688,8 @@ static inline struct wb_domain *mem_cgroup_wb_domain(struct bdi_writeback *wb)
 }
 
 static inline void mem_cgroup_wb_stats(struct bdi_writeback *wb,
-                                      unsigned long *pavail,
+                                      unsigned long *pfilepages,
+                                      unsigned long *pheadroom,
                                       unsigned long *pdirty,
                                       unsigned long *pwriteback)
 {
index 2d15e383144038ca12d5e876bf4e5cbfe5f84feb..210d11a75e4ff36bcdedb6496c9e5943cb24f465 100644 (file)
@@ -1054,6 +1054,10 @@ typedef u16 (*select_queue_fallback_t)(struct net_device *dev,
  *     This function is used to pass protocol port error state information
  *     to the switch driver. The switch driver can react to the proto_down
  *      by doing a phys down on the associated switch port.
+ * int (*ndo_fill_metadata_dst)(struct net_device *dev, struct sk_buff *skb);
+ *     This function is used to get egress tunnel information for given skb.
+ *     This is useful for retrieving outer tunnel header parameters while
+ *     sampling packet.
  *
  */
 struct net_device_ops {
@@ -1227,6 +1231,8 @@ struct net_device_ops {
        int                     (*ndo_get_iflink)(const struct net_device *dev);
        int                     (*ndo_change_proto_down)(struct net_device *dev,
                                                         bool proto_down);
+       int                     (*ndo_fill_metadata_dst)(struct net_device *dev,
+                                                      struct sk_buff *skb);
 };
 
 /**
@@ -2203,6 +2209,7 @@ void dev_add_offload(struct packet_offload *po);
 void dev_remove_offload(struct packet_offload *po);
 
 int dev_get_iflink(const struct net_device *dev);
+int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
 struct net_device *__dev_get_by_flags(struct net *net, unsigned short flags,
                                      unsigned short mask);
 struct net_device *dev_get_by_name(struct net *net, const char *name);
index cb1b9bbda332116b6e2173b011ff9fd58f83f431..b36d837c701ec9fe94280a91df3cf1e359ad50af 100644 (file)
@@ -64,7 +64,7 @@ struct unix_sock {
        struct socket_wq        peer_wq;
 };
 
-static inline struct unix_sock *unix_sk(struct sock *sk)
+static inline struct unix_sock *unix_sk(const struct sock *sk)
 {
        return (struct unix_sock *)sk;
 }
index af9d5382f6cbae8c38d45106f5702bd1e66c5671..ce009710120ca8b541615b237a329ee089ec357b 100644 (file)
@@ -60,6 +60,38 @@ static inline struct metadata_dst *tun_rx_dst(int md_size)
        return tun_dst;
 }
 
+static inline struct metadata_dst *tun_dst_unclone(struct sk_buff *skb)
+{
+       struct metadata_dst *md_dst = skb_metadata_dst(skb);
+       int md_size = md_dst->u.tun_info.options_len;
+       struct metadata_dst *new_md;
+
+       if (!md_dst)
+               return ERR_PTR(-EINVAL);
+
+       new_md = metadata_dst_alloc(md_size, GFP_ATOMIC);
+       if (!new_md)
+               return ERR_PTR(-ENOMEM);
+
+       memcpy(&new_md->u.tun_info, &md_dst->u.tun_info,
+              sizeof(struct ip_tunnel_info) + md_size);
+       skb_dst_drop(skb);
+       dst_hold(&new_md->dst);
+       skb_dst_set(skb, &new_md->dst);
+       return new_md;
+}
+
+static inline struct ip_tunnel_info *skb_tunnel_info_unclone(struct sk_buff *skb)
+{
+       struct metadata_dst *dst;
+
+       dst = tun_dst_unclone(skb);
+       if (IS_ERR(dst))
+               return NULL;
+
+       return &dst->u.tun_info;
+}
+
 static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb,
                                                 __be16 flags,
                                                 __be64 tunnel_id,
index 186f3a1e1b1f6ddd898d0f5871cb46222ae6b80d..fc19376986259de8faf9c2be4c5c3376780e54ff 100644 (file)
@@ -113,12 +113,12 @@ void __inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
 void __inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo,
                          bool rearm);
 
-static void inline inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo)
+static inline void inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo)
 {
        __inet_twsk_schedule(tw, timeo, false);
 }
 
-static void inline inet_twsk_reschedule(struct inet_timewait_sock *tw, int timeo)
+static inline void inet_twsk_reschedule(struct inet_timewait_sock *tw, int timeo)
 {
        __inet_twsk_schedule(tw, timeo, true);
 }
index 7aa78440559a47db8e5ccc8ea69a34f87b90c125..e23717013a4e6cb1ef84e6b8ba6654b011ee8670 100644 (file)
@@ -828,6 +828,14 @@ static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *s
        if (sk_rcvqueues_full(sk, limit))
                return -ENOBUFS;
 
+       /*
+        * If the skb was allocated from pfmemalloc reserves, only
+        * allow SOCK_MEMALLOC sockets to use it as this socket is
+        * helping free memory
+        */
+       if (skb_pfmemalloc(skb) && !sock_flag(sk, SOCK_MEMALLOC))
+               return -ENOMEM;
+
        __sk_add_backlog(sk, skb);
        sk->sk_backlog.len += skb->truesize;
        return 0;
index 884e728b09d9a57e8a56ac8ea224b3f873cb81c3..26ede14597daba32f8bf2cfcc84a821d094cc3d3 100644 (file)
@@ -86,7 +86,7 @@
        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
        SNDRV_CTL_ELEM_ACCESS_READWRITE, \
        .tlv.p  = (tlv_array),\
-       .info = snd_soc_info_volsw, \
+       .info = snd_soc_info_volsw_sx, \
        .get = snd_soc_get_volsw_sx,\
        .put = snd_soc_put_volsw_sx, \
        .private_value = (unsigned long)&(struct soc_mixer_control) \
        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
        SNDRV_CTL_ELEM_ACCESS_READWRITE, \
        .tlv.p  = (tlv_array), \
-       .info = snd_soc_info_volsw, \
+       .info = snd_soc_info_volsw_sx, \
        .get = snd_soc_get_volsw_sx, \
        .put = snd_soc_put_volsw_sx, \
        .private_value = (unsigned long)&(struct soc_mixer_control) \
@@ -574,6 +574,8 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
 int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_info *uinfo);
+int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
+                         struct snd_ctl_elem_info *uinfo);
 #define snd_soc_info_bool_ext          snd_ctl_boolean_mono_info
 int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol);
index 898be3a8db9aecfc8c9e942e03053b582be3af2a..6d8f8fba33414a40cefc344811ec3acfecd72f01 100644 (file)
 #define WM8904_MIC_REGS  2
 #define WM8904_GPIO_REGS 4
 #define WM8904_DRC_REGS  4
-#define WM8904_EQ_REGS   25
+#define WM8904_EQ_REGS   24
 
 /**
  * DRC configurations are specified with a label and a set of register
index 32e07d8cbaf47cf80841adf0e872d85c26c8c708..e663627a8ef36530b4dc658e9d30d4b7bc32a90a 100644 (file)
@@ -323,10 +323,10 @@ enum ovs_key_attr {
        OVS_KEY_ATTR_MPLS,      /* array of struct ovs_key_mpls.
                                 * The implementation may restrict
                                 * the accepted length of the array. */
-       OVS_KEY_ATTR_CT_STATE,  /* u8 bitmask of OVS_CS_F_* */
+       OVS_KEY_ATTR_CT_STATE,  /* u32 bitmask of OVS_CS_F_* */
        OVS_KEY_ATTR_CT_ZONE,   /* u16 connection tracking zone. */
        OVS_KEY_ATTR_CT_MARK,   /* u32 connection tracking mark */
-       OVS_KEY_ATTR_CT_LABEL /* 16-octet connection tracking label */
+       OVS_KEY_ATTR_CT_LABELS, /* 16-octet connection tracking label */
 
 #ifdef __KERNEL__
        OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
@@ -439,9 +439,9 @@ struct ovs_key_nd {
        __u8    nd_tll[ETH_ALEN];
 };
 
-#define OVS_CT_LABEL_LEN       16
-struct ovs_key_ct_label {
-       __u8    ct_label[OVS_CT_LABEL_LEN];
+#define OVS_CT_LABELS_LEN      16
+struct ovs_key_ct_labels {
+       __u8    ct_labels[OVS_CT_LABELS_LEN];
 };
 
 /* OVS_KEY_ATTR_CT_STATE flags */
@@ -449,9 +449,9 @@ struct ovs_key_ct_label {
 #define OVS_CS_F_ESTABLISHED       0x02 /* Part of an existing connection. */
 #define OVS_CS_F_RELATED           0x04 /* Related to an established
                                         * connection. */
-#define OVS_CS_F_INVALID           0x20 /* Could not track connection. */
-#define OVS_CS_F_REPLY_DIR         0x40 /* Flow is in the reply direction. */
-#define OVS_CS_F_TRACKED           0x80 /* Conntrack has occurred. */
+#define OVS_CS_F_REPLY_DIR         0x08 /* Flow is in the reply direction. */
+#define OVS_CS_F_INVALID           0x10 /* Could not track connection. */
+#define OVS_CS_F_TRACKED           0x20 /* Conntrack has occurred. */
 
 /**
  * enum ovs_flow_attr - attributes for %OVS_FLOW_* commands.
@@ -618,22 +618,25 @@ struct ovs_action_hash {
 
 /**
  * enum ovs_ct_attr - Attributes for %OVS_ACTION_ATTR_CT action.
- * @OVS_CT_ATTR_FLAGS: u32 connection tracking flags.
+ * @OVS_CT_ATTR_COMMIT: If present, commits the connection to the conntrack
+ * table. This allows future packets for the same connection to be identified
+ * as 'established' or 'related'. The flow key for the current packet will
+ * retain the pre-commit connection state.
  * @OVS_CT_ATTR_ZONE: u16 connection tracking zone.
  * @OVS_CT_ATTR_MARK: u32 value followed by u32 mask. For each bit set in the
  * mask, the corresponding bit in the value is copied to the connection
  * tracking mark field in the connection.
- * @OVS_CT_ATTR_LABEL: %OVS_CT_LABEL_LEN value followed by %OVS_CT_LABEL_LEN
+ * @OVS_CT_ATTR_LABEL: %OVS_CT_LABELS_LEN value followed by %OVS_CT_LABELS_LEN
  * mask. For each bit set in the mask, the corresponding bit in the value is
  * copied to the connection tracking label field in the connection.
  * @OVS_CT_ATTR_HELPER: variable length string defining conntrack ALG.
  */
 enum ovs_ct_attr {
        OVS_CT_ATTR_UNSPEC,
-       OVS_CT_ATTR_FLAGS,      /* u8 bitmask of OVS_CT_F_*. */
+       OVS_CT_ATTR_COMMIT,     /* No argument, commits connection. */
        OVS_CT_ATTR_ZONE,       /* u16 zone id. */
        OVS_CT_ATTR_MARK,       /* mark to associate with this connection. */
-       OVS_CT_ATTR_LABEL,      /* label to associate with this connection. */
+       OVS_CT_ATTR_LABELS,     /* labels to associate with this connection. */
        OVS_CT_ATTR_HELPER,     /* netlink helper to assist detection of
                                   related connections. */
        __OVS_CT_ATTR_MAX
@@ -641,14 +644,6 @@ enum ovs_ct_attr {
 
 #define OVS_CT_ATTR_MAX (__OVS_CT_ATTR_MAX - 1)
 
-/*
- * OVS_CT_ATTR_FLAGS flags - bitmask of %OVS_CT_F_*
- * @OVS_CT_F_COMMIT: Commits the flow to the conntrack table. This allows
- * future packets for the same connection to be identified as 'established'
- * or 'related'.
- */
-#define OVS_CT_F_COMMIT                0x01
-
 /**
  * enum ovs_action_attr - Action types.
  *
@@ -705,7 +700,7 @@ enum ovs_action_attr {
                                       * data immediately followed by a mask.
                                       * The data must be zero for the unmasked
                                       * bits. */
-       OVS_ACTION_ATTR_CT,           /* One nested OVS_CT_ATTR_* . */
+       OVS_ACTION_ATTR_CT,           /* Nested OVS_CT_ATTR_* . */
 
        __OVS_ACTION_ATTR_MAX,        /* Nothing past this will be accepted
                                       * from userspace. */
index 702024769c74bc39f1e9f8400b23ec5bbd7a8ffb..9d8f5d10c1e553122be08d3407434ea24d19c136 100644 (file)
@@ -160,7 +160,7 @@ struct rtattr {
 
 /* Macros to handle rtattributes */
 
-#define RTA_ALIGNTO    4
+#define RTA_ALIGNTO    4U
 #define RTA_ALIGN(len) ( ((len)+RTA_ALIGNTO-1) & ~(RTA_ALIGNTO-1) )
 #define RTA_OK(rta,len) ((len) >= (int)sizeof(struct rtattr) && \
                         (rta)->rta_len >= sizeof(struct rtattr) && \
index da98d0593de24206d68222d787d059a5a2b025a1..0277d1216f80ae1adeed84a686ed34c9b2931fc2 100644 (file)
@@ -327,9 +327,13 @@ static void call_usermodehelper_exec_work(struct work_struct *work)
                call_usermodehelper_exec_sync(sub_info);
        } else {
                pid_t pid;
-
+               /*
+                * Use CLONE_PARENT to reparent it to kthreadd; we do not
+                * want to pollute current->children, and we need a parent
+                * that always ignores SIGCHLD to ensure auto-reaping.
+                */
                pid = kernel_thread(call_usermodehelper_exec_async, sub_info,
-                                   SIGCHLD);
+                                   CLONE_PARENT | SIGCHLD);
                if (pid < 0) {
                        sub_info->retval = pid;
                        umh_complete(sub_info);
index b86b7bf1be388d72fe92fb6038b4a67b4710df1f..8f051a106676fb8f2d5457a9104340cce81ce37a 100644 (file)
@@ -1063,11 +1063,15 @@ void symbol_put_addr(void *addr)
        if (core_kernel_text(a))
                return;
 
-       /* module_text_address is safe here: we're supposed to have reference
-        * to module from symbol_get, so it can't go away. */
+       /*
+        * Even though we hold a reference on the module; we still need to
+        * disable preemption in order to safely traverse the data structure.
+        */
+       preempt_disable();
        modaddr = __module_text_address(a);
        BUG_ON(!modaddr);
        module_put(modaddr);
+       preempt_enable();
 }
 EXPORT_SYMBOL_GPL(symbol_put_addr);
 
index 10a8faa1b0d4a5f737bd9008eb8f9a7e817b6ec9..bcd214e4b4d630eb3304f6000a220dc881bafc24 100644 (file)
@@ -2366,8 +2366,15 @@ void wake_up_new_task(struct task_struct *p)
        trace_sched_wakeup_new(p);
        check_preempt_curr(rq, p, WF_FORK);
 #ifdef CONFIG_SMP
-       if (p->sched_class->task_woken)
+       if (p->sched_class->task_woken) {
+               /*
+                * Nothing relies on rq->lock after this, so its fine to
+                * drop it.
+                */
+               lockdep_unpin_lock(&rq->lock);
                p->sched_class->task_woken(rq, p);
+               lockdep_pin_lock(&rq->lock);
+       }
 #endif
        task_rq_unlock(rq, p, &flags);
 }
@@ -7238,9 +7245,6 @@ void __init sched_init_smp(void)
        alloc_cpumask_var(&non_isolated_cpus, GFP_KERNEL);
        alloc_cpumask_var(&fallback_doms, GFP_KERNEL);
 
-       /* nohz_full won't take effect without isolating the cpus. */
-       tick_nohz_full_add_cpus_to(cpu_isolated_map);
-
        sched_init_numa();
 
        /*
index fc8f01083527a570af73a8f8b4c6e586e7e332f9..8b0a15e285f9121ccd5540fa11eef49c94f017c1 100644 (file)
@@ -668,8 +668,15 @@ static enum hrtimer_restart dl_task_timer(struct hrtimer *timer)
         * Queueing this task back might have overloaded rq, check if we need
         * to kick someone away.
         */
-       if (has_pushable_dl_tasks(rq))
+       if (has_pushable_dl_tasks(rq)) {
+               /*
+                * Nothing relies on rq->lock after this, so its safe to drop
+                * rq->lock.
+                */
+               lockdep_unpin_lock(&rq->lock);
                push_dl_task(rq);
+               lockdep_pin_lock(&rq->lock);
+       }
 #endif
 
 unlock:
@@ -1066,8 +1073,9 @@ select_task_rq_dl(struct task_struct *p, int cpu, int sd_flag, int flags)
                int target = find_later_rq(p);
 
                if (target != -1 &&
-                               dl_time_before(p->dl.deadline,
-                                       cpu_rq(target)->dl.earliest_dl.curr))
+                               (dl_time_before(p->dl.deadline,
+                                       cpu_rq(target)->dl.earliest_dl.curr) ||
+                               (cpu_rq(target)->dl.dl_nr_running == 0)))
                        cpu = target;
        }
        rcu_read_unlock();
@@ -1417,7 +1425,8 @@ static struct rq *find_lock_later_rq(struct task_struct *task, struct rq *rq)
 
                later_rq = cpu_rq(cpu);
 
-               if (!dl_time_before(task->dl.deadline,
+               if (later_rq->dl.dl_nr_running &&
+                   !dl_time_before(task->dl.deadline,
                                        later_rq->dl.earliest_dl.curr)) {
                        /*
                         * Target rq has tasks of equal or earlier deadline,
index 6e2e3483b1ecff588e76103e0b7b7d673f16d2a5..9a5e60fe721a5e7e8036508f61950eeb0c8dea31 100644 (file)
@@ -2363,7 +2363,7 @@ static inline long calc_tg_weight(struct task_group *tg, struct cfs_rq *cfs_rq)
         */
        tg_weight = atomic_long_read(&tg->load_avg);
        tg_weight -= cfs_rq->tg_load_avg_contrib;
-       tg_weight += cfs_rq_load_avg(cfs_rq);
+       tg_weight += cfs_rq->load.weight;
 
        return tg_weight;
 }
@@ -2373,7 +2373,7 @@ static long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg)
        long tg_weight, load, shares;
 
        tg_weight = calc_tg_weight(tg, cfs_rq);
-       load = cfs_rq_load_avg(cfs_rq);
+       load = cfs_rq->load.weight;
 
        shares = (tg->shares * load);
        if (tg_weight)
@@ -2664,13 +2664,14 @@ static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq);
 /* Group cfs_rq's load_avg is used for task_h_load and update_cfs_share */
 static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
 {
-       int decayed;
        struct sched_avg *sa = &cfs_rq->avg;
+       int decayed, removed = 0;
 
        if (atomic_long_read(&cfs_rq->removed_load_avg)) {
                long r = atomic_long_xchg(&cfs_rq->removed_load_avg, 0);
                sa->load_avg = max_t(long, sa->load_avg - r, 0);
                sa->load_sum = max_t(s64, sa->load_sum - r * LOAD_AVG_MAX, 0);
+               removed = 1;
        }
 
        if (atomic_long_read(&cfs_rq->removed_util_avg)) {
@@ -2688,7 +2689,7 @@ static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
        cfs_rq->load_last_update_time_copy = sa->last_update_time;
 #endif
 
-       return decayed;
+       return decayed || removed;
 }
 
 /* Update task and its cfs_rq load average */
index 8f177c73ae199ba41878fea8de9a5b0a7196620a..4a2ef5a02fd3f91d7c4228378c23d5606bb73812 100644 (file)
@@ -57,9 +57,11 @@ static inline int cpu_idle_poll(void)
        rcu_idle_enter();
        trace_cpu_idle_rcuidle(0, smp_processor_id());
        local_irq_enable();
+       stop_critical_timings();
        while (!tif_need_resched() &&
                (cpu_idle_force_poll || tick_check_broadcast_expired()))
                cpu_relax();
+       start_critical_timings();
        trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
        rcu_idle_exit();
        return 1;
index b746399ab59c01e422da63468aa370b1b642a860..8abf1ba18085742af78176dbc514095a47643c9c 100644 (file)
@@ -85,9 +85,19 @@ check_stack(unsigned long ip, unsigned long *stack)
        if (!object_is_on_stack(stack))
                return;
 
+       /* Can't do this from NMI context (can cause deadlocks) */
+       if (in_nmi())
+               return;
+
        local_irq_save(flags);
        arch_spin_lock(&max_stack_lock);
 
+       /*
+        * RCU may not be watching, make it see us.
+        * The stack trace code uses rcu_sched.
+        */
+       rcu_irq_enter();
+
        /* In case another CPU set the tracer_frame on us */
        if (unlikely(!frame_size))
                this_size -= tracer_frame;
@@ -169,6 +179,7 @@ check_stack(unsigned long ip, unsigned long *stack)
        }
 
  out:
+       rcu_irq_exit();
        arch_spin_unlock(&max_stack_lock);
        local_irq_restore(flags);
 }
index ab76b99adc857fb38c2e4677b6ab34d6a01fa786..1d1521c26302a2510e873d49a8b6bb525f399d66 100644 (file)
@@ -197,6 +197,7 @@ config ENABLE_MUST_CHECK
 config FRAME_WARN
        int "Warn for stack frames larger than (needs gcc 4.4)"
        range 0 8192
+       default 0 if KASAN
        default 1024 if !64BIT
        default 2048 if 64BIT
        help
index f1cdeb024d172a488e1ed44f70ce1e090ee5e541..6a823a53e357bc83e84476d93cc2c155f0adfee5 100644 (file)
@@ -44,7 +44,7 @@ static void fail_dump(struct fault_attr *attr)
                printk(KERN_NOTICE "FAULT_INJECTION: forcing a failure.\n"
                       "name %pd, interval %lu, probability %lu, "
                       "space %d, times %d\n", attr->dname,
-                      attr->probability, attr->interval,
+                      attr->interval, attr->probability,
                       atomic_read(&attr->space),
                       atomic_read(&attr->times));
                if (attr->verbose > 1)
index 2df8ddcb0ca0a7f7a055456de4b46a8c55bbfdf1..619984fc07ec32792349c7fe8aec7c8b56e3d2a3 100644 (file)
@@ -480,6 +480,10 @@ static void cgwb_release_workfn(struct work_struct *work)
                                                release_work);
        struct backing_dev_info *bdi = wb->bdi;
 
+       spin_lock_irq(&cgwb_lock);
+       list_del_rcu(&wb->bdi_node);
+       spin_unlock_irq(&cgwb_lock);
+
        wb_shutdown(wb);
 
        css_put(wb->memcg_css);
@@ -575,6 +579,7 @@ static int cgwb_create(struct backing_dev_info *bdi,
                ret = radix_tree_insert(&bdi->cgwb_tree, memcg_css->id, wb);
                if (!ret) {
                        atomic_inc(&bdi->usage_cnt);
+                       list_add_tail_rcu(&wb->bdi_node, &bdi->wb_list);
                        list_add(&wb->memcg_node, memcg_cgwb_list);
                        list_add(&wb->blkcg_node, blkcg_cgwb_list);
                        css_get(memcg_css);
@@ -676,7 +681,7 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
 static void cgwb_bdi_destroy(struct backing_dev_info *bdi)
 {
        struct radix_tree_iter iter;
-       struct bdi_writeback_congested *congested, *congested_n;
+       struct rb_node *rbn;
        void **slot;
 
        WARN_ON(test_bit(WB_registered, &bdi->wb.state));
@@ -686,9 +691,11 @@ static void cgwb_bdi_destroy(struct backing_dev_info *bdi)
        radix_tree_for_each_slot(slot, &bdi->cgwb_tree, &iter, 0)
                cgwb_kill(*slot);
 
-       rbtree_postorder_for_each_entry_safe(congested, congested_n,
-                                       &bdi->cgwb_congested_tree, rb_node) {
-               rb_erase(&congested->rb_node, &bdi->cgwb_congested_tree);
+       while ((rbn = rb_first(&bdi->cgwb_congested_tree))) {
+               struct bdi_writeback_congested *congested =
+                       rb_entry(rbn, struct bdi_writeback_congested, rb_node);
+
+               rb_erase(rbn, &bdi->cgwb_congested_tree);
                congested->bdi = NULL;  /* mark @congested unlinked */
        }
 
@@ -764,15 +771,22 @@ static void cgwb_bdi_destroy(struct backing_dev_info *bdi) { }
 
 int bdi_init(struct backing_dev_info *bdi)
 {
+       int ret;
+
        bdi->dev = NULL;
 
        bdi->min_ratio = 0;
        bdi->max_ratio = 100;
        bdi->max_prop_frac = FPROP_FRAC_BASE;
        INIT_LIST_HEAD(&bdi->bdi_list);
+       INIT_LIST_HEAD(&bdi->wb_list);
        init_waitqueue_head(&bdi->wb_waitq);
 
-       return cgwb_bdi_init(bdi);
+       ret = cgwb_bdi_init(bdi);
+
+       list_add_tail_rcu(&bdi->wb.bdi_node, &bdi->wb_list);
+
+       return ret;
 }
 EXPORT_SYMBOL(bdi_init);
 
@@ -823,7 +837,7 @@ static void bdi_remove_from_list(struct backing_dev_info *bdi)
        synchronize_rcu_expedited();
 }
 
-void bdi_destroy(struct backing_dev_info *bdi)
+void bdi_unregister(struct backing_dev_info *bdi)
 {
        /* make sure nobody finds us on the bdi_list anymore */
        bdi_remove_from_list(bdi);
@@ -835,9 +849,19 @@ void bdi_destroy(struct backing_dev_info *bdi)
                device_unregister(bdi->dev);
                bdi->dev = NULL;
        }
+}
 
+void bdi_exit(struct backing_dev_info *bdi)
+{
+       WARN_ON_ONCE(bdi->dev);
        wb_exit(&bdi->wb);
 }
+
+void bdi_destroy(struct backing_dev_info *bdi)
+{
+       bdi_unregister(bdi);
+       bdi_exit(bdi);
+}
 EXPORT_SYMBOL(bdi_destroy);
 
 /*
index e7d1db5330254da4a8d265b8784d1eb645693447..4eb56badf37e60e63a5a1badd093d1934a21ad35 100644 (file)
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -361,7 +361,7 @@ err:
  * This function allocates part of contiguous memory on specific
  * contiguous memory area.
  */
-struct page *cma_alloc(struct cma *cma, unsigned int count, unsigned int align)
+struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align)
 {
        unsigned long mask, offset, pfn, start = 0;
        unsigned long bitmap_maxno, bitmap_no, bitmap_count;
@@ -371,7 +371,7 @@ struct page *cma_alloc(struct cma *cma, unsigned int count, unsigned int align)
        if (!cma || !cma->count)
                return NULL;
 
-       pr_debug("%s(cma %p, count %d, align %d)\n", __func__, (void *)cma,
+       pr_debug("%s(cma %p, count %zu, align %d)\n", __func__, (void *)cma,
                 count, align);
 
        if (!count)
index 1cc5467cf36ce7852f7a0474d5fd3237b3dfff10..327910c2400c6ce36f440383147fdc768cf14692 100644 (file)
@@ -2488,6 +2488,11 @@ again:
                        break;
                }
 
+               if (fatal_signal_pending(current)) {
+                       status = -EINTR;
+                       break;
+               }
+
                status = a_ops->write_begin(file, mapping, pos, bytes, flags,
                                                &page, &fsdata);
                if (unlikely(status < 0))
@@ -2525,10 +2530,6 @@ again:
                written += copied;
 
                balance_dirty_pages_ratelimited(mapping);
-               if (fatal_signal_pending(current)) {
-                       status = -EINTR;
-                       break;
-               }
        } while (iov_iter_count(i));
 
        return written ? written : status;
index 4b06b8db9df23c8f33406586507bbaecf7f5444c..bbac913f96bc1662ac3d7ef37c82080d9c17562f 100644 (file)
@@ -2206,7 +2206,8 @@ static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
        for (_pte = pte; _pte < pte+HPAGE_PMD_NR;
             _pte++, address += PAGE_SIZE) {
                pte_t pteval = *_pte;
-               if (pte_none(pteval) || is_zero_pfn(pte_pfn(pteval))) {
+               if (pte_none(pteval) || (pte_present(pteval) &&
+                               is_zero_pfn(pte_pfn(pteval)))) {
                        if (!userfaultfd_armed(vma) &&
                            ++none_or_zero <= khugepaged_max_ptes_none)
                                continue;
index d9b5c817dce8e0a99aab1853eafc572e5b70015f..c57c4423c68837d14816c5ff230435e1567e7c20 100644 (file)
@@ -3741,44 +3741,43 @@ struct wb_domain *mem_cgroup_wb_domain(struct bdi_writeback *wb)
 /**
  * mem_cgroup_wb_stats - retrieve writeback related stats from its memcg
  * @wb: bdi_writeback in question
- * @pavail: out parameter for number of available pages
+ * @pfilepages: out parameter for number of file pages
+ * @pheadroom: out parameter for number of allocatable pages according to memcg
  * @pdirty: out parameter for number of dirty pages
  * @pwriteback: out parameter for number of pages under writeback
  *
- * Determine the numbers of available, dirty, and writeback pages in @wb's
- * memcg.  Dirty and writeback are self-explanatory.  Available is a bit
- * more involved.
+ * Determine the numbers of file, headroom, dirty, and writeback pages in
+ * @wb's memcg.  File, dirty and writeback are self-explanatory.  Headroom
+ * is a bit more involved.
  *
- * A memcg's headroom is "min(max, high) - used".  The available memory is
- * calculated as the lowest headroom of itself and the ancestors plus the
- * number of pages already being used for file pages.  Note that this
- * doesn't consider the actual amount of available memory in the system.
- * The caller should further cap *@pavail accordingly.
+ * A memcg's headroom is "min(max, high) - used".  In the hierarchy, the
+ * headroom is calculated as the lowest headroom of itself and the
+ * ancestors.  Note that this doesn't consider the actual amount of
+ * available memory in the system.  The caller should further cap
+ * *@pheadroom accordingly.
  */
-void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pavail,
-                        unsigned long *pdirty, unsigned long *pwriteback)
+void mem_cgroup_wb_stats(struct bdi_writeback *wb, unsigned long *pfilepages,
+                        unsigned long *pheadroom, unsigned long *pdirty,
+                        unsigned long *pwriteback)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_css(wb->memcg_css);
        struct mem_cgroup *parent;
-       unsigned long head_room = PAGE_COUNTER_MAX;
-       unsigned long file_pages;
 
        *pdirty = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_DIRTY);
 
        /* this should eventually include NR_UNSTABLE_NFS */
        *pwriteback = mem_cgroup_read_stat(memcg, MEM_CGROUP_STAT_WRITEBACK);
+       *pfilepages = mem_cgroup_nr_lru_pages(memcg, (1 << LRU_INACTIVE_FILE) |
+                                                    (1 << LRU_ACTIVE_FILE));
+       *pheadroom = PAGE_COUNTER_MAX;
 
-       file_pages = mem_cgroup_nr_lru_pages(memcg, (1 << LRU_INACTIVE_FILE) |
-                                                   (1 << LRU_ACTIVE_FILE));
        while ((parent = parent_mem_cgroup(memcg))) {
                unsigned long ceiling = min(memcg->memory.limit, memcg->high);
                unsigned long used = page_counter_read(&memcg->memory);
 
-               head_room = min(head_room, ceiling - min(ceiling, used));
+               *pheadroom = min(*pheadroom, ceiling - min(ceiling, used));
                memcg = parent;
        }
-
-       *pavail = file_pages + head_room;
 }
 
 #else  /* CONFIG_CGROUP_WRITEBACK */
index 0a931cdd4f6baaa96cdfab2e0dd668c0abef8809..2c90357c34ea4c4d81521b7bf14d669d6565cc07 100644 (file)
@@ -145,9 +145,6 @@ struct dirty_throttle_control {
        unsigned long           pos_ratio;
 };
 
-#define DTC_INIT_COMMON(__wb)  .wb = (__wb),                           \
-                               .wb_completions = &(__wb)->completions
-
 /*
  * Length of period for aging writeout fractions of bdis. This is an
  * arbitrarily chosen number. The longer the period, the slower fractions will
@@ -157,12 +154,16 @@ struct dirty_throttle_control {
 
 #ifdef CONFIG_CGROUP_WRITEBACK
 
-#define GDTC_INIT(__wb)                .dom = &global_wb_domain,               \
-                               DTC_INIT_COMMON(__wb)
+#define GDTC_INIT(__wb)                .wb = (__wb),                           \
+                               .dom = &global_wb_domain,               \
+                               .wb_completions = &(__wb)->completions
+
 #define GDTC_INIT_NO_WB                .dom = &global_wb_domain
-#define MDTC_INIT(__wb, __gdtc)        .dom = mem_cgroup_wb_domain(__wb),      \
-                               .gdtc = __gdtc,                         \
-                               DTC_INIT_COMMON(__wb)
+
+#define MDTC_INIT(__wb, __gdtc)        .wb = (__wb),                           \
+                               .dom = mem_cgroup_wb_domain(__wb),      \
+                               .wb_completions = &(__wb)->memcg_completions, \
+                               .gdtc = __gdtc
 
 static bool mdtc_valid(struct dirty_throttle_control *dtc)
 {
@@ -213,7 +214,8 @@ static void wb_min_max_ratio(struct bdi_writeback *wb,
 
 #else  /* CONFIG_CGROUP_WRITEBACK */
 
-#define GDTC_INIT(__wb)                DTC_INIT_COMMON(__wb)
+#define GDTC_INIT(__wb)                .wb = (__wb),                           \
+                               .wb_completions = &(__wb)->completions
 #define GDTC_INIT_NO_WB
 #define MDTC_INIT(__wb, __gdtc)
 
@@ -682,13 +684,19 @@ static unsigned long hard_dirty_limit(struct wb_domain *dom,
        return max(thresh, dom->dirty_limit);
 }
 
-/* memory available to a memcg domain is capped by system-wide clean memory */
-static void mdtc_cap_avail(struct dirty_throttle_control *mdtc)
+/*
+ * Memory which can be further allocated to a memcg domain is capped by
+ * system-wide clean memory excluding the amount being used in the domain.
+ */
+static void mdtc_calc_avail(struct dirty_throttle_control *mdtc,
+                           unsigned long filepages, unsigned long headroom)
 {
        struct dirty_throttle_control *gdtc = mdtc_gdtc(mdtc);
-       unsigned long clean = gdtc->avail - min(gdtc->avail, gdtc->dirty);
+       unsigned long clean = filepages - min(filepages, mdtc->dirty);
+       unsigned long global_clean = gdtc->avail - min(gdtc->avail, gdtc->dirty);
+       unsigned long other_clean = global_clean - min(global_clean, clean);
 
-       mdtc->avail = min(mdtc->avail, clean);
+       mdtc->avail = filepages + min(headroom, other_clean);
 }
 
 /**
@@ -1562,16 +1570,16 @@ static void balance_dirty_pages(struct address_space *mapping,
                }
 
                if (mdtc) {
-                       unsigned long writeback;
+                       unsigned long filepages, headroom, writeback;
 
                        /*
                         * If @wb belongs to !root memcg, repeat the same
                         * basic calculations for the memcg domain.
                         */
-                       mem_cgroup_wb_stats(wb, &mdtc->avail, &mdtc->dirty,
-                                           &writeback);
-                       mdtc_cap_avail(mdtc);
+                       mem_cgroup_wb_stats(wb, &filepages, &headroom,
+                                           &mdtc->dirty, &writeback);
                        mdtc->dirty += writeback;
+                       mdtc_calc_avail(mdtc, filepages, headroom);
 
                        domain_dirty_limits(mdtc);
 
@@ -1893,10 +1901,11 @@ bool wb_over_bg_thresh(struct bdi_writeback *wb)
                return true;
 
        if (mdtc) {
-               unsigned long writeback;
+               unsigned long filepages, headroom, writeback;
 
-               mem_cgroup_wb_stats(wb, &mdtc->avail, &mdtc->dirty, &writeback);
-               mdtc_cap_avail(mdtc);
+               mem_cgroup_wb_stats(wb, &filepages, &headroom, &mdtc->dirty,
+                                   &writeback);
+               mdtc_calc_avail(mdtc, filepages, headroom);
                domain_dirty_limits(mdtc);      /* ditto, ignore writeback */
 
                if (mdtc->dirty > mdtc->bg_thresh)
@@ -1956,7 +1965,6 @@ void laptop_mode_timer_fn(unsigned long data)
        int nr_pages = global_page_state(NR_FILE_DIRTY) +
                global_page_state(NR_UNSTABLE_NFS);
        struct bdi_writeback *wb;
-       struct wb_iter iter;
 
        /*
         * We want to write everything out, not just down to the dirty
@@ -1965,10 +1973,12 @@ void laptop_mode_timer_fn(unsigned long data)
        if (!bdi_has_dirty_io(&q->backing_dev_info))
                return;
 
-       bdi_for_each_wb(wb, &q->backing_dev_info, &iter, 0)
+       rcu_read_lock();
+       list_for_each_entry_rcu(wb, &q->backing_dev_info.wb_list, bdi_node)
                if (wb_has_dirty_io(wb))
                        wb_start_writeback(wb, nr_pages, true,
                                           WB_REASON_LAPTOP_TIMER);
+       rcu_read_unlock();
 }
 
 /*
index b4548c739a6475446d643bd5b01ab8627ef1f08e..2dda439c8cb83b7fa72b238dcf93023088762001 100644 (file)
@@ -91,10 +91,50 @@ static void hci_connect_le_scan_cleanup(struct hci_conn *conn)
         * autoconnect action, remove them completely. If they are, just unmark
         * them as waiting for connection, by clearing explicit_connect field.
         */
-       if (params->auto_connect == HCI_AUTO_CONN_EXPLICIT)
+       params->explicit_connect = false;
+
+       list_del_init(&params->action);
+
+       switch (params->auto_connect) {
+       case HCI_AUTO_CONN_EXPLICIT:
                hci_conn_params_del(conn->hdev, bdaddr, bdaddr_type);
-       else
-               params->explicit_connect = false;
+               /* return instead of break to avoid duplicate scan update */
+               return;
+       case HCI_AUTO_CONN_DIRECT:
+       case HCI_AUTO_CONN_ALWAYS:
+               list_add(&params->action, &conn->hdev->pend_le_conns);
+               break;
+       case HCI_AUTO_CONN_REPORT:
+               list_add(&params->action, &conn->hdev->pend_le_reports);
+               break;
+       default:
+               break;
+       }
+
+       hci_update_background_scan(conn->hdev);
+}
+
+static void hci_conn_cleanup(struct hci_conn *conn)
+{
+       struct hci_dev *hdev = conn->hdev;
+
+       if (test_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags))
+               hci_conn_params_del(conn->hdev, &conn->dst, conn->dst_type);
+
+       hci_chan_list_flush(conn);
+
+       hci_conn_hash_del(hdev, conn);
+
+       if (hdev->notify)
+               hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
+
+       hci_conn_del_sysfs(conn);
+
+       debugfs_remove_recursive(conn->debugfs);
+
+       hci_dev_put(hdev);
+
+       hci_conn_put(conn);
 }
 
 /* This function requires the caller holds hdev->lock */
@@ -102,8 +142,13 @@ static void hci_connect_le_scan_remove(struct hci_conn *conn)
 {
        hci_connect_le_scan_cleanup(conn);
 
-       hci_conn_hash_del(conn->hdev, conn);
-       hci_update_background_scan(conn->hdev);
+       /* We can't call hci_conn_del here since that would deadlock
+        * with trying to call cancel_delayed_work_sync(&conn->disc_work).
+        * Instead, call just hci_conn_cleanup() which contains the bare
+        * minimum cleanup operations needed for a connection in this
+        * state.
+        */
+       hci_conn_cleanup(conn);
 }
 
 static void hci_acl_create_connection(struct hci_conn *conn)
@@ -581,27 +626,17 @@ int hci_conn_del(struct hci_conn *conn)
                }
        }
 
-       hci_chan_list_flush(conn);
-
        if (conn->amp_mgr)
                amp_mgr_put(conn->amp_mgr);
 
-       hci_conn_hash_del(hdev, conn);
-       if (hdev->notify)
-               hdev->notify(hdev, HCI_NOTIFY_CONN_DEL);
-
        skb_queue_purge(&conn->data_q);
 
-       hci_conn_del_sysfs(conn);
-
-       debugfs_remove_recursive(conn->debugfs);
-
-       if (test_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags))
-               hci_conn_params_del(conn->hdev, &conn->dst, conn->dst_type);
-
-       hci_dev_put(hdev);
-
-       hci_conn_put(conn);
+       /* Remove the connection from the list and cleanup its remaining
+        * state. This is a separate function since for some cases like
+        * BT_CONNECT_SCAN we *only* want the cleanup part without the
+        * rest of hci_conn_del.
+        */
+       hci_conn_cleanup(conn);
 
        return 0;
 }
@@ -973,15 +1008,23 @@ static int hci_explicit_conn_params_set(struct hci_request *req,
        if (is_connected(hdev, addr, addr_type))
                return -EISCONN;
 
-       params = hci_conn_params_add(hdev, addr, addr_type);
-       if (!params)
-               return -EIO;
+       params = hci_conn_params_lookup(hdev, addr, addr_type);
+       if (!params) {
+               params = hci_conn_params_add(hdev, addr, addr_type);
+               if (!params)
+                       return -ENOMEM;
 
-       /* If we created new params, or existing params were marked as disabled,
-        * mark them to be used just once to connect.
-        */
-       if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
+               /* If we created new params, mark them to be deleted in
+                * hci_connect_le_scan_cleanup. It's different case than
+                * existing disabled params, those will stay after cleanup.
+                */
                params->auto_connect = HCI_AUTO_CONN_EXPLICIT;
+       }
+
+       /* We're trying to connect, so make sure params are at pend_le_conns */
+       if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
+           params->auto_connect == HCI_AUTO_CONN_REPORT ||
+           params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
                list_del_init(&params->action);
                list_add(&params->action, &hdev->pend_le_conns);
        }
index adcbc74c243268e8330bf760c39fa792a1c2a3a8..e837539452fb0e2880d8335da7769752a3b08110 100644 (file)
@@ -2861,13 +2861,6 @@ struct hci_conn_params *hci_explicit_connect_lookup(struct hci_dev *hdev,
                        return param;
        }
 
-       list_for_each_entry(param, &hdev->pend_le_reports, action) {
-               if (bacmp(&param->addr, addr) == 0 &&
-                   param->addr_type == addr_type &&
-                   param->explicit_connect)
-                       return param;
-       }
-
        return NULL;
 }
 
index 186041866315a4e107de086df52142f39d6c6ee3..bc31099d3b5bd113a8496b2ccad9e3e40364187f 100644 (file)
@@ -55,7 +55,12 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)
        wake_up_bit(&hdev->flags, HCI_INQUIRY);
 
        hci_dev_lock(hdev);
-       hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+       /* Set discovery state to stopped if we're not doing LE active
+        * scanning.
+        */
+       if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
+           hdev->le_scan_type != LE_SCAN_ACTIVE)
+               hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
        hci_dev_unlock(hdev);
 
        hci_conn_check_pending(hdev);
@@ -4648,8 +4653,8 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
        /* If we're not connectable only connect devices that we have in
         * our pend_le_conns list.
         */
-       params = hci_explicit_connect_lookup(hdev, addr, addr_type);
-
+       params = hci_pend_le_action_lookup(&hdev->pend_le_conns, addr,
+                                          addr_type);
        if (!params)
                return NULL;
 
index ccaf5a436d8f7a70799729a04ffc17583d11913f..c4fe2fee753fcfaa4233a4bb6675bbbdd29fc9d5 100644 (file)
@@ -3545,6 +3545,7 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
                                       auth_type);
        } else {
                u8 addr_type;
+               struct hci_conn_params *p;
 
                /* Convert from L2CAP channel address type to HCI address type
                 */
@@ -3562,7 +3563,10 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
                 * If connection parameters already exist, then they
                 * will be kept and this function does nothing.
                 */
-               hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
+               p = hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
+
+               if (p->auto_connect == HCI_AUTO_CONN_EXPLICIT)
+                       p->auto_connect = HCI_AUTO_CONN_DISABLED;
 
                conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr,
                                           addr_type, sec_level,
@@ -6117,14 +6121,21 @@ static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
                __hci_update_background_scan(req);
                break;
        case HCI_AUTO_CONN_REPORT:
-               list_add(&params->action, &hdev->pend_le_reports);
+               if (params->explicit_connect)
+                       list_add(&params->action, &hdev->pend_le_conns);
+               else
+                       list_add(&params->action, &hdev->pend_le_reports);
                __hci_update_background_scan(req);
                break;
        case HCI_AUTO_CONN_DIRECT:
        case HCI_AUTO_CONN_ALWAYS:
                if (!is_connected(hdev, addr, addr_type)) {
                        list_add(&params->action, &hdev->pend_le_conns);
-                       __hci_update_background_scan(req);
+                       /* If we are in scan phase of connecting, we were
+                        * already added to pend_le_conns and scanning.
+                        */
+                       if (params->auto_connect != HCI_AUTO_CONN_EXPLICIT)
+                               __hci_update_background_scan(req);
                }
                break;
        }
@@ -6379,7 +6390,8 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
                        goto unlock;
                }
 
-               if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
+               if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
+                   params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
                        err = cmd->cmd_complete(cmd,
                                                MGMT_STATUS_INVALID_PARAMS);
                        mgmt_pending_remove(cmd);
@@ -6415,6 +6427,10 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
                        if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
                                continue;
                        device_removed(sk, hdev, &p->addr, p->addr_type);
+                       if (p->explicit_connect) {
+                               p->auto_connect = HCI_AUTO_CONN_EXPLICIT;
+                               continue;
+                       }
                        list_del(&p->action);
                        list_del(&p->list);
                        kfree(p);
index 6bb6470f5b7bbbfaa60de8e33277b63aadbdb641..c14748d051e7f58343768e920e52317154ef06fb 100644 (file)
@@ -99,6 +99,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/stat.h>
 #include <net/dst.h>
+#include <net/dst_metadata.h>
 #include <net/pkt_sched.h>
 #include <net/checksum.h>
 #include <net/xfrm.h>
@@ -681,6 +682,32 @@ int dev_get_iflink(const struct net_device *dev)
 }
 EXPORT_SYMBOL(dev_get_iflink);
 
+/**
+ *     dev_fill_metadata_dst - Retrieve tunnel egress information.
+ *     @dev: targeted interface
+ *     @skb: The packet.
+ *
+ *     For better visibility of tunnel traffic OVS needs to retrieve
+ *     egress tunnel information for a packet. Following API allows
+ *     user to get this info.
+ */
+int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct ip_tunnel_info *info;
+
+       if (!dev->netdev_ops  || !dev->netdev_ops->ndo_fill_metadata_dst)
+               return -EINVAL;
+
+       info = skb_tunnel_info_unclone(skb);
+       if (!info)
+               return -ENOMEM;
+       if (unlikely(!(info->mode & IP_TUNNEL_INFO_TX)))
+               return -EINVAL;
+
+       return dev->netdev_ops->ndo_fill_metadata_dst(dev, skb);
+}
+EXPORT_SYMBOL_GPL(dev_fill_metadata_dst);
+
 /**
  *     __dev_get_by_name       - find a device by its name
  *     @net: the applicable net namespace
index b495ab1797fae303d12a3251f09b141052c1ff55..29edf74846fc9cfef49f3fc35b4ba41de6c254af 100644 (file)
@@ -1284,7 +1284,7 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
 
        gstrings.len = ret;
 
-       data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
+       data = kcalloc(gstrings.len, ETH_GSTRING_LEN, GFP_USER);
        if (!data)
                return -ENOMEM;
 
index 05a04ea871728d2c18f68571321e9435df1f3b18..bb18c368000129ebea752a0a78785524848eaab8 100644 (file)
@@ -1415,6 +1415,7 @@ static u64 bpf_clone_redirect(u64 r1, u64 ifindex, u64 flags, u64 r4, u64 r5)
                return dev_forward_skb(dev, skb2);
 
        skb2->dev = dev;
+       skb_sender_cpu_clear(skb2);
        return dev_queue_xmit(skb2);
 }
 
@@ -1854,9 +1855,13 @@ int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf,
                goto out;
 
        /* We're copying the filter that has been originally attached,
-        * so no conversion/decode needed anymore.
+        * so no conversion/decode needed anymore. eBPF programs that
+        * have no original program cannot be dumped through this.
         */
+       ret = -EACCES;
        fprog = filter->prog->orig_prog;
+       if (!fprog)
+               goto out;
 
        ret = fprog->len;
        if (!len)
index c59fa5d9c22c449b4bfa9f058575d44324cfd7f9..adb5325f49348412efb50f0eeee5a5f0fa1e50ed 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_net.h>
 #include <linux/sysfs.h>
+#include <linux/phy_fixed.h>
 #include "dsa_priv.h"
 
 char dsa_driver_version[] = "0.1";
@@ -305,7 +306,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
        if (ret < 0)
                goto out;
 
-       ds->slave_mii_bus = mdiobus_alloc();
+       ds->slave_mii_bus = devm_mdiobus_alloc(parent);
        if (ds->slave_mii_bus == NULL) {
                ret = -ENOMEM;
                goto out;
@@ -314,7 +315,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 
        ret = mdiobus_register(ds->slave_mii_bus);
        if (ret < 0)
-               goto out_free;
+               goto out;
 
 
        /*
@@ -367,10 +368,7 @@ static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
 
        return ret;
 
-out_free:
-       mdiobus_free(ds->slave_mii_bus);
 out:
-       kfree(ds);
        return ret;
 }
 
@@ -400,7 +398,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
        /*
         * Allocate and initialise switch state.
         */
-       ds = kzalloc(sizeof(*ds) + drv->priv_size, GFP_KERNEL);
+       ds = devm_kzalloc(parent, sizeof(*ds) + drv->priv_size, GFP_KERNEL);
        if (ds == NULL)
                return ERR_PTR(-ENOMEM);
 
@@ -420,10 +418,47 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
 
 static void dsa_switch_destroy(struct dsa_switch *ds)
 {
+       struct device_node *port_dn;
+       struct phy_device *phydev;
+       struct dsa_chip_data *cd = ds->pd;
+       int port;
+
 #ifdef CONFIG_NET_DSA_HWMON
        if (ds->hwmon_dev)
                hwmon_device_unregister(ds->hwmon_dev);
 #endif
+
+       /* Disable configuration of the CPU and DSA ports */
+       for (port = 0; port < DSA_MAX_PORTS; port++) {
+               if (!(dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)))
+                       continue;
+
+               port_dn = cd->port_dn[port];
+               if (of_phy_is_fixed_link(port_dn)) {
+                       phydev = of_phy_find_device(port_dn);
+                       if (phydev) {
+                               int addr = phydev->addr;
+
+                               phy_device_free(phydev);
+                               of_node_put(port_dn);
+                               fixed_phy_del(addr);
+                       }
+               }
+       }
+
+       /* Destroy network devices for physical switch ports. */
+       for (port = 0; port < DSA_MAX_PORTS; port++) {
+               if (!(ds->phys_port_mask & (1 << port)))
+                       continue;
+
+               if (!ds->ports[port])
+                       continue;
+
+               unregister_netdev(ds->ports[port]);
+               free_netdev(ds->ports[port]);
+       }
+
+       mdiobus_unregister(ds->slave_mii_bus);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -802,10 +837,11 @@ static inline void dsa_of_remove(struct device *dev)
 }
 #endif
 
-static void dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
-                         struct device *parent, struct dsa_platform_data *pd)
+static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
+                        struct device *parent, struct dsa_platform_data *pd)
 {
        int i;
+       unsigned configured = 0;
 
        dst->pd = pd;
        dst->master_netdev = dev;
@@ -825,8 +861,16 @@ static void dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
                dst->ds[i] = ds;
                if (ds->drv->poll_link != NULL)
                        dst->link_poll_needed = 1;
+
+               ++configured;
        }
 
+       /*
+        * If no switch was found, exit cleanly
+        */
+       if (!configured)
+               return -EPROBE_DEFER;
+
        /*
         * If we use a tagging format that doesn't have an ethertype
         * field, make sure that all packets from this point on get
@@ -843,6 +887,8 @@ static void dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
                dst->link_poll_timer.expires = round_jiffies(jiffies + HZ);
                add_timer(&dst->link_poll_timer);
        }
+
+       return 0;
 }
 
 static int dsa_probe(struct platform_device *pdev)
@@ -883,7 +929,7 @@ static int dsa_probe(struct platform_device *pdev)
                goto out;
        }
 
-       dst = kzalloc(sizeof(*dst), GFP_KERNEL);
+       dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
        if (dst == NULL) {
                dev_put(dev);
                ret = -ENOMEM;
@@ -892,7 +938,9 @@ static int dsa_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, dst);
 
-       dsa_setup_dst(dst, dev, &pdev->dev, pd);
+       ret = dsa_setup_dst(dst, dev, &pdev->dev, pd);
+       if (ret)
+               goto out;
 
        return 0;
 
@@ -914,7 +962,7 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
        for (i = 0; i < dst->pd->nr_chips; i++) {
                struct dsa_switch *ds = dst->ds[i];
 
-               if (ds != NULL)
+               if (ds)
                        dsa_switch_destroy(ds);
        }
 }
index f03db8b7abee68806468c104470da4054a8bf755..0c9c3482e41997a671c23be7dc0387edb1403916 100644 (file)
@@ -312,7 +312,7 @@ static void arp_send_dst(int type, int ptype, __be32 dest_ip,
        if (!skb)
                return;
 
-       skb_dst_set(skb, dst);
+       skb_dst_set(skb, dst_clone(dst));
        arp_xmit(skb);
 }
 
@@ -384,7 +384,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
        }
 
        if (skb && !(dev->priv_flags & IFF_XMIT_DST_RELEASE))
-               dst = dst_clone(skb_dst(skb));
+               dst = skb_dst(skb);
        arp_send_dst(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr,
                     dst_hw, dev->dev_addr, NULL, dst);
 }
@@ -811,7 +811,7 @@ static int arp_process(struct sock *sk, struct sk_buff *skb)
                                } else {
                                        pneigh_enqueue(&arp_tbl,
                                                       in_dev->arp_parms, skb);
-                                       return 0;
+                                       goto out_free_dst;
                                }
                                goto out;
                        }
@@ -865,6 +865,8 @@ static int arp_process(struct sock *sk, struct sk_buff *skb)
 
 out:
        consume_skb(skb);
+out_free_dst:
+       dst_release(reply_dst);
        return 0;
 }
 
index 6c2af797f2f92b93cf4ea28d1d5deee4e725f757..744e5936c10d7ec555d1ca621f5bd4be57f1c72b 100644 (file)
@@ -1569,7 +1569,7 @@ static struct key_vector *leaf_walk_rcu(struct key_vector **tn, t_key key)
        do {
                /* record parent and next child index */
                pn = n;
-               cindex = key ? get_index(key, pn) : 0;
+               cindex = (key > pn->key) ? get_index(key, pn) : 0;
 
                if (cindex >> pn->bits)
                        break;
index 5aa46d4b44efb99702ccd89005528f20ae422a0e..5a8ee3282550880a7749b8d6a9086dc413661519 100644 (file)
@@ -36,7 +36,8 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
                                  SKB_GSO_TCP_ECN |
                                  SKB_GSO_GRE |
                                  SKB_GSO_GRE_CSUM |
-                                 SKB_GSO_IPIP)))
+                                 SKB_GSO_IPIP |
+                                 SKB_GSO_SIT)))
                goto out;
 
        if (!skb->encapsulation)
index 7bb9c39e0a4d1a6a30b7aece9d3b0c17e447c20a..61b45a17fc738e17146a5e1f1cf97774f338179e 100644 (file)
@@ -577,21 +577,22 @@ EXPORT_SYMBOL(inet_rtx_syn_ack);
 static bool reqsk_queue_unlink(struct request_sock_queue *queue,
                               struct request_sock *req)
 {
-       struct listen_sock *lopt = queue->listen_opt;
        struct request_sock **prev;
+       struct listen_sock *lopt;
        bool found = false;
 
        spin_lock(&queue->syn_wait_lock);
-
-       for (prev = &lopt->syn_table[req->rsk_hash]; *prev != NULL;
-            prev = &(*prev)->dl_next) {
-               if (*prev == req) {
-                       *prev = req->dl_next;
-                       found = true;
-                       break;
+       lopt = queue->listen_opt;
+       if (lopt) {
+               for (prev = &lopt->syn_table[req->rsk_hash]; *prev != NULL;
+                    prev = &(*prev)->dl_next) {
+                       if (*prev == req) {
+                               *prev = req->dl_next;
+                               found = true;
+                               break;
+                       }
                }
        }
-
        spin_unlock(&queue->syn_wait_lock);
        if (timer_pending(&req->rsk_timer) && del_timer_sync(&req->rsk_timer))
                reqsk_put(req);
index bd0679d90519b170dc98369e9b438e4c31b152b9..614521437e30159c5234e9b24fcc41bad7ea6c6b 100644 (file)
@@ -498,10 +498,26 @@ static struct sk_buff *gre_handle_offloads(struct sk_buff *skb,
                                        csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
 }
 
+static struct rtable *gre_get_rt(struct sk_buff *skb,
+                                struct net_device *dev,
+                                struct flowi4 *fl,
+                                const struct ip_tunnel_key *key)
+{
+       struct net *net = dev_net(dev);
+
+       memset(fl, 0, sizeof(*fl));
+       fl->daddr = key->u.ipv4.dst;
+       fl->saddr = key->u.ipv4.src;
+       fl->flowi4_tos = RT_TOS(key->tos);
+       fl->flowi4_mark = skb->mark;
+       fl->flowi4_proto = IPPROTO_GRE;
+
+       return ip_route_output_key(net, fl);
+}
+
 static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ip_tunnel_info *tun_info;
-       struct net *net = dev_net(dev);
        const struct ip_tunnel_key *key;
        struct flowi4 fl;
        struct rtable *rt;
@@ -516,14 +532,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev)
                goto err_free_skb;
 
        key = &tun_info->key;
-       memset(&fl, 0, sizeof(fl));
-       fl.daddr = key->u.ipv4.dst;
-       fl.saddr = key->u.ipv4.src;
-       fl.flowi4_tos = RT_TOS(key->tos);
-       fl.flowi4_mark = skb->mark;
-       fl.flowi4_proto = IPPROTO_GRE;
-
-       rt = ip_route_output_key(net, &fl);
+       rt = gre_get_rt(skb, dev, &fl, key);
        if (IS_ERR(rt))
                goto err_free_skb;
 
@@ -566,6 +575,24 @@ err_free_skb:
        dev->stats.tx_dropped++;
 }
 
+static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
+{
+       struct ip_tunnel_info *info = skb_tunnel_info(skb);
+       struct rtable *rt;
+       struct flowi4 fl4;
+
+       if (ip_tunnel_info_af(info) != AF_INET)
+               return -EINVAL;
+
+       rt = gre_get_rt(skb, dev, &fl4, &info->key);
+       if (IS_ERR(rt))
+               return PTR_ERR(rt);
+
+       ip_rt_put(rt);
+       info->key.u.ipv4.src = fl4.saddr;
+       return 0;
+}
+
 static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
                              struct net_device *dev)
 {
@@ -1023,6 +1050,7 @@ static const struct net_device_ops gre_tap_netdev_ops = {
        .ndo_change_mtu         = ip_tunnel_change_mtu,
        .ndo_get_stats64        = ip_tunnel_get_stats64,
        .ndo_get_iflink         = ip_tunnel_get_iflink,
+       .ndo_fill_metadata_dst  = gre_fill_metadata_dst,
 };
 
 static void ipgre_tap_setup(struct net_device *dev)
index 690d27d3f2f90d99612de8ed4a32dec0596a680a..a3558417653567ffe3a83d06515fb1b68ec36dcf 100644 (file)
@@ -75,6 +75,7 @@ endif # NF_TABLES
 
 config NF_DUP_IPV4
        tristate "Netfilter IPv4 packet duplication to alternate destination"
+       depends on !NF_CONNTRACK || NF_CONNTRACK
        help
          This option enables the nf_dup_ipv4 core, which duplicates an IPv4
          packet to be rerouted to another destination.
index 8618fd150c965015ca2ee256499add4186f4810a..c4ffc9de165420f5839006ec053859aff77147fe 100644 (file)
@@ -61,9 +61,7 @@ static bool rpfilter_lookup_reverse(struct flowi4 *fl4,
        if (FIB_RES_DEV(res) == dev)
                dev_match = true;
 #endif
-       if (dev_match || flags & XT_RPFILTER_LOOSE)
-               return FIB_RES_NH(res).nh_scope <= RT_SCOPE_HOST;
-       return dev_match;
+       return dev_match || flags & XT_RPFILTER_LOOSE;
 }
 
 static bool rpfilter_is_local(const struct sk_buff *skb)
index 7092a61c4dc8465fcf17ff71b289cf25bbb8b559..7e538f71f5fbae087c3e3e4367d60e08cd609ac5 100644 (file)
@@ -209,7 +209,7 @@ static void dctcp_update_alpha(struct sock *sk, u32 flags)
 
                /* alpha = (1 - g) * alpha + g * F */
 
-               alpha -= alpha >> dctcp_shift_g;
+               alpha -= min_not_zero(alpha, alpha >> dctcp_shift_g);
                if (bytes_ecn) {
                        /* If dctcp_shift_g == 1, a 32bit value would overflow
                         * after 8 Mbytes.
index 1100ffe4a722d7bbae1ec30ee165ecc565cc2e72..3dbee0d83b15b0cbd2a1008cab5eeb8f9365c878 100644 (file)
@@ -3405,7 +3405,7 @@ static int tcp_xmit_probe_skb(struct sock *sk, int urgent, int mib)
         */
        tcp_init_nondata_skb(skb, tp->snd_una - !urgent, TCPHDR_ACK);
        skb_mstamp_get(&skb->skb_mstamp);
-       NET_INC_STATS_BH(sock_net(sk), mib);
+       NET_INC_STATS(sock_net(sk), mib);
        return tcp_transmit_skb(sk, skb, 0, GFP_ATOMIC);
 }
 
index 2878dbfffeb7e769a32079f1a6b80061136a7efc..41a261355662eb42fae031fdd30132767469f98e 100644 (file)
@@ -30,6 +30,8 @@ static int xfrm4_tunnel_check_size(struct sk_buff *skb)
 
        mtu = dst_mtu(skb_dst(skb));
        if (skb->len > mtu) {
+               skb->protocol = htons(ETH_P_IP);
+
                if (skb->sk)
                        xfrm_local_error(skb, mtu);
                else
index 900113376d4e0e528dc5a5d349687ae908ca08d6..36b85bd05ac8a320b1b910c7d3454da1139ecd3c 100644 (file)
@@ -3119,6 +3119,8 @@ static void addrconf_gre_config(struct net_device *dev)
        }
 
        addrconf_addr_gen(idev, true);
+       if (dev->flags & IFF_POINTOPOINT)
+               addrconf_add_mroute(dev);
 }
 #endif
 
index 9f777ec59a59d24566d87643889a8c591dd52637..ed33abf57abd7d7ec71685a7180cf88ec132626c 100644 (file)
@@ -32,6 +32,7 @@ struct fib6_rule {
 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
                                   int flags, pol_lookup_t lookup)
 {
+       struct rt6_info *rt;
        struct fib_lookup_arg arg = {
                .lookup_ptr = lookup,
                .flags = FIB_LOOKUP_NOREF,
@@ -40,11 +41,21 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
        fib_rules_lookup(net->ipv6.fib6_rules_ops,
                         flowi6_to_flowi(fl6), flags, &arg);
 
-       if (arg.result)
-               return arg.result;
+       rt = arg.result;
 
-       dst_hold(&net->ipv6.ip6_null_entry->dst);
-       return &net->ipv6.ip6_null_entry->dst;
+       if (!rt) {
+               dst_hold(&net->ipv6.ip6_null_entry->dst);
+               return &net->ipv6.ip6_null_entry->dst;
+       }
+
+       if (rt->rt6i_flags & RTF_REJECT &&
+           rt->dst.error == -EAGAIN) {
+               ip6_rt_put(rt);
+               rt = net->ipv6.ip6_null_entry;
+               dst_hold(&rt->dst);
+       }
+
+       return &rt->dst;
 }
 
 static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
index 7d2e0023c72dbe2e466b35ffb1c6f0c0446af6da..6cedc62b2abb1c3520647b4046c1f027ffe1295b 100644 (file)
@@ -285,7 +285,17 @@ struct fib6_table *fib6_get_table(struct net *net, u32 id)
 struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
                                   int flags, pol_lookup_t lookup)
 {
-       return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
+       struct rt6_info *rt;
+
+       rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
+       if (rt->rt6i_flags & RTF_REJECT &&
+           rt->dst.error == -EAGAIN) {
+               ip6_rt_put(rt);
+               rt = net->ipv6.ip6_null_entry;
+               dst_hold(&rt->dst);
+       }
+
+       return &rt->dst;
 }
 
 static void __net_init fib6_tables_init(struct net *net)
index 92b1aa38f121507b662e2c964423952bf995b81e..f84ec4e9b2de7653d1ad8b2348977418827676c2 100644 (file)
@@ -376,6 +376,9 @@ int ip6_forward(struct sk_buff *skb)
        if (skb->pkt_type != PACKET_HOST)
                goto drop;
 
+       if (unlikely(skb->sk))
+               goto drop;
+
        if (skb_warn_if_lro(skb))
                goto drop;
 
@@ -581,6 +584,8 @@ int ip6_fragment(struct sock *sk, struct sk_buff *skb,
                if (np->frag_size)
                        mtu = np->frag_size;
        }
+       if (mtu < hlen + sizeof(struct frag_hdr) + 8)
+               goto fail_toobig;
        mtu -= hlen + sizeof(struct frag_hdr);
 
        frag_id = ipv6_select_ident(net, &ipv6_hdr(skb)->daddr,
@@ -874,7 +879,8 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
 #ifdef CONFIG_IPV6_SUBTREES
            ip6_rt_check(&rt->rt6i_src, &fl6->saddr, np->saddr_cache) ||
 #endif
-           (fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex)) {
+          (!(fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF) &&
+             (fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex))) {
                dst_release(dst);
                dst = NULL;
        }
index 96833e4b31939a191eaf7de297ac438d4aa41fa4..f6a024e141e595541009cb24c172e0c52a8a879f 100644 (file)
@@ -58,6 +58,7 @@ endif # NF_TABLES
 
 config NF_DUP_IPV6
        tristate "Netfilter IPv6 packet duplication to alternate destination"
+       depends on !NF_CONNTRACK || NF_CONNTRACK
        help
          This option enables the nf_dup_ipv6 core, which duplicates an IPv6
          packet to be rerouted to another destination.
index 701cd2bae0a9224d56005f67d8b9f5e71f45825f..c7196ad1d69f8467a6971cf40f1c5ffdd14b4a92 100644 (file)
@@ -646,6 +646,7 @@ void nf_ct_frag6_consume_orig(struct sk_buff *skb)
                s = s2;
        }
 }
+EXPORT_SYMBOL_GPL(nf_ct_frag6_consume_orig);
 
 static int nf_ct_net_init(struct net *net)
 {
index cb32ce250db0c0fd8cdc19a066f3956a893f2fba..946880ad48acda725eb66f9e2d0a8fd0f2b4ec40 100644 (file)
@@ -142,6 +142,9 @@ static void rt6_uncached_list_flush_dev(struct net *net, struct net_device *dev)
        struct net_device *loopback_dev = net->loopback_dev;
        int cpu;
 
+       if (dev == loopback_dev)
+               return;
+
        for_each_possible_cpu(cpu) {
                struct uncached_list *ul = per_cpu_ptr(&rt6_uncached_list, cpu);
                struct rt6_info *rt;
@@ -151,14 +154,12 @@ static void rt6_uncached_list_flush_dev(struct net *net, struct net_device *dev)
                        struct inet6_dev *rt_idev = rt->rt6i_idev;
                        struct net_device *rt_dev = rt->dst.dev;
 
-                       if (rt_idev && (rt_idev->dev == dev || !dev) &&
-                           rt_idev->dev != loopback_dev) {
+                       if (rt_idev->dev == dev) {
                                rt->rt6i_idev = in6_dev_get(loopback_dev);
                                in6_dev_put(rt_idev);
                        }
 
-                       if (rt_dev && (rt_dev == dev || !dev) &&
-                           rt_dev != loopback_dev) {
+                       if (rt_dev == dev) {
                                rt->dst.dev = loopback_dev;
                                dev_hold(rt->dst.dev);
                                dev_put(rt_dev);
@@ -247,12 +248,6 @@ static void ip6_rt_blackhole_redirect(struct dst_entry *dst, struct sock *sk,
 {
 }
 
-static u32 *ip6_rt_blackhole_cow_metrics(struct dst_entry *dst,
-                                        unsigned long old)
-{
-       return NULL;
-}
-
 static struct dst_ops ip6_dst_blackhole_ops = {
        .family                 =       AF_INET6,
        .destroy                =       ip6_dst_destroy,
@@ -261,7 +256,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
        .default_advmss         =       ip6_default_advmss,
        .update_pmtu            =       ip6_rt_blackhole_update_pmtu,
        .redirect               =       ip6_rt_blackhole_redirect,
-       .cow_metrics            =       ip6_rt_blackhole_cow_metrics,
+       .cow_metrics            =       dst_cow_metrics_generic,
        .neigh_lookup           =       ip6_neigh_lookup,
 };
 
@@ -318,6 +313,15 @@ static const struct rt6_info ip6_blk_hole_entry_template = {
 
 #endif
 
+static void rt6_info_init(struct rt6_info *rt)
+{
+       struct dst_entry *dst = &rt->dst;
+
+       memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
+       INIT_LIST_HEAD(&rt->rt6i_siblings);
+       INIT_LIST_HEAD(&rt->rt6i_uncached);
+}
+
 /* allocate dst with ip6_dst_ops */
 static struct rt6_info *__ip6_dst_alloc(struct net *net,
                                        struct net_device *dev,
@@ -326,13 +330,9 @@ static struct rt6_info *__ip6_dst_alloc(struct net *net,
        struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
                                        0, DST_OBSOLETE_FORCE_CHK, flags);
 
-       if (rt) {
-               struct dst_entry *dst = &rt->dst;
+       if (rt)
+               rt6_info_init(rt);
 
-               memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
-               INIT_LIST_HEAD(&rt->rt6i_siblings);
-               INIT_LIST_HEAD(&rt->rt6i_uncached);
-       }
        return rt;
 }
 
@@ -1068,6 +1068,9 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
        fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
        saved_fn = fn;
 
+       if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
+               oif = 0;
+
 redo_rt6_select:
        rt = rt6_select(fn, oif, strict);
        if (rt->rt6i_nsiblings)
@@ -1190,14 +1193,16 @@ struct dst_entry *ip6_route_output(struct net *net, const struct sock *sk,
                                    struct flowi6 *fl6)
 {
        int flags = 0;
+       bool any_src;
 
        fl6->flowi6_iif = LOOPBACK_IFINDEX;
 
+       any_src = ipv6_addr_any(&fl6->saddr);
        if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr) ||
-           fl6->flowi6_oif)
+           (fl6->flowi6_oif && any_src))
                flags |= RT6_LOOKUP_F_IFACE;
 
-       if (!ipv6_addr_any(&fl6->saddr))
+       if (!any_src)
                flags |= RT6_LOOKUP_F_HAS_SADDR;
        else if (sk)
                flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs);
@@ -1213,24 +1218,20 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori
 
        rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, DST_OBSOLETE_NONE, 0);
        if (rt) {
-               new = &rt->dst;
-
-               memset(new + 1, 0, sizeof(*rt) - sizeof(*new));
+               rt6_info_init(rt);
 
+               new = &rt->dst;
                new->__use = 1;
                new->input = dst_discard;
                new->output = dst_discard_sk;
 
-               if (dst_metrics_read_only(&ort->dst))
-                       new->_metrics = ort->dst._metrics;
-               else
-                       dst_copy_metrics(new, &ort->dst);
+               dst_copy_metrics(new, &ort->dst);
                rt->rt6i_idev = ort->rt6i_idev;
                if (rt->rt6i_idev)
                        in6_dev_hold(rt->rt6i_idev);
 
                rt->rt6i_gateway = ort->rt6i_gateway;
-               rt->rt6i_flags = ort->rt6i_flags;
+               rt->rt6i_flags = ort->rt6i_flags & ~RTF_PCPU;
                rt->rt6i_metric = 0;
 
                memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
@@ -2622,7 +2623,8 @@ void rt6_ifdown(struct net *net, struct net_device *dev)
 
        fib6_clean_all(net, fib6_ifdown, &adn);
        icmp6_clean_all(fib6_ifdown, &adn);
-       rt6_uncached_list_flush_dev(net, dev);
+       if (dev)
+               rt6_uncached_list_flush_dev(net, dev);
 }
 
 struct rt6_mtu_change_arg {
index 09c76a7b474dbcb12cae8aeba6fcba375d0d329a..e15feb7b413dd1a93a376f2ab6aabcbc3c3bb944 100644 (file)
@@ -79,6 +79,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
 
        if (!skb->ignore_df && skb->len > mtu) {
                skb->dev = dst->dev;
+               skb->protocol = htons(ETH_P_IPV6);
 
                if (xfrm6_local_dontfrag(skb))
                        xfrm6_local_rxpmtu(skb, mtu);
@@ -136,6 +137,7 @@ static int __xfrm6_output(struct sock *sk, struct sk_buff *skb)
        struct dst_entry *dst = skb_dst(skb);
        struct xfrm_state *x = dst->xfrm;
        int mtu;
+       bool toobig;
 
 #ifdef CONFIG_NETFILTER
        if (!x) {
@@ -144,25 +146,29 @@ static int __xfrm6_output(struct sock *sk, struct sk_buff *skb)
        }
 #endif
 
+       if (x->props.mode != XFRM_MODE_TUNNEL)
+               goto skip_frag;
+
        if (skb->protocol == htons(ETH_P_IPV6))
                mtu = ip6_skb_dst_mtu(skb);
        else
                mtu = dst_mtu(skb_dst(skb));
 
-       if (skb->len > mtu && xfrm6_local_dontfrag(skb)) {
+       toobig = skb->len > mtu && !skb_is_gso(skb);
+
+       if (toobig && xfrm6_local_dontfrag(skb)) {
                xfrm6_local_rxpmtu(skb, mtu);
                return -EMSGSIZE;
-       } else if (!skb->ignore_df && skb->len > mtu && skb->sk) {
+       } else if (!skb->ignore_df && toobig && skb->sk) {
                xfrm_local_error(skb, mtu);
                return -EMSGSIZE;
        }
 
-       if (x->props.mode == XFRM_MODE_TUNNEL &&
-           ((skb->len > mtu && !skb_is_gso(skb)) ||
-               dst_allfrag(skb_dst(skb)))) {
+       if (toobig || dst_allfrag(skb_dst(skb)))
                return ip6_fragment(sk, skb,
                                    x->outer_mode->afinfo->output_finish);
-       }
+
+skip_frag:
        return x->outer_mode->afinfo->output_finish(sk, skb);
 }
 
index 30caa289c5dbf589270768ce90d15f2990341231..da55e0c85bb8edca213eae4686c46073e2af1650 100644 (file)
@@ -37,6 +37,7 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
 
        memset(&fl6, 0, sizeof(fl6));
        fl6.flowi6_oif = oif;
+       fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
        memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
        if (saddr)
                memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));
@@ -178,7 +179,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
                        return;
 
                case IPPROTO_ICMPV6:
-                       if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) {
+                       if (!onlyproto && (nh + offset + 2 < skb->data ||
+                           pskb_may_pull(skb, nh + offset + 2 - skb->data))) {
                                u8 *icmp;
 
                                nh = skb_network_header(skb);
@@ -192,7 +194,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
 #if IS_ENABLED(CONFIG_IPV6_MIP6)
                case IPPROTO_MH:
                        offset += ipv6_optlen(exthdr);
-                       if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
+                       if (!onlyproto && (nh + offset + 3 < skb->data ||
+                           pskb_may_pull(skb, nh + offset + 3 - skb->data))) {
                                struct ip6_mh *mh;
 
                                nh = skb_network_header(skb);
index a26c401ef4a4431b2957d5b46c05c0c2a35c90bd..43964594aa12d9864c00a3b778d77060084e6a14 100644 (file)
@@ -1839,7 +1839,7 @@ static void *irlmp_seq_hb_idx(struct irlmp_iter_state *iter, loff_t *off)
        for (element = hashbin_get_first(iter->hashbin);
             element != NULL;
             element = hashbin_get_next(iter->hashbin)) {
-               if (!off || *off-- == 0) {
+               if (!off || (*off)-- == 0) {
                        /* NB: hashbin left locked */
                        return element;
                }
index 83a70688784b8449603e13f32ec26ff6fce06639..f9c9ecb0cdd3b3eea618538fda2e884583f9bc09 100644 (file)
@@ -261,7 +261,7 @@ static int pfkey_broadcast(struct sk_buff *skb,
 
                err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
 
-               /* Error is cleare after succecful sending to at least one
+               /* Error is cleared after successful sending to at least one
                 * registered KM */
                if ((broadcast_flags & BROADCAST_REGISTERED) && err)
                        err = err2;
index ced6bf3be8d6cf5d3d9fc80b6c46f48c4e567aef..1560c8482bcb9fd587d1e278a499f99fd9958803 100644 (file)
@@ -149,7 +149,7 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
 
        for (i = 0; i < NUM_IEEE80211_HW_FLAGS; i++) {
                if (test_bit(i, local->hw.flags))
-                       pos += scnprintf(pos, end - pos, "%s",
+                       pos += scnprintf(pos, end - pos, "%s\n",
                                         hw_flag_names[i]);
        }
 
index 8ba5832435095f10e94f782e07d92a4f742cad3a..3ed7ddfbf8e840d4c910b0e9452c06843031c91d 100644 (file)
@@ -101,6 +101,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
         * when it wakes up for the next time.
         */
        set_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT);
+       ieee80211_clear_fast_xmit(sta);
 
        /*
         * This code races in the following way:
index 84e0e8c7fb236952dfc1cfcb23204623e80d7867..7892eb8ed4c8b1fa416ebcb297fab9f1cce91743 100644 (file)
@@ -1218,8 +1218,10 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
 
        if (!tx->sta)
                info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
-       else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT))
+       else if (test_and_clear_sta_flag(tx->sta, WLAN_STA_CLEAR_PS_FILT)) {
                info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
+               ieee80211_check_fast_xmit(tx->sta);
+       }
 
        info->flags |= IEEE80211_TX_CTL_FIRST_FRAGMENT;
 
@@ -2451,7 +2453,8 @@ void ieee80211_check_fast_xmit(struct sta_info *sta)
 
        if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
            test_sta_flag(sta, WLAN_STA_PS_DRIVER) ||
-           test_sta_flag(sta, WLAN_STA_PS_DELIVER))
+           test_sta_flag(sta, WLAN_STA_PS_DELIVER) ||
+           test_sta_flag(sta, WLAN_STA_CLEAR_PS_FILT))
                goto out;
 
        if (sdata->noack_map)
index 8e47f8113495739082572d269797e00160251751..21a085686dc1b543439f33e448531bc64a273684 100644 (file)
@@ -152,6 +152,8 @@ void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg)
 #endif
        synchronize_net();
        nf_queue_nf_hook_drop(net, &entry->ops);
+       /* other cpu might still process nfqueue verdict that used reg */
+       synchronize_net();
        kfree(entry);
 }
 EXPORT_SYMBOL(nf_unregister_net_hook);
index a1fe5377a2b3376d29f29b18d77ebfe08fc988e1..5a30ce6e8c90d278ac37cb0115f45a4390f9a6d7 100644 (file)
@@ -297,7 +297,7 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
              ip_set_timeout_expired(ext_timeout(n, set))))
                n =  NULL;
 
-       e = kzalloc(set->dsize, GFP_KERNEL);
+       e = kzalloc(set->dsize, GFP_ATOMIC);
        if (!e)
                return -ENOMEM;
        e->id = d->id;
index 8f060d7f9a0e107a410d3ffe71722f49059f7bc8..fafe33bdb61989e680dc4b26dbe99dcc1d4064b5 100644 (file)
@@ -2371,7 +2371,7 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
                int pos, idx, shift;
 
                err = 0;
-               netlink_table_grab();
+               netlink_lock_table();
                for (pos = 0; pos * 8 < nlk->ngroups; pos += sizeof(u32)) {
                        if (len - pos < sizeof(u32))
                                break;
@@ -2386,7 +2386,7 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
                }
                if (put_user(ALIGN(nlk->ngroups / 8, sizeof(u32)), optlen))
                        err = -EFAULT;
-               netlink_table_ungrab();
+               netlink_unlock_table();
                break;
        }
        case NETLINK_CAP_ACK:
@@ -2785,6 +2785,7 @@ static int netlink_dump(struct sock *sk)
        struct sk_buff *skb = NULL;
        struct nlmsghdr *nlh;
        int len, err = -ENOBUFS;
+       int alloc_min_size;
        int alloc_size;
 
        mutex_lock(nlk->cb_mutex);
@@ -2793,9 +2794,6 @@ static int netlink_dump(struct sock *sk)
                goto errout_skb;
        }
 
-       cb = &nlk->cb;
-       alloc_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
-
        if (!netlink_rx_is_mmaped(sk) &&
            atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
                goto errout_skb;
@@ -2805,23 +2803,35 @@ static int netlink_dump(struct sock *sk)
         * to reduce number of system calls on dump operations, if user
         * ever provided a big enough buffer.
         */
-       if (alloc_size < nlk->max_recvmsg_len) {
-               skb = netlink_alloc_skb(sk,
-                                       nlk->max_recvmsg_len,
-                                       nlk->portid,
+       cb = &nlk->cb;
+       alloc_min_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE);
+
+       if (alloc_min_size < nlk->max_recvmsg_len) {
+               alloc_size = nlk->max_recvmsg_len;
+               skb = netlink_alloc_skb(sk, alloc_size, nlk->portid,
                                        GFP_KERNEL |
                                        __GFP_NOWARN |
                                        __GFP_NORETRY);
-               /* available room should be exact amount to avoid MSG_TRUNC */
-               if (skb)
-                       skb_reserve(skb, skb_tailroom(skb) -
-                                        nlk->max_recvmsg_len);
        }
-       if (!skb)
+       if (!skb) {
+               alloc_size = alloc_min_size;
                skb = netlink_alloc_skb(sk, alloc_size, nlk->portid,
                                        GFP_KERNEL);
+       }
        if (!skb)
                goto errout_skb;
+
+       /* Trim skb to allocated size. User is expected to provide buffer as
+        * large as max(min_dump_alloc, 16KiB (mac_recvmsg_len capped at
+        * netlink_recvmsg())). dump will pack as many smaller messages as
+        * could fit within the allocated skb. skb is typically allocated
+        * with larger space than required (could be as much as near 2x the
+        * requested size with align to next power of 2 approach). Allowing
+        * dump to use the excess space makes it difficult for a user to have a
+        * reasonable static buffer based on the expected largest dump of a
+        * single netdev. The outcome is MSG_TRUNC error.
+        */
+       skb_reserve(skb, skb_tailroom(skb) - alloc_size);
        netlink_skb_set_owner_r(skb, sk);
 
        len = cb->dump(skb, cb);
index 315f5330b6e5400eaf28ce7d0290038b7113a6fd..dba635d086b2f165940ce1dea67c92c48392e4cb 100644 (file)
@@ -684,7 +684,7 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
 {
        if (skb_network_offset(skb) > MAX_L2_LEN) {
                OVS_NLERR(1, "L2 header too long to fragment");
-               return;
+               goto err;
        }
 
        if (ethertype == htons(ETH_P_IP)) {
@@ -708,8 +708,7 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
                struct rt6_info ovs_rt;
 
                if (!v6ops) {
-                       kfree_skb(skb);
-                       return;
+                       goto err;
                }
 
                prepare_frag(vport, skb);
@@ -728,8 +727,12 @@ static void ovs_fragment(struct vport *vport, struct sk_buff *skb, u16 mru,
                WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
                          ovs_vport_name(vport), ntohs(ethertype), mru,
                          vport->dev->mtu);
-               kfree_skb(skb);
+               goto err;
        }
+
+       return;
+err:
+       kfree_skb(skb);
 }
 
 static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
@@ -765,7 +768,6 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
                            struct sw_flow_key *key, const struct nlattr *attr,
                            const struct nlattr *actions, int actions_len)
 {
-       struct ip_tunnel_info info;
        struct dp_upcall_info upcall;
        const struct nlattr *a;
        int rem;
@@ -793,11 +795,9 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
                        if (vport) {
                                int err;
 
-                               upcall.egress_tun_info = &info;
-                               err = ovs_vport_get_egress_tun_info(vport, skb,
-                                                                   &upcall);
-                               if (err)
-                                       upcall.egress_tun_info = NULL;
+                               err = dev_fill_metadata_dst(vport->dev, skb);
+                               if (!err)
+                                       upcall.egress_tun_info = skb_tunnel_info(skb);
                        }
 
                        break;
@@ -968,7 +968,7 @@ static int execute_masked_set_action(struct sk_buff *skb,
        case OVS_KEY_ATTR_CT_STATE:
        case OVS_KEY_ATTR_CT_ZONE:
        case OVS_KEY_ATTR_CT_MARK:
-       case OVS_KEY_ATTR_CT_LABEL:
+       case OVS_KEY_ATTR_CT_LABELS:
                err = -EINVAL;
                break;
        }
@@ -1099,12 +1099,18 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
                        break;
 
                case OVS_ACTION_ATTR_CT:
+                       if (!is_flow_key_valid(key)) {
+                               err = ovs_flow_key_update(skb, key);
+                               if (err)
+                                       return err;
+                       }
+
                        err = ovs_ct_execute(ovs_dp_get_net(dp), skb, key,
                                             nla_data(a));
 
                        /* Hide stolen IP fragments from user space. */
-                       if (err == -EINPROGRESS)
-                               return 0;
+                       if (err)
+                               return err == -EINPROGRESS ? 0 : err;
                        break;
                }
 
index 002a755fa07ea8c6c71c762716a5be8700c0a36c..50095820edb7b2f8adc1ba1699543c2b28e378b0 100644 (file)
@@ -37,9 +37,9 @@ struct md_mark {
 };
 
 /* Metadata label for masked write to conntrack label. */
-struct md_label {
-       struct ovs_key_ct_label value;
-       struct ovs_key_ct_label mask;
+struct md_labels {
+       struct ovs_key_ct_labels value;
+       struct ovs_key_ct_labels mask;
 };
 
 /* Conntrack action context for execution. */
@@ -47,10 +47,10 @@ struct ovs_conntrack_info {
        struct nf_conntrack_helper *helper;
        struct nf_conntrack_zone zone;
        struct nf_conn *ct;
-       u32 flags;
+       u8 commit : 1;
        u16 family;
        struct md_mark mark;
-       struct md_label label;
+       struct md_labels labels;
 };
 
 static u16 key_to_nfproto(const struct sw_flow_key *key)
@@ -109,21 +109,21 @@ static u32 ovs_ct_get_mark(const struct nf_conn *ct)
 #endif
 }
 
-static void ovs_ct_get_label(const struct nf_conn *ct,
-                            struct ovs_key_ct_label *label)
+static void ovs_ct_get_labels(const struct nf_conn *ct,
+                             struct ovs_key_ct_labels *labels)
 {
        struct nf_conn_labels *cl = ct ? nf_ct_labels_find(ct) : NULL;
 
        if (cl) {
                size_t len = cl->words * sizeof(long);
 
-               if (len > OVS_CT_LABEL_LEN)
-                       len = OVS_CT_LABEL_LEN;
-               else if (len < OVS_CT_LABEL_LEN)
-                       memset(label, 0, OVS_CT_LABEL_LEN);
-               memcpy(label, cl->bits, len);
+               if (len > OVS_CT_LABELS_LEN)
+                       len = OVS_CT_LABELS_LEN;
+               else if (len < OVS_CT_LABELS_LEN)
+                       memset(labels, 0, OVS_CT_LABELS_LEN);
+               memcpy(labels, cl->bits, len);
        } else {
-               memset(label, 0, OVS_CT_LABEL_LEN);
+               memset(labels, 0, OVS_CT_LABELS_LEN);
        }
 }
 
@@ -134,7 +134,7 @@ static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
        key->ct.state = state;
        key->ct.zone = zone->id;
        key->ct.mark = ovs_ct_get_mark(ct);
-       ovs_ct_get_label(ct, &key->ct.label);
+       ovs_ct_get_labels(ct, &key->ct.labels);
 }
 
 /* Update 'key' based on skb->nfct. If 'post_ct' is true, then OVS has
@@ -151,6 +151,8 @@ static void ovs_ct_update_key(const struct sk_buff *skb,
        ct = nf_ct_get(skb, &ctinfo);
        if (ct) {
                state = ovs_ct_get_state(ctinfo);
+               if (!nf_ct_is_confirmed(ct))
+                       state |= OVS_CS_F_NEW;
                if (ct->master)
                        state |= OVS_CS_F_RELATED;
                zone = nf_ct_zone(ct);
@@ -167,7 +169,7 @@ void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
 
 int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
 {
-       if (nla_put_u8(skb, OVS_KEY_ATTR_CT_STATE, key->ct.state))
+       if (nla_put_u32(skb, OVS_KEY_ATTR_CT_STATE, key->ct.state))
                return -EMSGSIZE;
 
        if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
@@ -179,8 +181,8 @@ int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
                return -EMSGSIZE;
 
        if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
-           nla_put(skb, OVS_KEY_ATTR_CT_LABEL, sizeof(key->ct.label),
-                   &key->ct.label))
+           nla_put(skb, OVS_KEY_ATTR_CT_LABELS, sizeof(key->ct.labels),
+                   &key->ct.labels))
                return -EMSGSIZE;
 
        return 0;
@@ -213,18 +215,15 @@ static int ovs_ct_set_mark(struct sk_buff *skb, struct sw_flow_key *key,
 #endif
 }
 
-static int ovs_ct_set_label(struct sk_buff *skb, struct sw_flow_key *key,
-                           const struct ovs_key_ct_label *label,
-                           const struct ovs_key_ct_label *mask)
+static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key,
+                            const struct ovs_key_ct_labels *labels,
+                            const struct ovs_key_ct_labels *mask)
 {
        enum ip_conntrack_info ctinfo;
        struct nf_conn_labels *cl;
        struct nf_conn *ct;
        int err;
 
-       if (!IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS))
-               return -ENOTSUPP;
-
        /* The connection could be invalid, in which case set_label is no-op.*/
        ct = nf_ct_get(skb, &ctinfo);
        if (!ct)
@@ -235,15 +234,15 @@ static int ovs_ct_set_label(struct sk_buff *skb, struct sw_flow_key *key,
                nf_ct_labels_ext_add(ct);
                cl = nf_ct_labels_find(ct);
        }
-       if (!cl || cl->words * sizeof(long) < OVS_CT_LABEL_LEN)
+       if (!cl || cl->words * sizeof(long) < OVS_CT_LABELS_LEN)
                return -ENOSPC;
 
-       err = nf_connlabels_replace(ct, (u32 *)label, (u32 *)mask,
-                                   OVS_CT_LABEL_LEN / sizeof(u32));
+       err = nf_connlabels_replace(ct, (u32 *)labels, (u32 *)mask,
+                                   OVS_CT_LABELS_LEN / sizeof(u32));
        if (err)
                return err;
 
-       ovs_ct_get_label(ct, &key->ct.label);
+       ovs_ct_get_labels(ct, &key->ct.labels);
        return 0;
 }
 
@@ -294,6 +293,9 @@ static int ovs_ct_helper(struct sk_buff *skb, u16 proto)
        return helper->help(skb, protoff, ct, ctinfo);
 }
 
+/* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
+ * value if 'skb' is freed.
+ */
 static int handle_fragments(struct net *net, struct sw_flow_key *key,
                            u16 zone, struct sk_buff *skb)
 {
@@ -309,8 +311,8 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
                        return err;
 
                ovs_cb.mru = IPCB(skb)->frag_max_size;
-       } else if (key->eth.type == htons(ETH_P_IPV6)) {
 #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
+       } else if (key->eth.type == htons(ETH_P_IPV6)) {
                enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone;
                struct sk_buff *reasm;
 
@@ -319,17 +321,25 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
                if (!reasm)
                        return -EINPROGRESS;
 
-               if (skb == reasm)
+               if (skb == reasm) {
+                       kfree_skb(skb);
                        return -EINVAL;
+               }
+
+               /* Don't free 'skb' even though it is one of the original
+                * fragments, as we're going to morph it into the head.
+                */
+               skb_get(skb);
+               nf_ct_frag6_consume_orig(reasm);
 
                key->ip.proto = ipv6_hdr(reasm)->nexthdr;
                skb_morph(skb, reasm);
+               skb->next = reasm->next;
                consume_skb(reasm);
                ovs_cb.mru = IP6CB(skb)->frag_max_size;
-#else
-               return -EPFNOSUPPORT;
 #endif
        } else {
+               kfree_skb(skb);
                return -EPFNOSUPPORT;
        }
 
@@ -377,7 +387,7 @@ static bool skb_nfct_cached(const struct net *net, const struct sk_buff *skb,
        return true;
 }
 
-static int __ovs_ct_lookup(struct net *net, const struct sw_flow_key *key,
+static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
                           const struct ovs_conntrack_info *info,
                           struct sk_buff *skb)
 {
@@ -408,6 +418,8 @@ static int __ovs_ct_lookup(struct net *net, const struct sw_flow_key *key,
                }
        }
 
+       ovs_ct_update_key(skb, key, true);
+
        return 0;
 }
 
@@ -430,8 +442,6 @@ static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
                err = __ovs_ct_lookup(net, key, info, skb);
                if (err)
                        return err;
-
-               ovs_ct_update_key(skb, key, true);
        }
 
        return 0;
@@ -460,22 +470,23 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
        if (nf_conntrack_confirm(skb) != NF_ACCEPT)
                return -EINVAL;
 
-       ovs_ct_update_key(skb, key, true);
-
        return 0;
 }
 
-static bool label_nonzero(const struct ovs_key_ct_label *label)
+static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
 {
        size_t i;
 
-       for (i = 0; i < sizeof(*label); i++)
-               if (label->ct_label[i])
+       for (i = 0; i < sizeof(*labels); i++)
+               if (labels->ct_labels[i])
                        return true;
 
        return false;
 }
 
+/* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
+ * value if 'skb' is freed.
+ */
 int ovs_ct_execute(struct net *net, struct sk_buff *skb,
                   struct sw_flow_key *key,
                   const struct ovs_conntrack_info *info)
@@ -493,7 +504,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
                        return err;
        }
 
-       if (info->flags & OVS_CT_F_COMMIT)
+       if (info->commit)
                err = ovs_ct_commit(net, key, info, skb);
        else
                err = ovs_ct_lookup(net, key, info, skb);
@@ -506,11 +517,13 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
                if (err)
                        goto err;
        }
-       if (label_nonzero(&info->label.mask))
-               err = ovs_ct_set_label(skb, key, &info->label.value,
-                                      &info->label.mask);
+       if (labels_nonzero(&info->labels.mask))
+               err = ovs_ct_set_labels(skb, key, &info->labels.value,
+                                       &info->labels.mask);
 err:
        skb_push(skb, nh_ofs);
+       if (err)
+               kfree_skb(skb);
        return err;
 }
 
@@ -539,14 +552,13 @@ static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name,
 }
 
 static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = {
-       [OVS_CT_ATTR_FLAGS]     = { .minlen = sizeof(u32),
-                                   .maxlen = sizeof(u32) },
+       [OVS_CT_ATTR_COMMIT]    = { .minlen = 0, .maxlen = 0 },
        [OVS_CT_ATTR_ZONE]      = { .minlen = sizeof(u16),
                                    .maxlen = sizeof(u16) },
        [OVS_CT_ATTR_MARK]      = { .minlen = sizeof(struct md_mark),
                                    .maxlen = sizeof(struct md_mark) },
-       [OVS_CT_ATTR_LABEL]     = { .minlen = sizeof(struct md_label),
-                                   .maxlen = sizeof(struct md_label) },
+       [OVS_CT_ATTR_LABELS]    = { .minlen = sizeof(struct md_labels),
+                                   .maxlen = sizeof(struct md_labels) },
        [OVS_CT_ATTR_HELPER]    = { .minlen = 1,
                                    .maxlen = NF_CT_HELPER_NAME_LEN }
 };
@@ -576,8 +588,8 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
                }
 
                switch (type) {
-               case OVS_CT_ATTR_FLAGS:
-                       info->flags = nla_get_u32(a);
+               case OVS_CT_ATTR_COMMIT:
+                       info->commit = true;
                        break;
 #ifdef CONFIG_NF_CONNTRACK_ZONES
                case OVS_CT_ATTR_ZONE:
@@ -588,15 +600,23 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
                case OVS_CT_ATTR_MARK: {
                        struct md_mark *mark = nla_data(a);
 
+                       if (!mark->mask) {
+                               OVS_NLERR(log, "ct_mark mask cannot be 0");
+                               return -EINVAL;
+                       }
                        info->mark = *mark;
                        break;
                }
 #endif
 #ifdef CONFIG_NF_CONNTRACK_LABELS
-               case OVS_CT_ATTR_LABEL: {
-                       struct md_label *label = nla_data(a);
+               case OVS_CT_ATTR_LABELS: {
+                       struct md_labels *labels = nla_data(a);
 
-                       info->label = *label;
+                       if (!labels_nonzero(&labels->mask)) {
+                               OVS_NLERR(log, "ct_labels mask cannot be 0");
+                               return -EINVAL;
+                       }
+                       info->labels = *labels;
                        break;
                }
 #endif
@@ -633,7 +653,7 @@ bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr)
            attr == OVS_KEY_ATTR_CT_MARK)
                return true;
        if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
-           attr == OVS_KEY_ATTR_CT_LABEL) {
+           attr == OVS_KEY_ATTR_CT_LABELS) {
                struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
 
                return ovs_net->xt_label;
@@ -701,18 +721,19 @@ int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
        if (!start)
                return -EMSGSIZE;
 
-       if (nla_put_u32(skb, OVS_CT_ATTR_FLAGS, ct_info->flags))
+       if (ct_info->commit && nla_put_flag(skb, OVS_CT_ATTR_COMMIT))
                return -EMSGSIZE;
        if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
            nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id))
                return -EMSGSIZE;
-       if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
+       if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && ct_info->mark.mask &&
            nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark),
                    &ct_info->mark))
                return -EMSGSIZE;
        if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
-           nla_put(skb, OVS_CT_ATTR_LABEL, sizeof(ct_info->label),
-                   &ct_info->label))
+           labels_nonzero(&ct_info->labels.mask) &&
+           nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels),
+                   &ct_info->labels))
                return -EMSGSIZE;
        if (ct_info->helper) {
                if (nla_put_string(skb, OVS_CT_ATTR_HELPER,
@@ -737,7 +758,7 @@ void ovs_ct_free_action(const struct nlattr *a)
 
 void ovs_ct_init(struct net *net)
 {
-       unsigned int n_bits = sizeof(struct ovs_key_ct_label) * BITS_PER_BYTE;
+       unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
        struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
 
        if (nf_connlabels_get(net, n_bits)) {
index 43f5dd7a55774414aeb7aad8c0560db3e0596035..a7544f405c1626f6564075f4453832b311b1ac29 100644 (file)
@@ -34,6 +34,10 @@ int ovs_ct_execute(struct net *, struct sk_buff *, struct sw_flow_key *,
 void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key);
 int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb);
 void ovs_ct_free_action(const struct nlattr *a);
+
+#define CT_SUPPORTED_MASK (OVS_CS_F_NEW | OVS_CS_F_ESTABLISHED | \
+                          OVS_CS_F_RELATED | OVS_CS_F_REPLY_DIR | \
+                          OVS_CS_F_INVALID | OVS_CS_F_TRACKED)
 #else
 #include <linux/errno.h>
 
@@ -63,6 +67,7 @@ static inline int ovs_ct_execute(struct net *net, struct sk_buff *skb,
                                 struct sw_flow_key *key,
                                 const struct ovs_conntrack_info *info)
 {
+       kfree_skb(skb);
        return -ENOTSUPP;
 }
 
@@ -72,7 +77,7 @@ static inline void ovs_ct_fill_key(const struct sk_buff *skb,
        key->ct.state = 0;
        key->ct.zone = 0;
        key->ct.mark = 0;
-       memset(&key->ct.label, 0, sizeof(key->ct.label));
+       memset(&key->ct.labels, 0, sizeof(key->ct.labels));
 }
 
 static inline int ovs_ct_put_key(const struct sw_flow_key *key,
@@ -82,5 +87,7 @@ static inline int ovs_ct_put_key(const struct sw_flow_key *key,
 }
 
 static inline void ovs_ct_free_action(const struct nlattr *a) { }
+
+#define CT_SUPPORTED_MASK 0
 #endif /* CONFIG_NF_CONNTRACK */
 #endif /* ovs_conntrack.h */
index b816ff87152834065841ff41e96d2f0d9ee4e307..c5d08ee377304313e7e320133e46343adff5da95 100644 (file)
@@ -490,9 +490,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
 
        if (upcall_info->egress_tun_info) {
                nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY);
-               err = ovs_nla_put_egress_tunnel_key(user_skb,
-                                                   upcall_info->egress_tun_info,
-                                                   upcall_info->egress_tun_opts);
+               err = ovs_nla_put_tunnel_info(user_skb,
+                                             upcall_info->egress_tun_info);
                BUG_ON(err);
                nla_nest_end(user_skb, nla);
        }
index f88038a99f4442bb753b4fc0cb3cc6c05c2bc2fc..67bdecd9fdc1f2b0544c2081aa1a557b16e0063a 100644 (file)
@@ -117,7 +117,6 @@ struct ovs_skb_cb {
  */
 struct dp_upcall_info {
        struct ip_tunnel_info *egress_tun_info;
-       const void *egress_tun_opts;
        const struct nlattr *userdata;
        const struct nlattr *actions;
        int actions_len;
index fe527d2dd4b7ae9d6b31a7d9d92586d1cd276c26..8cfa15a08668804a2a74c0047662694f23acbb80 100644 (file)
@@ -116,7 +116,7 @@ struct sw_flow_key {
                u16 zone;
                u32 mark;
                u8 state;
-               struct ovs_key_ct_label label;
+               struct ovs_key_ct_labels labels;
        } ct;
 
 } __aligned(BITS_PER_LONG/8); /* Ensure that we can do comparisons as longs. */
index 5c030a4d73382f6123345f4a6b608ea1b1684ae0..38536c137c54d0d4ebcebcce613fefdb89799b5a 100644 (file)
@@ -291,10 +291,10 @@ size_t ovs_key_attr_size(void)
                + nla_total_size(4)   /* OVS_KEY_ATTR_SKB_MARK */
                + nla_total_size(4)   /* OVS_KEY_ATTR_DP_HASH */
                + nla_total_size(4)   /* OVS_KEY_ATTR_RECIRC_ID */
-               + nla_total_size(1)   /* OVS_KEY_ATTR_CT_STATE */
+               + nla_total_size(4)   /* OVS_KEY_ATTR_CT_STATE */
                + nla_total_size(2)   /* OVS_KEY_ATTR_CT_ZONE */
                + nla_total_size(4)   /* OVS_KEY_ATTR_CT_MARK */
-               + nla_total_size(16)  /* OVS_KEY_ATTR_CT_LABEL */
+               + nla_total_size(16)  /* OVS_KEY_ATTR_CT_LABELS */
                + nla_total_size(12)  /* OVS_KEY_ATTR_ETHERNET */
                + nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */
                + nla_total_size(4)   /* OVS_KEY_ATTR_VLAN */
@@ -349,10 +349,10 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
        [OVS_KEY_ATTR_TUNNEL]    = { .len = OVS_ATTR_NESTED,
                                     .next = ovs_tunnel_key_lens, },
        [OVS_KEY_ATTR_MPLS]      = { .len = sizeof(struct ovs_key_mpls) },
-       [OVS_KEY_ATTR_CT_STATE]  = { .len = sizeof(u8) },
+       [OVS_KEY_ATTR_CT_STATE]  = { .len = sizeof(u32) },
        [OVS_KEY_ATTR_CT_ZONE]   = { .len = sizeof(u16) },
        [OVS_KEY_ATTR_CT_MARK]   = { .len = sizeof(u32) },
-       [OVS_KEY_ATTR_CT_LABEL]  = { .len = sizeof(struct ovs_key_ct_label) },
+       [OVS_KEY_ATTR_CT_LABELS] = { .len = sizeof(struct ovs_key_ct_labels) },
 };
 
 static bool check_attr_len(unsigned int attr_len, unsigned int expected_len)
@@ -717,7 +717,7 @@ static int __ipv4_tun_to_nlattr(struct sk_buff *skb,
        if ((output->tun_flags & TUNNEL_OAM) &&
            nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM))
                return -EMSGSIZE;
-       if (tun_opts) {
+       if (swkey_tun_opts_len) {
                if (output->tun_flags & TUNNEL_GENEVE_OPT &&
                    nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
                            swkey_tun_opts_len, tun_opts))
@@ -749,13 +749,12 @@ static int ipv4_tun_to_nlattr(struct sk_buff *skb,
        return 0;
 }
 
-int ovs_nla_put_egress_tunnel_key(struct sk_buff *skb,
-                                 const struct ip_tunnel_info *egress_tun_info,
-                                 const void *egress_tun_opts)
+int ovs_nla_put_tunnel_info(struct sk_buff *skb,
+                           struct ip_tunnel_info *tun_info)
 {
-       return __ipv4_tun_to_nlattr(skb, &egress_tun_info->key,
-                                   egress_tun_opts,
-                                   egress_tun_info->options_len);
+       return __ipv4_tun_to_nlattr(skb, &tun_info->key,
+                                   ip_tunnel_info_opts(tun_info),
+                                   tun_info->options_len);
 }
 
 static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
@@ -814,7 +813,13 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
 
        if (*attrs & (1 << OVS_KEY_ATTR_CT_STATE) &&
            ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) {
-               u8 ct_state = nla_get_u8(a[OVS_KEY_ATTR_CT_STATE]);
+               u32 ct_state = nla_get_u32(a[OVS_KEY_ATTR_CT_STATE]);
+
+               if (ct_state & ~CT_SUPPORTED_MASK) {
+                       OVS_NLERR(log, "ct_state flags %08x unsupported",
+                                 ct_state);
+                       return -EINVAL;
+               }
 
                SW_FLOW_KEY_PUT(match, ct.state, ct_state, is_mask);
                *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_STATE);
@@ -833,14 +838,14 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
                SW_FLOW_KEY_PUT(match, ct.mark, mark, is_mask);
                *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_MARK);
        }
-       if (*attrs & (1 << OVS_KEY_ATTR_CT_LABEL) &&
-           ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABEL)) {
-               const struct ovs_key_ct_label *cl;
+       if (*attrs & (1 << OVS_KEY_ATTR_CT_LABELS) &&
+           ovs_ct_verify(net, OVS_KEY_ATTR_CT_LABELS)) {
+               const struct ovs_key_ct_labels *cl;
 
-               cl = nla_data(a[OVS_KEY_ATTR_CT_LABEL]);
-               SW_FLOW_KEY_MEMCPY(match, ct.label, cl->ct_label,
+               cl = nla_data(a[OVS_KEY_ATTR_CT_LABELS]);
+               SW_FLOW_KEY_MEMCPY(match, ct.labels, cl->ct_labels,
                                   sizeof(*cl), is_mask);
-               *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABEL);
+               *attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
        }
        return 0;
 }
@@ -1093,6 +1098,9 @@ static void nlattr_set(struct nlattr *attr, u8 val,
                } else {
                        memset(nla_data(nla), val, nla_len(nla));
                }
+
+               if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE)
+                       *(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK;
        }
 }
 
@@ -1973,7 +1981,7 @@ static int validate_set(const struct nlattr *a,
        case OVS_KEY_ATTR_PRIORITY:
        case OVS_KEY_ATTR_SKB_MARK:
        case OVS_KEY_ATTR_CT_MARK:
-       case OVS_KEY_ATTR_CT_LABEL:
+       case OVS_KEY_ATTR_CT_LABELS:
        case OVS_KEY_ATTR_ETHERNET:
                break;
 
@@ -2374,10 +2382,7 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
                if (!start)
                        return -EMSGSIZE;
 
-               err = ipv4_tun_to_nlattr(skb, &tun_info->key,
-                                        tun_info->options_len ?
-                                            ip_tunnel_info_opts(tun_info) : NULL,
-                                        tun_info->options_len);
+               err = ovs_nla_put_tunnel_info(skb, tun_info);
                if (err)
                        return err;
                nla_nest_end(skb, start);
index 6ca3f0baf449f05f82dd92f9796cd8cfa7abf141..47dd142eca1c0856c74406e1d75682fc822861f6 100644 (file)
@@ -55,9 +55,9 @@ int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb);
 int ovs_nla_get_match(struct net *, struct sw_flow_match *,
                      const struct nlattr *key, const struct nlattr *mask,
                      bool log);
-int ovs_nla_put_egress_tunnel_key(struct sk_buff *,
-                                 const struct ip_tunnel_info *,
-                                 const void *egress_tun_opts);
+
+int ovs_nla_put_tunnel_info(struct sk_buff *skb,
+                           struct ip_tunnel_info *tun_info);
 
 bool ovs_nla_get_ufid(struct sw_flow_id *, const struct nlattr *, bool log);
 int ovs_nla_get_identifier(struct sw_flow_id *sfid, const struct nlattr *ufid,
index f2ea83ba47631d4f650aa3dcf2f9c66cf4fd1c6f..c7f74aab34b9ef7d2befcd571d44290b76fbfbc1 100644 (file)
@@ -93,7 +93,8 @@ struct sw_flow *ovs_flow_alloc(void)
 
        /* Initialize the default stat node. */
        stats = kmem_cache_alloc_node(flow_stats_cache,
-                                     GFP_KERNEL | __GFP_ZERO, 0);
+                                     GFP_KERNEL | __GFP_ZERO,
+                                     node_online(0) ? 0 : NUMA_NO_NODE);
        if (!stats)
                goto err;
 
index 2735e9c4a3b88586165ef5644e429cf28079974d..5f8aaaaa0785385b89096925718d96b3335c1d32 100644 (file)
@@ -52,18 +52,6 @@ static int geneve_get_options(const struct vport *vport,
        return 0;
 }
 
-static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                     struct dp_upcall_info *upcall)
-{
-       struct geneve_port *geneve_port = geneve_vport(vport);
-       struct net *net = ovs_dp_get_net(vport->dp);
-       __be16 dport = htons(geneve_port->port_no);
-       __be16 sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true);
-
-       return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp),
-                                         skb, IPPROTO_UDP, sport, dport);
-}
-
 static struct vport *geneve_tnl_create(const struct vport_parms *parms)
 {
        struct net *net = ovs_dp_get_net(parms->dp);
@@ -130,7 +118,6 @@ static struct vport_ops ovs_geneve_vport_ops = {
        .get_options    = geneve_get_options,
        .send           = ovs_netdev_send,
        .owner          = THIS_MODULE,
-       .get_egress_tun_info    = geneve_get_egress_tun_info,
 };
 
 static int __init ovs_geneve_tnl_init(void)
index 4d24481669c95197b06bb75d207b3e713b433508..64225bf5eb405f4082547bbc8f09d920de72cdb8 100644 (file)
@@ -84,18 +84,10 @@ static struct vport *gre_create(const struct vport_parms *parms)
        return ovs_netdev_link(vport, parms->name);
 }
 
-static int gre_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                  struct dp_upcall_info *upcall)
-{
-       return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp),
-                                         skb, IPPROTO_GRE, 0, 0);
-}
-
 static struct vport_ops ovs_gre_vport_ops = {
        .type           = OVS_VPORT_TYPE_GRE,
        .create         = gre_create,
        .send           = ovs_netdev_send,
-       .get_egress_tun_info    = gre_get_egress_tun_info,
        .destroy        = ovs_netdev_tunnel_destroy,
        .owner          = THIS_MODULE,
 };
index 388b8a6bf112979f7f7291c5bb17fd6c7027e594..b3934126daa894d7bdaf7511ece6ff5319cf2c8a 100644 (file)
@@ -106,12 +106,45 @@ static void internal_dev_destructor(struct net_device *dev)
        free_netdev(dev);
 }
 
+static struct rtnl_link_stats64 *
+internal_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
+{
+       int i;
+
+       memset(stats, 0, sizeof(*stats));
+       stats->rx_errors  = dev->stats.rx_errors;
+       stats->tx_errors  = dev->stats.tx_errors;
+       stats->tx_dropped = dev->stats.tx_dropped;
+       stats->rx_dropped = dev->stats.rx_dropped;
+
+       for_each_possible_cpu(i) {
+               const struct pcpu_sw_netstats *percpu_stats;
+               struct pcpu_sw_netstats local_stats;
+               unsigned int start;
+
+               percpu_stats = per_cpu_ptr(dev->tstats, i);
+
+               do {
+                       start = u64_stats_fetch_begin_irq(&percpu_stats->syncp);
+                       local_stats = *percpu_stats;
+               } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start));
+
+               stats->rx_bytes         += local_stats.rx_bytes;
+               stats->rx_packets       += local_stats.rx_packets;
+               stats->tx_bytes         += local_stats.tx_bytes;
+               stats->tx_packets       += local_stats.tx_packets;
+       }
+
+       return stats;
+}
+
 static const struct net_device_ops internal_dev_netdev_ops = {
        .ndo_open = internal_dev_open,
        .ndo_stop = internal_dev_stop,
        .ndo_start_xmit = internal_dev_xmit,
        .ndo_set_mac_address = eth_mac_addr,
        .ndo_change_mtu = internal_dev_change_mtu,
+       .ndo_get_stats64 = internal_get_stats,
 };
 
 static struct rtnl_link_ops internal_dev_link_ops __read_mostly = {
@@ -161,6 +194,11 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
                err = -ENOMEM;
                goto error_free_vport;
        }
+       vport->dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
+       if (!vport->dev->tstats) {
+               err = -ENOMEM;
+               goto error_free_netdev;
+       }
 
        dev_net_set(vport->dev, ovs_dp_get_net(vport->dp));
        internal_dev = internal_dev_priv(vport->dev);
@@ -173,7 +211,7 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
        rtnl_lock();
        err = register_netdevice(vport->dev);
        if (err)
-               goto error_free_netdev;
+               goto error_unlock;
 
        dev_set_promiscuity(vport->dev, 1);
        rtnl_unlock();
@@ -181,8 +219,10 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
 
        return vport;
 
-error_free_netdev:
+error_unlock:
        rtnl_unlock();
+       free_percpu(vport->dev->tstats);
+error_free_netdev:
        free_netdev(vport->dev);
 error_free_vport:
        ovs_vport_free(vport);
@@ -198,7 +238,7 @@ static void internal_dev_destroy(struct vport *vport)
 
        /* unregister_netdevice() waits for an RCU grace period. */
        unregister_netdevice(vport->dev);
-
+       free_percpu(vport->dev->tstats);
        rtnl_unlock();
 }
 
index c11413d5075f882c2b360515285ba520a7303d0c..e1c9c08880373276e8430cadd93f03fe4a1e11a0 100644 (file)
@@ -146,31 +146,12 @@ static struct vport *vxlan_create(const struct vport_parms *parms)
        return ovs_netdev_link(vport, parms->name);
 }
 
-static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                    struct dp_upcall_info *upcall)
-{
-       struct vxlan_dev *vxlan = netdev_priv(vport->dev);
-       struct net *net = ovs_dp_get_net(vport->dp);
-       __be16 dst_port = vxlan_dev_dst_port(vxlan);
-       __be16 src_port;
-       int port_min;
-       int port_max;
-
-       inet_get_local_port_range(net, &port_min, &port_max);
-       src_port = udp_flow_src_port(net, skb, 0, 0, true);
-
-       return ovs_tunnel_get_egress_info(upcall, net,
-                                         skb, IPPROTO_UDP,
-                                         src_port, dst_port);
-}
-
 static struct vport_ops ovs_vxlan_netdev_vport_ops = {
        .type                   = OVS_VPORT_TYPE_VXLAN,
        .create                 = vxlan_create,
        .destroy                = ovs_netdev_tunnel_destroy,
        .get_options            = vxlan_get_options,
        .send                   = ovs_netdev_send,
-       .get_egress_tun_info    = vxlan_get_egress_tun_info,
 };
 
 static int __init ovs_vxlan_tnl_init(void)
index dc81dc619aa2344a5c7912def9d6852fcd37ebda..320c765ce44a07e71daedfd457d37c81ea2e4c49 100644 (file)
@@ -280,35 +280,19 @@ void ovs_vport_del(struct vport *vport)
  */
 void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
 {
-       struct net_device *dev = vport->dev;
-       int i;
-
-       memset(stats, 0, sizeof(*stats));
-       stats->rx_errors  = dev->stats.rx_errors;
-       stats->tx_errors  = dev->stats.tx_errors;
-       stats->tx_dropped = dev->stats.tx_dropped;
-       stats->rx_dropped = dev->stats.rx_dropped;
-
-       stats->rx_dropped += atomic_long_read(&dev->rx_dropped);
-       stats->tx_dropped += atomic_long_read(&dev->tx_dropped);
-
-       for_each_possible_cpu(i) {
-               const struct pcpu_sw_netstats *percpu_stats;
-               struct pcpu_sw_netstats local_stats;
-               unsigned int start;
-
-               percpu_stats = per_cpu_ptr(dev->tstats, i);
-
-               do {
-                       start = u64_stats_fetch_begin_irq(&percpu_stats->syncp);
-                       local_stats = *percpu_stats;
-               } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start));
-
-               stats->rx_bytes         += local_stats.rx_bytes;
-               stats->rx_packets       += local_stats.rx_packets;
-               stats->tx_bytes         += local_stats.tx_bytes;
-               stats->tx_packets       += local_stats.tx_packets;
-       }
+       const struct rtnl_link_stats64 *dev_stats;
+       struct rtnl_link_stats64 temp;
+
+       dev_stats = dev_get_stats(vport->dev, &temp);
+       stats->rx_errors  = dev_stats->rx_errors;
+       stats->tx_errors  = dev_stats->tx_errors;
+       stats->tx_dropped = dev_stats->tx_dropped;
+       stats->rx_dropped = dev_stats->rx_dropped;
+
+       stats->rx_bytes   = dev_stats->rx_bytes;
+       stats->rx_packets = dev_stats->rx_packets;
+       stats->tx_bytes   = dev_stats->tx_bytes;
+       stats->tx_packets = dev_stats->tx_packets;
 }
 
 /**
@@ -460,6 +444,15 @@ int ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
 
        OVS_CB(skb)->input_vport = vport;
        OVS_CB(skb)->mru = 0;
+       if (unlikely(dev_net(skb->dev) != ovs_dp_get_net(vport->dp))) {
+               u32 mark;
+
+               mark = skb->mark;
+               skb_scrub_packet(skb, true);
+               skb->mark = mark;
+               tun_info = NULL;
+       }
+
        /* Extract flow from 'skb' into 'key'. */
        error = ovs_flow_key_extract(tun_info, skb, &key);
        if (unlikely(error)) {
@@ -486,61 +479,3 @@ void ovs_vport_deferred_free(struct vport *vport)
        call_rcu(&vport->rcu, free_vport_rcu);
 }
 EXPORT_SYMBOL_GPL(ovs_vport_deferred_free);
-
-int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall,
-                              struct net *net,
-                              struct sk_buff *skb,
-                              u8 ipproto,
-                              __be16 tp_src,
-                              __be16 tp_dst)
-{
-       struct ip_tunnel_info *egress_tun_info = upcall->egress_tun_info;
-       const struct ip_tunnel_info *tun_info = skb_tunnel_info(skb);
-       const struct ip_tunnel_key *tun_key;
-       u32 skb_mark = skb->mark;
-       struct rtable *rt;
-       struct flowi4 fl;
-
-       if (unlikely(!tun_info))
-               return -EINVAL;
-       if (ip_tunnel_info_af(tun_info) != AF_INET)
-               return -EINVAL;
-
-       tun_key = &tun_info->key;
-
-       /* Route lookup to get srouce IP address.
-        * The process may need to be changed if the corresponding process
-        * in vports ops changed.
-        */
-       rt = ovs_tunnel_route_lookup(net, tun_key, skb_mark, &fl, ipproto);
-       if (IS_ERR(rt))
-               return PTR_ERR(rt);
-
-       ip_rt_put(rt);
-
-       /* Generate egress_tun_info based on tun_info,
-        * saddr, tp_src and tp_dst
-        */
-       ip_tunnel_key_init(&egress_tun_info->key,
-                          fl.saddr, tun_key->u.ipv4.dst,
-                          tun_key->tos,
-                          tun_key->ttl,
-                          tp_src, tp_dst,
-                          tun_key->tun_id,
-                          tun_key->tun_flags);
-       egress_tun_info->options_len = tun_info->options_len;
-       egress_tun_info->mode = tun_info->mode;
-       upcall->egress_tun_opts = ip_tunnel_info_opts(egress_tun_info);
-       return 0;
-}
-EXPORT_SYMBOL_GPL(ovs_tunnel_get_egress_info);
-
-int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                 struct dp_upcall_info *upcall)
-{
-       /* get_egress_tun_info() is only implemented on tunnel ports. */
-       if (unlikely(!vport->ops->get_egress_tun_info))
-               return -EINVAL;
-
-       return vport->ops->get_egress_tun_info(vport, skb, upcall);
-}
index a413f3ae6a7b540ed7b34fd4b31f69424caeb39f..d341ad6f3afe5734f587c1df347fd72dc2ba2c38 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/u64_stats_sync.h>
-#include <net/route.h>
 
 #include "datapath.h"
 
@@ -53,16 +52,6 @@ int ovs_vport_set_upcall_portids(struct vport *, const struct nlattr *pids);
 int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *);
 u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *);
 
-int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall,
-                              struct net *net,
-                              struct sk_buff *,
-                              u8 ipproto,
-                              __be16 tp_src,
-                              __be16 tp_dst);
-
-int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb,
-                                 struct dp_upcall_info *upcall);
-
 /**
  * struct vport_portids - array of netlink portids of a vport.
  *                        must be protected by rcu.
@@ -140,8 +129,6 @@ struct vport_parms {
  * have any configuration.
  * @send: Send a packet on the device.
  * zero for dropped packets or negative for error.
- * @get_egress_tun_info: Get the egress tunnel 5-tuple and other info for
- * a packet.
  */
 struct vport_ops {
        enum ovs_vport_type type;
@@ -154,9 +141,6 @@ struct vport_ops {
        int (*get_options)(const struct vport *, struct sk_buff *);
 
        void (*send)(struct vport *, struct sk_buff *);
-       int (*get_egress_tun_info)(struct vport *, struct sk_buff *,
-                                  struct dp_upcall_info *upcall);
-
        struct module *owner;
        struct list_head list;
 };
@@ -215,25 +199,6 @@ static inline const char *ovs_vport_name(struct vport *vport)
 int ovs_vport_ops_register(struct vport_ops *ops);
 void ovs_vport_ops_unregister(struct vport_ops *ops);
 
-static inline struct rtable *ovs_tunnel_route_lookup(struct net *net,
-                                                    const struct ip_tunnel_key *key,
-                                                    u32 mark,
-                                                    struct flowi4 *fl,
-                                                    u8 protocol)
-{
-       struct rtable *rt;
-
-       memset(fl, 0, sizeof(*fl));
-       fl->daddr = key->u.ipv4.dst;
-       fl->saddr = key->u.ipv4.src;
-       fl->flowi4_tos = RT_TOS(key->tos);
-       fl->flowi4_mark = mark;
-       fl->flowi4_proto = protocol;
-
-       rt = ip_route_output_key(net, fl);
-       return rt;
-}
-
 static inline void ovs_vport_send(struct vport *vport, struct sk_buff *skb)
 {
        vport->ops->send(vport, skb);
index fbc5ef88bc0e692ea4cf9cb59f6163905510928e..27a992154804c685d983206b599ef7a5bf96e8af 100644 (file)
@@ -214,8 +214,15 @@ static int rds_tcp_data_recv(read_descriptor_t *desc, struct sk_buff *skb,
                        }
 
                        to_copy = min(tc->t_tinc_data_rem, left);
-                       pskb_pull(clone, offset);
-                       pskb_trim(clone, to_copy);
+                       if (!pskb_pull(clone, offset) ||
+                           pskb_trim(clone, to_copy)) {
+                               pr_warn("rds_tcp_data_recv: pull/trim failed "
+                                       "left %zu data_rem %zu skb_len %d\n",
+                                       left, tc->t_tinc_data_rem, skb->len);
+                               kfree_skb(clone);
+                               desc->error = -ENOMEM;
+                               goto out;
+                       }
                        skb_queue_tail(&tinc->ti_skb_list, clone);
 
                        rdsdebug("skb %p data %p len %d off %u to_copy %zu -> "
index 2d1be4a760fdc4361f23d0aa93a861298eaafe45..32fcdecdb9e2074bad6f3e3002738e9c289317c3 100644 (file)
 
 #define MIRRED_TAB_MASK     7
 static LIST_HEAD(mirred_list);
+static DEFINE_SPINLOCK(mirred_list_lock);
 
 static void tcf_mirred_release(struct tc_action *a, int bind)
 {
        struct tcf_mirred *m = to_mirred(a);
        struct net_device *dev = rcu_dereference_protected(m->tcfm_dev, 1);
 
+       /* We could be called either in a RCU callback or with RTNL lock held. */
+       spin_lock_bh(&mirred_list_lock);
        list_del(&m->tcfm_list);
+       spin_unlock_bh(&mirred_list_lock);
        if (dev)
                dev_put(dev);
 }
@@ -103,10 +107,10 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
        } else {
                if (bind)
                        return 0;
-               if (!ovr) {
-                       tcf_hash_release(a, bind);
+
+               tcf_hash_release(a, bind);
+               if (!ovr)
                        return -EEXIST;
-               }
        }
        m = to_mirred(a);
 
@@ -123,7 +127,9 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
        }
 
        if (ret == ACT_P_CREATED) {
+               spin_lock_bh(&mirred_list_lock);
                list_add(&m->tcfm_list, &mirred_list);
+               spin_unlock_bh(&mirred_list_lock);
                tcf_hash_insert(a);
        }
 
@@ -173,6 +179,7 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
 
        skb2->skb_iif = skb->dev->ifindex;
        skb2->dev = dev;
+       skb_sender_cpu_clear(skb2);
        err = dev_queue_xmit(skb2);
 
        if (err) {
@@ -221,7 +228,8 @@ static int mirred_device_event(struct notifier_block *unused,
        struct tcf_mirred *m;
 
        ASSERT_RTNL();
-       if (event == NETDEV_UNREGISTER)
+       if (event == NETDEV_UNREGISTER) {
+               spin_lock_bh(&mirred_list_lock);
                list_for_each_entry(m, &mirred_list, tcfm_list) {
                        if (rcu_access_pointer(m->tcfm_dev) == dev) {
                                dev_put(dev);
@@ -231,6 +239,8 @@ static int mirred_device_event(struct notifier_block *unused,
                                RCU_INIT_POINTER(m->tcfm_dev, NULL);
                        }
                }
+               spin_unlock_bh(&mirred_list_lock);
+       }
 
        return NOTIFY_DONE;
 }
index 9d15cb6b8cb1f5e8424e96f6245e9dd206d92405..86b04e31e60b76027214b85ee0c4c0e0de1b04c4 100644 (file)
@@ -368,6 +368,15 @@ static unsigned int hhf_drop(struct Qdisc *sch)
        return bucket - q->buckets;
 }
 
+static unsigned int hhf_qdisc_drop(struct Qdisc *sch)
+{
+       unsigned int prev_backlog;
+
+       prev_backlog = sch->qstats.backlog;
+       hhf_drop(sch);
+       return prev_backlog - sch->qstats.backlog;
+}
+
 static int hhf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
        struct hhf_sched_data *q = qdisc_priv(sch);
@@ -696,7 +705,7 @@ static struct Qdisc_ops hhf_qdisc_ops __read_mostly = {
        .enqueue        =       hhf_enqueue,
        .dequeue        =       hhf_dequeue,
        .peek           =       qdisc_peek_dequeued,
-       .drop           =       hhf_drop,
+       .drop           =       hhf_qdisc_drop,
        .init           =       hhf_init,
        .reset          =       hhf_reset,
        .destroy        =       hhf_destroy,
index fda38f830a10869713177220f8d2066c6076da0c..77f5d17e261230a6db4f261445311eafb37c7b06 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/notifier.h>
 #include <linux/netdevice.h>
 #include <linux/if_bridge.h>
+#include <linux/if_vlan.h>
 #include <net/ip_fib.h>
 #include <net/switchdev.h>
 
@@ -634,6 +635,8 @@ static int switchdev_port_br_afspec(struct net_device *dev,
                if (nla_len(attr) != sizeof(struct bridge_vlan_info))
                        return -EINVAL;
                vinfo = nla_data(attr);
+               if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
+                       return -EINVAL;
                vlan->flags = vinfo->flags;
                if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
                        if (vlan->vid_begin)
index e7000be321b0148469264524ed6fce75c3952955..ed98c1fc3de1428560ea370413084102af9dff7f 100644 (file)
@@ -94,10 +94,14 @@ __init int net_sysctl_init(void)
                goto out;
        ret = register_pernet_subsys(&sysctl_pernet_ops);
        if (ret)
-               goto out;
+               goto out1;
        register_sysctl_root(&net_sysctl_root);
 out:
        return ret;
+out1:
+       unregister_sysctl_table(net_header);
+       net_header = NULL;
+       goto out;
 }
 
 struct ctl_table_header *register_net_sysctl(struct net *net,
index 41042de3ae9bcfad4504e0bcbb29d3bea4512bb5..eadba62afa85dcd9463f5eddd08704539fa63488 100644 (file)
@@ -42,7 +42,8 @@
 #include "core.h"
 
 #define        MAX_PKT_DEFAULT_MCAST   1500    /* bcast link max packet size (fixed) */
-#define        BCLINK_WIN_DEFAULT      20      /* bcast link window size (default) */
+#define        BCLINK_WIN_DEFAULT      50      /* bcast link window size (default) */
+#define        BCLINK_WIN_MIN          32      /* bcast minimum link window size */
 
 const char tipc_bclink_name[] = "broadcast-link";
 
@@ -908,9 +909,10 @@ int tipc_bclink_set_queue_limits(struct net *net, u32 limit)
 
        if (!bcl)
                return -ENOPROTOOPT;
-       if ((limit < TIPC_MIN_LINK_WIN) || (limit > TIPC_MAX_LINK_WIN))
+       if (limit < BCLINK_WIN_MIN)
+               limit = BCLINK_WIN_MIN;
+       if (limit > TIPC_MAX_LINK_WIN)
                return -EINVAL;
-
        tipc_bclink_lock(net);
        tipc_link_set_queue_limits(bcl, limit);
        tipc_bclink_unlock(net);
index c5ac436235e0823c016123394fef6a0cf321092c..5f73450159df3b7d99349e2b49610b7d9a1d6c47 100644 (file)
@@ -121,7 +121,7 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
 {
        struct sk_buff *head = *headbuf;
        struct sk_buff *frag = *buf;
-       struct sk_buff *tail;
+       struct sk_buff *tail = NULL;
        struct tipc_msg *msg;
        u32 fragid;
        int delta;
@@ -141,9 +141,15 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
                if (unlikely(skb_unclone(frag, GFP_ATOMIC)))
                        goto err;
                head = *headbuf = frag;
-               skb_frag_list_init(head);
-               TIPC_SKB_CB(head)->tail = NULL;
                *buf = NULL;
+               TIPC_SKB_CB(head)->tail = NULL;
+               if (skb_is_nonlinear(head)) {
+                       skb_walk_frags(head, tail) {
+                               TIPC_SKB_CB(head)->tail = tail;
+                       }
+               } else {
+                       skb_frag_list_init(head);
+               }
                return 0;
        }
 
index a82c5848d4bc22129bd1e6ba7f677795febdc9e9..5351a3f97e8ecf17e545459344a8b315f522045a 100644 (file)
@@ -357,7 +357,7 @@ static inline u32 msg_importance(struct tipc_msg *m)
        if (likely((usr <= TIPC_CRITICAL_IMPORTANCE) && !msg_errcode(m)))
                return usr;
        if ((usr == MSG_FRAGMENTER) || (usr == MSG_BUNDLER))
-               return msg_bits(m, 5, 13, 0x7);
+               return msg_bits(m, 9, 0, 0x7);
        return TIPC_SYSTEM_IMPORTANCE;
 }
 
@@ -366,7 +366,7 @@ static inline void msg_set_importance(struct tipc_msg *m, u32 i)
        int usr = msg_user(m);
 
        if (likely((usr == MSG_FRAGMENTER) || (usr == MSG_BUNDLER)))
-               msg_set_bits(m, 5, 13, 0x7, i);
+               msg_set_bits(m, 9, 0, 0x7, i);
        else if (i < TIPC_SYSTEM_IMPORTANCE)
                msg_set_user(m, i);
        else
index 703875fd6cde204ddeaf630b9a6bd11daec6dbfa..2c32a83037a3614ef09fb4b29c8f3337dcdf0f45 100644 (file)
@@ -1116,7 +1116,7 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
        }
 
        /* Ignore duplicate packets */
-       if (less(oseqno, rcv_nxt))
+       if ((usr != LINK_PROTOCOL) && less(oseqno, rcv_nxt))
                return true;
 
        /* Initiate or update failover mode if applicable */
@@ -1146,8 +1146,8 @@ static bool tipc_node_check_state(struct tipc_node *n, struct sk_buff *skb,
        if (!pl || !tipc_link_is_up(pl))
                return true;
 
-       /* Initiate or update synch mode if applicable */
-       if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG)) {
+       /* Initiate synch mode if applicable */
+       if ((usr == TUNNEL_PROTOCOL) && (mtyp == SYNCH_MSG) && (oseqno == 1)) {
                syncpt = iseqno + exp_pkts - 1;
                if (!tipc_link_is_up(l)) {
                        tipc_link_fsm_evt(l, LINK_ESTABLISH_EVT);
index c170d3138953a2361df5439aeffadd29afa52ad9..6e648d90297a9ecc69a23a68183fde658eed63cd 100644 (file)
@@ -52,6 +52,8 @@
 /* IANA assigned UDP port */
 #define UDP_PORT_DEFAULT       6118
 
+#define UDP_MIN_HEADROOM        28
+
 static const struct nla_policy tipc_nl_udp_policy[TIPC_NLA_UDP_MAX + 1] = {
        [TIPC_NLA_UDP_UNSPEC]   = {.type = NLA_UNSPEC},
        [TIPC_NLA_UDP_LOCAL]    = {.type = NLA_BINARY,
@@ -156,6 +158,9 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb,
        struct sk_buff *clone;
        struct rtable *rt;
 
+       if (skb_headroom(skb) < UDP_MIN_HEADROOM)
+               pskb_expand_head(skb, UDP_MIN_HEADROOM, 0, GFP_ATOMIC);
+
        clone = skb_clone(skb, GFP_ATOMIC);
        skb_set_inner_protocol(clone, htons(ETH_P_TIPC));
        ub = rcu_dereference_rtnl(b->media_ptr);
index ef31b40ad55000a5fd029d7479b546483cc782b3..94f658235fb49a0c644a84867302cc00a75243d5 100644 (file)
@@ -2064,6 +2064,11 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state)
                goto out;
        }
 
+       if (flags & MSG_PEEK)
+               skip = sk_peek_offset(sk, flags);
+       else
+               skip = 0;
+
        do {
                int chunk;
                struct sk_buff *skb, *last;
@@ -2112,7 +2117,6 @@ unlock:
                        break;
                }
 
-               skip = sk_peek_offset(sk, flags);
                while (skip >= unix_skb_len(skb)) {
                        skip -= unix_skb_len(skb);
                        last = skb;
@@ -2179,14 +2183,12 @@ unlock:
                        if (UNIXCB(skb).fp)
                                scm.fp = scm_fp_dup(UNIXCB(skb).fp);
 
-                       if (skip) {
-                               sk_peek_offset_fwd(sk, chunk);
-                               skip -= chunk;
-                       }
+                       sk_peek_offset_fwd(sk, chunk);
 
                        if (UNIXCB(skb).fp)
                                break;
 
+                       skip = 0;
                        last = skb;
                        last_len = skb->len;
                        unix_state_lock(sk);
index df5fc6b340f1bbde621fbe84fa44e0af6e2e00af..00e8a349aabccc61cec1f9ebb889bc7dd9d3b5e1 100644 (file)
@@ -1948,13 +1948,13 @@ int __vsock_core_init(const struct vsock_transport *t, struct module *owner)
        err = misc_register(&vsock_device);
        if (err) {
                pr_err("Failed to register misc device\n");
-               return -ENOENT;
+               goto err_reset_transport;
        }
 
        err = proto_register(&vsock_proto, 1);  /* we want our slab */
        if (err) {
                pr_err("Cannot register vsock protocol\n");
-               goto err_misc_deregister;
+               goto err_deregister_misc;
        }
 
        err = sock_register(&vsock_family_ops);
@@ -1969,8 +1969,9 @@ int __vsock_core_init(const struct vsock_transport *t, struct module *owner)
 
 err_unregister_proto:
        proto_unregister(&vsock_proto);
-err_misc_deregister:
+err_deregister_misc:
        misc_deregister(&vsock_device);
+err_reset_transport:
        transport = NULL;
 err_busy:
        mutex_unlock(&vsock_register_mutex);
index 1f63daff39659e08561862cfd71220ffc6949291..7555cad83a752a930a54e4a8ca609846386e0ec1 100644 (file)
 
 static int vmci_transport_recv_dgram_cb(void *data, struct vmci_datagram *dg);
 static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg);
-static void vmci_transport_peer_attach_cb(u32 sub_id,
-                                         const struct vmci_event_data *ed,
-                                         void *client_data);
 static void vmci_transport_peer_detach_cb(u32 sub_id,
                                          const struct vmci_event_data *ed,
                                          void *client_data);
 static void vmci_transport_recv_pkt_work(struct work_struct *work);
+static void vmci_transport_cleanup(struct work_struct *work);
 static int vmci_transport_recv_listen(struct sock *sk,
                                      struct vmci_transport_packet *pkt);
 static int vmci_transport_recv_connecting_server(
@@ -75,6 +73,10 @@ struct vmci_transport_recv_pkt_info {
        struct vmci_transport_packet pkt;
 };
 
+static LIST_HEAD(vmci_transport_cleanup_list);
+static DEFINE_SPINLOCK(vmci_transport_cleanup_lock);
+static DECLARE_WORK(vmci_transport_cleanup_work, vmci_transport_cleanup);
+
 static struct vmci_handle vmci_transport_stream_handle = { VMCI_INVALID_ID,
                                                           VMCI_INVALID_ID };
 static u32 vmci_transport_qp_resumed_sub_id = VMCI_INVALID_ID;
@@ -791,44 +793,6 @@ out:
        return err;
 }
 
-static void vmci_transport_peer_attach_cb(u32 sub_id,
-                                         const struct vmci_event_data *e_data,
-                                         void *client_data)
-{
-       struct sock *sk = client_data;
-       const struct vmci_event_payload_qp *e_payload;
-       struct vsock_sock *vsk;
-
-       e_payload = vmci_event_data_const_payload(e_data);
-
-       vsk = vsock_sk(sk);
-
-       /* We don't ask for delayed CBs when we subscribe to this event (we
-        * pass 0 as flags to vmci_event_subscribe()).  VMCI makes no
-        * guarantees in that case about what context we might be running in,
-        * so it could be BH or process, blockable or non-blockable.  So we
-        * need to account for all possible contexts here.
-        */
-       local_bh_disable();
-       bh_lock_sock(sk);
-
-       /* XXX This is lame, we should provide a way to lookup sockets by
-        * qp_handle.
-        */
-       if (vmci_handle_is_equal(vmci_trans(vsk)->qp_handle,
-                                e_payload->handle)) {
-               /* XXX This doesn't do anything, but in the future we may want
-                * to set a flag here to verify the attach really did occur and
-                * we weren't just sent a datagram claiming it was.
-                */
-               goto out;
-       }
-
-out:
-       bh_unlock_sock(sk);
-       local_bh_enable();
-}
-
 static void vmci_transport_handle_detach(struct sock *sk)
 {
        struct vsock_sock *vsk;
@@ -871,28 +835,38 @@ static void vmci_transport_peer_detach_cb(u32 sub_id,
                                          const struct vmci_event_data *e_data,
                                          void *client_data)
 {
-       struct sock *sk = client_data;
+       struct vmci_transport *trans = client_data;
        const struct vmci_event_payload_qp *e_payload;
-       struct vsock_sock *vsk;
 
        e_payload = vmci_event_data_const_payload(e_data);
-       vsk = vsock_sk(sk);
-       if (vmci_handle_is_invalid(e_payload->handle))
-               return;
-
-       /* Same rules for locking as for peer_attach_cb(). */
-       local_bh_disable();
-       bh_lock_sock(sk);
 
        /* XXX This is lame, we should provide a way to lookup sockets by
         * qp_handle.
         */
-       if (vmci_handle_is_equal(vmci_trans(vsk)->qp_handle,
-                                e_payload->handle))
-               vmci_transport_handle_detach(sk);
+       if (vmci_handle_is_invalid(e_payload->handle) ||
+           vmci_handle_is_equal(trans->qp_handle, e_payload->handle))
+               return;
 
-       bh_unlock_sock(sk);
-       local_bh_enable();
+       /* We don't ask for delayed CBs when we subscribe to this event (we
+        * pass 0 as flags to vmci_event_subscribe()).  VMCI makes no
+        * guarantees in that case about what context we might be running in,
+        * so it could be BH or process, blockable or non-blockable.  So we
+        * need to account for all possible contexts here.
+        */
+       spin_lock_bh(&trans->lock);
+       if (!trans->sk)
+               goto out;
+
+       /* Apart from here, trans->lock is only grabbed as part of sk destruct,
+        * where trans->sk isn't locked.
+        */
+       bh_lock_sock(trans->sk);
+
+       vmci_transport_handle_detach(trans->sk);
+
+       bh_unlock_sock(trans->sk);
+ out:
+       spin_unlock_bh(&trans->lock);
 }
 
 static void vmci_transport_qp_resumed_cb(u32 sub_id,
@@ -1181,7 +1155,7 @@ vmci_transport_recv_connecting_server(struct sock *listener,
         */
        err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_DETACH,
                                   vmci_transport_peer_detach_cb,
-                                  pending, &detach_sub_id);
+                                  vmci_trans(vpending), &detach_sub_id);
        if (err < VMCI_SUCCESS) {
                vmci_transport_send_reset(pending, pkt);
                err = vmci_transport_error_to_vsock_error(err);
@@ -1321,7 +1295,6 @@ vmci_transport_recv_connecting_client(struct sock *sk,
                    || vmci_trans(vsk)->qpair
                    || vmci_trans(vsk)->produce_size != 0
                    || vmci_trans(vsk)->consume_size != 0
-                   || vmci_trans(vsk)->attach_sub_id != VMCI_INVALID_ID
                    || vmci_trans(vsk)->detach_sub_id != VMCI_INVALID_ID) {
                        skerr = EPROTO;
                        err = -EINVAL;
@@ -1389,7 +1362,6 @@ static int vmci_transport_recv_connecting_client_negotiate(
        struct vsock_sock *vsk;
        struct vmci_handle handle;
        struct vmci_qp *qpair;
-       u32 attach_sub_id;
        u32 detach_sub_id;
        bool is_local;
        u32 flags;
@@ -1399,7 +1371,6 @@ static int vmci_transport_recv_connecting_client_negotiate(
 
        vsk = vsock_sk(sk);
        handle = VMCI_INVALID_HANDLE;
-       attach_sub_id = VMCI_INVALID_ID;
        detach_sub_id = VMCI_INVALID_ID;
 
        /* If we have gotten here then we should be past the point where old
@@ -1444,23 +1415,15 @@ static int vmci_transport_recv_connecting_client_negotiate(
                goto destroy;
        }
 
-       /* Subscribe to attach and detach events first.
+       /* Subscribe to detach events first.
         *
         * XXX We attach once for each queue pair created for now so it is easy
         * to find the socket (it's provided), but later we should only
         * subscribe once and add a way to lookup sockets by queue pair handle.
         */
-       err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_ATTACH,
-                                  vmci_transport_peer_attach_cb,
-                                  sk, &attach_sub_id);
-       if (err < VMCI_SUCCESS) {
-               err = vmci_transport_error_to_vsock_error(err);
-               goto destroy;
-       }
-
        err = vmci_event_subscribe(VMCI_EVENT_QP_PEER_DETACH,
                                   vmci_transport_peer_detach_cb,
-                                  sk, &detach_sub_id);
+                                  vmci_trans(vsk), &detach_sub_id);
        if (err < VMCI_SUCCESS) {
                err = vmci_transport_error_to_vsock_error(err);
                goto destroy;
@@ -1496,7 +1459,6 @@ static int vmci_transport_recv_connecting_client_negotiate(
        vmci_trans(vsk)->produce_size = vmci_trans(vsk)->consume_size =
                pkt->u.size;
 
-       vmci_trans(vsk)->attach_sub_id = attach_sub_id;
        vmci_trans(vsk)->detach_sub_id = detach_sub_id;
 
        vmci_trans(vsk)->notify_ops->process_negotiate(sk);
@@ -1504,9 +1466,6 @@ static int vmci_transport_recv_connecting_client_negotiate(
        return 0;
 
 destroy:
-       if (attach_sub_id != VMCI_INVALID_ID)
-               vmci_event_unsubscribe(attach_sub_id);
-
        if (detach_sub_id != VMCI_INVALID_ID)
                vmci_event_unsubscribe(detach_sub_id);
 
@@ -1607,9 +1566,11 @@ static int vmci_transport_socket_init(struct vsock_sock *vsk,
        vmci_trans(vsk)->qp_handle = VMCI_INVALID_HANDLE;
        vmci_trans(vsk)->qpair = NULL;
        vmci_trans(vsk)->produce_size = vmci_trans(vsk)->consume_size = 0;
-       vmci_trans(vsk)->attach_sub_id = vmci_trans(vsk)->detach_sub_id =
-               VMCI_INVALID_ID;
+       vmci_trans(vsk)->detach_sub_id = VMCI_INVALID_ID;
        vmci_trans(vsk)->notify_ops = NULL;
+       INIT_LIST_HEAD(&vmci_trans(vsk)->elem);
+       vmci_trans(vsk)->sk = &vsk->sk;
+       spin_lock_init(&vmci_trans(vsk)->lock);
        if (psk) {
                vmci_trans(vsk)->queue_pair_size =
                        vmci_trans(psk)->queue_pair_size;
@@ -1629,29 +1590,57 @@ static int vmci_transport_socket_init(struct vsock_sock *vsk,
        return 0;
 }
 
-static void vmci_transport_destruct(struct vsock_sock *vsk)
+static void vmci_transport_free_resources(struct list_head *transport_list)
 {
-       if (vmci_trans(vsk)->attach_sub_id != VMCI_INVALID_ID) {
-               vmci_event_unsubscribe(vmci_trans(vsk)->attach_sub_id);
-               vmci_trans(vsk)->attach_sub_id = VMCI_INVALID_ID;
-       }
+       while (!list_empty(transport_list)) {
+               struct vmci_transport *transport =
+                   list_first_entry(transport_list, struct vmci_transport,
+                                    elem);
+               list_del(&transport->elem);
 
-       if (vmci_trans(vsk)->detach_sub_id != VMCI_INVALID_ID) {
-               vmci_event_unsubscribe(vmci_trans(vsk)->detach_sub_id);
-               vmci_trans(vsk)->detach_sub_id = VMCI_INVALID_ID;
-       }
+               if (transport->detach_sub_id != VMCI_INVALID_ID) {
+                       vmci_event_unsubscribe(transport->detach_sub_id);
+                       transport->detach_sub_id = VMCI_INVALID_ID;
+               }
 
-       if (!vmci_handle_is_invalid(vmci_trans(vsk)->qp_handle)) {
-               vmci_qpair_detach(&vmci_trans(vsk)->qpair);
-               vmci_trans(vsk)->qp_handle = VMCI_INVALID_HANDLE;
-               vmci_trans(vsk)->produce_size = 0;
-               vmci_trans(vsk)->consume_size = 0;
+               if (!vmci_handle_is_invalid(transport->qp_handle)) {
+                       vmci_qpair_detach(&transport->qpair);
+                       transport->qp_handle = VMCI_INVALID_HANDLE;
+                       transport->produce_size = 0;
+                       transport->consume_size = 0;
+               }
+
+               kfree(transport);
        }
+}
+
+static void vmci_transport_cleanup(struct work_struct *work)
+{
+       LIST_HEAD(pending);
+
+       spin_lock_bh(&vmci_transport_cleanup_lock);
+       list_replace_init(&vmci_transport_cleanup_list, &pending);
+       spin_unlock_bh(&vmci_transport_cleanup_lock);
+       vmci_transport_free_resources(&pending);
+}
+
+static void vmci_transport_destruct(struct vsock_sock *vsk)
+{
+       /* Ensure that the detach callback doesn't use the sk/vsk
+        * we are about to destruct.
+        */
+       spin_lock_bh(&vmci_trans(vsk)->lock);
+       vmci_trans(vsk)->sk = NULL;
+       spin_unlock_bh(&vmci_trans(vsk)->lock);
 
        if (vmci_trans(vsk)->notify_ops)
                vmci_trans(vsk)->notify_ops->socket_destruct(vsk);
 
-       kfree(vsk->trans);
+       spin_lock_bh(&vmci_transport_cleanup_lock);
+       list_add(&vmci_trans(vsk)->elem, &vmci_transport_cleanup_list);
+       spin_unlock_bh(&vmci_transport_cleanup_lock);
+       schedule_work(&vmci_transport_cleanup_work);
+
        vsk->trans = NULL;
 }
 
@@ -2146,6 +2135,9 @@ module_init(vmci_transport_init);
 
 static void __exit vmci_transport_exit(void)
 {
+       cancel_work_sync(&vmci_transport_cleanup_work);
+       vmci_transport_free_resources(&vmci_transport_cleanup_list);
+
        if (!vmci_handle_is_invalid(vmci_transport_stream_handle)) {
                if (vmci_datagram_destroy_handle(
                        vmci_transport_stream_handle) != VMCI_SUCCESS)
@@ -2164,6 +2156,7 @@ module_exit(vmci_transport_exit);
 
 MODULE_AUTHOR("VMware, Inc.");
 MODULE_DESCRIPTION("VMCI transport for Virtual Sockets");
+MODULE_VERSION("1.0.2.0-k");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("vmware_vsock");
 MODULE_ALIAS_NETPROTO(PF_VSOCK);
index ce6c9623d5f069029ce58294bcc7de9bc3728fcd..2ad46f39649f8130d9f19ce48ccf8a8b4309797d 100644 (file)
@@ -119,10 +119,12 @@ struct vmci_transport {
        u64 queue_pair_size;
        u64 queue_pair_min_size;
        u64 queue_pair_max_size;
-       u32 attach_sub_id;
        u32 detach_sub_id;
        union vmci_transport_notify notify;
        struct vmci_transport_notify_ops *notify_ops;
+       struct list_head elem;
+       struct sock *sk;
+       spinlock_t lock; /* protects sk. */
 };
 
 int vmci_transport_register(void);
index a8de9e3002000d7eaa76f6764797e5b231d187ff..24e06a2377f6b3601003157d22dd05bb0278f145 100644 (file)
@@ -1928,8 +1928,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
        struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
        struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
+       struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
+       struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
 
-       if (!lt && !rp && !re)
+       if (!lt && !rp && !re && !et && !rt)
                return err;
 
        /* pedantic mode - thou shalt sayeth replaceth */
index 3a44d3a272af40119b379fe1930244909499fd8d..af44e564d6ddc1278e6edce3c6b18a7879c76ecd 100644 (file)
@@ -86,5 +86,17 @@ static int (*bpf_l4_csum_replace)(void *ctx, int off, int from, int to, int flag
 #define PT_REGS_RC(x) ((x)->gprs[2])
 #define PT_REGS_SP(x) ((x)->gprs[15])
 
+#elif defined(__aarch64__)
+
+#define PT_REGS_PARM1(x) ((x)->regs[0])
+#define PT_REGS_PARM2(x) ((x)->regs[1])
+#define PT_REGS_PARM3(x) ((x)->regs[2])
+#define PT_REGS_PARM4(x) ((x)->regs[3])
+#define PT_REGS_PARM5(x) ((x)->regs[4])
+#define PT_REGS_RET(x) ((x)->regs[30])
+#define PT_REGS_FP(x) ((x)->regs[29]) /* Works only with CONFIG_FRAME_POINTER */
+#define PT_REGS_RC(x) ((x)->regs[0])
+#define PT_REGS_SP(x) ((x)->sp)
+
 #endif
 #endif
index 39eac1fd5706c6370df8b18fe5ac42e85e1b2ed3..addf060399e09547307d9c023f36d8dbf869a931 100644 (file)
@@ -134,8 +134,10 @@ static noinline void key_gc_unused_keys(struct list_head *keys)
                kdebug("- %u", key->serial);
                key_check(key);
 
-               /* Throw away the key data */
-               if (key->type->destroy)
+               /* Throw away the key data if the key is instantiated */
+               if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags) &&
+                   !test_bit(KEY_FLAG_NEGATIVE, &key->flags) &&
+                   key->type->destroy)
                        key->type->destroy(key);
 
                security_key_free(key);
index 486ef6fa393b2cc9d8ceb8cb11f187f97730bd90..0d625312427831b63ed18784719cd0b424f03a41 100644 (file)
@@ -440,6 +440,9 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx,
 
        kenter("");
 
+       if (ctx->index_key.type == &key_type_keyring)
+               return ERR_PTR(-EPERM);
+       
        user = key_user_lookup(current_fsuid());
        if (!user)
                return ERR_PTR(-ENOMEM);
index 4449d1a990893db4078a102b9da0f92835d5add3..2433f7c81472848be51b9af420ec198b523871b1 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <sound/hdaudio_ext.h>
 
 MODULE_DESCRIPTION("HDA extended core");
index 37f43a1b34ef1f5f48682230055c0f01d9a07449..a249d5486889dca683af566e0818d95ee49b12ae 100644 (file)
@@ -3367,10 +3367,8 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec)
        int dev, err;
 
        err = snd_hda_codec_parse_pcms(codec);
-       if (err < 0) {
-               snd_hda_codec_reset(codec);
+       if (err < 0)
                return err;
-       }
 
        /* attach a new PCM streams */
        list_for_each_entry(cpcm, &codec->pcm_list_head, list) {
index ca03c40609fcf09d8838ed05f4920de3f03a6cf7..2f0ec7c45fc70d6232339761e5773349d24213a9 100644 (file)
@@ -819,6 +819,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo IdeaPad Z560", CXT_FIXUP_MUTE_LED_EAPD),
+       SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
index 3c2f0f8d6266e358a667aa376fea3d094829845a..f823eb502367dccad4b93e71ac7e06d30c0bccdf 100644 (file)
@@ -50,24 +50,24 @@ struct rt298_priv {
 };
 
 static struct reg_default rt298_index_def[] = {
-       { 0x01, 0xaaaa },
-       { 0x02, 0x8aaa },
+       { 0x01, 0xa5a8 },
+       { 0x02, 0x8e95 },
        { 0x03, 0x0002 },
-       { 0x04, 0xaf01 },
-       { 0x08, 0x000d },
-       { 0x09, 0xd810 },
-       { 0x0a, 0x0120 },
+       { 0x04, 0xaf67 },
+       { 0x08, 0x200f },
+       { 0x09, 0xd010 },
+       { 0x0a, 0x0100 },
        { 0x0b, 0x0000 },
        { 0x0d, 0x2800 },
-       { 0x0f, 0x0000 },
-       { 0x19, 0x0a17 },
+       { 0x0f, 0x0022 },
+       { 0x19, 0x0217 },
        { 0x20, 0x0020 },
        { 0x33, 0x0208 },
        { 0x46, 0x0300 },
-       { 0x49, 0x0004 },
-       { 0x4f, 0x50e9 },
-       { 0x50, 0x2000 },
-       { 0x63, 0x2902 },
+       { 0x49, 0x4004 },
+       { 0x4f, 0x50c9 },
+       { 0x50, 0x3000 },
+       { 0x63, 0x1b02 },
        { 0x67, 0x1111 },
        { 0x68, 0x1016 },
        { 0x69, 0x273f },
@@ -1214,7 +1214,7 @@ static int rt298_i2c_probe(struct i2c_client *i2c,
        mdelay(10);
 
        if (!rt298->pdata.gpio2_en)
-               regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0x4000);
+               regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0x40);
        else
                regmap_write(rt298->regmap, RT298_SET_DMIC2_DEFAULT, 0);
 
index 2fbc6ef8cbdb394fd4ffa2b612f50d111fcdc4e5..39ebd7bf4f5306382c86fb49f3417dc3c908dcad 100644 (file)
@@ -3808,6 +3808,8 @@ static int wm8962_runtime_resume(struct device *dev)
 
        wm8962_reset(wm8962);
 
+       regcache_mark_dirty(wm8962->regmap);
+
        /* SYSCLK defaults to on; make sure it is off so we can safely
         * write to registers if the device is declocked.
         */
index 100d92b5b77ef92da6a7e64efd58ffde1437f769..05977ae1ff2a3250c3fe2043b8124f9370dd1542 100644 (file)
@@ -206,6 +206,34 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
 }
 EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
 
+/**
+ * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
+ * @kcontrol: mixer control
+ * @uinfo: control element information
+ *
+ * Callback to provide information about a single mixer control, or a double
+ * mixer control that spans 2 registers of the SX TLV type. SX TLV controls
+ * have a range that represents both positive and negative values either side
+ * of zero but without a sign bit.
+ *
+ * Returns 0 for success.
+ */
+int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
+                         struct snd_ctl_elem_info *uinfo)
+{
+       struct soc_mixer_control *mc =
+               (struct soc_mixer_control *)kcontrol->private_value;
+
+       snd_soc_info_volsw(kcontrol, uinfo);
+       /* Max represents the number of levels in an SX control not the
+        * maximum value, so add the minimum value back on
+        */
+       uinfo->value.integer.max += mc->min;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx);
+
 /**
  * snd_soc_get_volsw - single mixer get callback
  * @kcontrol: mixer control
index 48c6e1ac6827f14be7eaede56bfd1ae3d185d217..b9d3a32cbc048ddb7c1c885fb3af523f97944fbc 100644 (file)
@@ -137,6 +137,8 @@ bool kvm_timer_should_fire(struct kvm_vcpu *vcpu)
 void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
 {
        struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
+       bool phys_active;
+       int ret;
 
        /*
         * We're about to run this vcpu again, so there is no need to
@@ -151,6 +153,23 @@ void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
         */
        if (kvm_timer_should_fire(vcpu))
                kvm_timer_inject_irq(vcpu);
+
+       /*
+        * We keep track of whether the edge-triggered interrupt has been
+        * signalled to the vgic/guest, and if so, we mask the interrupt and
+        * the physical distributor to prevent the timer from raising a
+        * physical interrupt whenever we run a guest, preventing forward
+        * VCPU progress.
+        */
+       if (kvm_vgic_get_phys_irq_active(timer->map))
+               phys_active = true;
+       else
+               phys_active = false;
+
+       ret = irq_set_irqchip_state(timer->map->irq,
+                                   IRQCHIP_STATE_ACTIVE,
+                                   phys_active);
+       WARN_ON(ret);
 }
 
 /**
index 6bd1c9bf7ae71504d042f455bce8ad9ca6abf6fc..66c66165e712d743ed3da1a501c03a087f442378 100644 (file)
@@ -531,6 +531,34 @@ bool vgic_handle_set_pending_reg(struct kvm *kvm,
        return false;
 }
 
+/*
+ * If a mapped interrupt's state has been modified by the guest such that it
+ * is no longer active or pending, without it have gone through the sync path,
+ * then the map->active field must be cleared so the interrupt can be taken
+ * again.
+ */
+static void vgic_handle_clear_mapped_irq(struct kvm_vcpu *vcpu)
+{
+       struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+       struct list_head *root;
+       struct irq_phys_map_entry *entry;
+       struct irq_phys_map *map;
+
+       rcu_read_lock();
+
+       /* Check for PPIs */
+       root = &vgic_cpu->irq_phys_map_list;
+       list_for_each_entry_rcu(entry, root, entry) {
+               map = &entry->map;
+
+               if (!vgic_dist_irq_is_pending(vcpu, map->virt_irq) &&
+                   !vgic_irq_is_active(vcpu, map->virt_irq))
+                       map->active = false;
+       }
+
+       rcu_read_unlock();
+}
+
 bool vgic_handle_clear_pending_reg(struct kvm *kvm,
                                   struct kvm_exit_mmio *mmio,
                                   phys_addr_t offset, int vcpu_id)
@@ -561,6 +589,7 @@ bool vgic_handle_clear_pending_reg(struct kvm *kvm,
                                          vcpu_id, offset);
                vgic_reg_access(mmio, reg, offset, mode);
 
+               vgic_handle_clear_mapped_irq(kvm_get_vcpu(kvm, vcpu_id));
                vgic_update_state(kvm);
                return true;
        }
@@ -598,6 +627,7 @@ bool vgic_handle_clear_active_reg(struct kvm *kvm,
                        ACCESS_READ_VALUE | ACCESS_WRITE_CLEARBIT);
 
        if (mmio->is_write) {
+               vgic_handle_clear_mapped_irq(kvm_get_vcpu(kvm, vcpu_id));
                vgic_update_state(kvm);
                return true;
        }
@@ -982,6 +1012,12 @@ static int compute_pending_for_cpu(struct kvm_vcpu *vcpu)
        pend_percpu = vcpu->arch.vgic_cpu.pending_percpu;
        pend_shared = vcpu->arch.vgic_cpu.pending_shared;
 
+       if (!dist->enabled) {
+               bitmap_zero(pend_percpu, VGIC_NR_PRIVATE_IRQS);
+               bitmap_zero(pend_shared, nr_shared);
+               return 0;
+       }
+
        pending = vgic_bitmap_get_cpu_map(&dist->irq_pending, vcpu_id);
        enabled = vgic_bitmap_get_cpu_map(&dist->irq_enabled, vcpu_id);
        bitmap_and(pend_percpu, pending, enabled, VGIC_NR_PRIVATE_IRQS);
@@ -1009,11 +1045,6 @@ void vgic_update_state(struct kvm *kvm)
        struct kvm_vcpu *vcpu;
        int c;
 
-       if (!dist->enabled) {
-               set_bit(0, dist->irq_pending_on_cpu);
-               return;
-       }
-
        kvm_for_each_vcpu(c, vcpu, kvm) {
                if (compute_pending_for_cpu(vcpu))
                        set_bit(c, dist->irq_pending_on_cpu);
@@ -1092,6 +1123,15 @@ static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu)
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
        struct vgic_lr vlr = vgic_get_lr(vcpu, lr_nr);
 
+       /*
+        * We must transfer the pending state back to the distributor before
+        * retiring the LR, otherwise we may loose edge-triggered interrupts.
+        */
+       if (vlr.state & LR_STATE_PENDING) {
+               vgic_dist_irq_set_pending(vcpu, irq);
+               vlr.hwirq = 0;
+       }
+
        vlr.state = 0;
        vgic_set_lr(vcpu, lr_nr, vlr);
        clear_bit(lr_nr, vgic_cpu->lr_used);
@@ -1132,7 +1172,8 @@ static void vgic_queue_irq_to_lr(struct kvm_vcpu *vcpu, int irq,
                kvm_debug("Set active, clear distributor: 0x%x\n", vlr.state);
                vgic_irq_clear_active(vcpu, irq);
                vgic_update_state(vcpu->kvm);
-       } else if (vgic_dist_irq_is_pending(vcpu, irq)) {
+       } else {
+               WARN_ON(!vgic_dist_irq_is_pending(vcpu, irq));
                vlr.state |= LR_STATE_PENDING;
                kvm_debug("Set pending: 0x%x\n", vlr.state);
        }
@@ -1240,7 +1281,7 @@ static void __kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
        struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
        struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
        unsigned long *pa_percpu, *pa_shared;
-       int i, vcpu_id, lr, ret;
+       int i, vcpu_id;
        int overflow = 0;
        int nr_shared = vgic_nr_shared_irqs(dist);
 
@@ -1295,31 +1336,6 @@ epilog:
                 */
                clear_bit(vcpu_id, dist->irq_pending_on_cpu);
        }
-
-       for (lr = 0; lr < vgic->nr_lr; lr++) {
-               struct vgic_lr vlr;
-
-               if (!test_bit(lr, vgic_cpu->lr_used))
-                       continue;
-
-               vlr = vgic_get_lr(vcpu, lr);
-
-               /*
-                * If we have a mapping, and the virtual interrupt is
-                * presented to the guest (as pending or active), then we must
-                * set the state to active in the physical world. See
-                * Documentation/virtual/kvm/arm/vgic-mapped-irqs.txt.
-                */
-               if (vlr.state & LR_HW) {
-                       struct irq_phys_map *map;
-                       map = vgic_irq_map_search(vcpu, vlr.irq);
-
-                       ret = irq_set_irqchip_state(map->irq,
-                                                   IRQCHIP_STATE_ACTIVE,
-                                                   true);
-                       WARN_ON(ret);
-               }
-       }
 }
 
 static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
@@ -1421,7 +1437,7 @@ static int vgic_sync_hwirq(struct kvm_vcpu *vcpu, struct vgic_lr vlr)
                return 0;
 
        map = vgic_irq_map_search(vcpu, vlr.irq);
-       BUG_ON(!map || !map->active);
+       BUG_ON(!map);
 
        ret = irq_get_irqchip_state(map->irq,
                                    IRQCHIP_STATE_ACTIVE,
@@ -1429,13 +1445,8 @@ static int vgic_sync_hwirq(struct kvm_vcpu *vcpu, struct vgic_lr vlr)
 
        WARN_ON(ret);
 
-       if (map->active) {
-               ret = irq_set_irqchip_state(map->irq,
-                                           IRQCHIP_STATE_ACTIVE,
-                                           false);
-               WARN_ON(ret);
+       if (map->active)
                return 0;
-       }
 
        return 1;
 }
@@ -1607,8 +1618,12 @@ static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
        } else {
                if (level_triggered) {
                        vgic_dist_irq_clear_level(vcpu, irq_num);
-                       if (!vgic_dist_irq_soft_pend(vcpu, irq_num))
+                       if (!vgic_dist_irq_soft_pend(vcpu, irq_num)) {
                                vgic_dist_irq_clear_pending(vcpu, irq_num);
+                               vgic_cpu_irq_clear(vcpu, irq_num);
+                               if (!compute_pending_for_cpu(vcpu))
+                                       clear_bit(cpuid, dist->irq_pending_on_cpu);
+                       }
                }
 
                ret = false;