Merge branch 'linux-linaro-lsk-v4.4-android' of git://git.linaro.org/kernel/linux...
authorHuang, Tao <huangtao@rock-chips.com>
Tue, 10 Jan 2017 07:57:54 +0000 (15:57 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Tue, 10 Jan 2017 08:07:06 +0000 (16:07 +0800)
* linux-linaro-lsk-v4.4-android: (199 commits)
  Linux 4.4.41
  net: mvpp2: fix dma unmapping of TX buffers for fragments
  sg_write()/bsg_write() is not fit to be called under KERNEL_DS
  kconfig/nconf: Fix hang when editing symbol with a long prompt
  target/user: Fix use-after-free of tcmu_cmds if they are expired
  powerpc: Convert cmp to cmpd in idle enter sequence
  powerpc/ps3: Fix system hang with GCC 5 builds
  nfs_write_end(): fix handling of short copies
  libceph: verify authorize reply on connect
  PCI: Check for PME in targeted sleep state
  Input: drv260x - fix input device's parent assignment
  media: solo6x10: fix lockup by avoiding delayed register write
  IB/cma: Fix a race condition in iboe_addr_get_sgid()
  IB/multicast: Check ib_find_pkey() return value
  IPoIB: Avoid reading an uninitialized member variable
  IB/mad: Fix an array index check
  fgraph: Handle a case where a tracer ignores set_graph_notrace
  platform/x86: asus-nb-wmi.c: Add X45U quirk
  ftrace/x86_32: Set ftrace_stub to weak to prevent gcc from using short jumps to it
  kvm: nVMX: Allow L1 to intercept software exceptions (#BP and #OF)
  ...

Change-Id: I8c8467700d5563d9a1121c982737ff0ab6d9cdc9

252 files changed:
Documentation/virtual/kvm/api.txt
Makefile
android/configs/android-base.cfg
arch/arc/include/asm/cacheflush.h
arch/arc/include/asm/delay.h
arch/arc/mm/cache.c
arch/arm/configs/ranchu_defconfig
arch/arm/xen/enlighten.c
arch/arm64/Kconfig.debug
arch/arm64/configs/ranchu64_defconfig
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/processor.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/suspend.c
arch/arm64/mm/fault.c
arch/m68k/include/asm/delay.h
arch/parisc/include/asm/pgtable.h
arch/parisc/kernel/cache.c
arch/parisc/kernel/pacache.S
arch/powerpc/boot/ps3-head.S
arch/powerpc/boot/ps3.c
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/uapi/asm/kvm.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kernel/idle_power7.S
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_rm_mmu.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/sparc/kernel/signal_32.c
arch/sparc/mm/init_64.c
arch/x86/configs/i386_ranchu_defconfig
arch/x86/configs/x86_64_ranchu_defconfig
arch/x86/entry/entry_32.S
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/head_32.S
arch/x86/kvm/vmx.c
block/blk-map.c
block/blk-mq.c
block/bsg.c
crypto/Makefile
crypto/mcryptd.c
drivers/acpi/video_detect.c
drivers/base/core.c
drivers/base/firmware_class.c
drivers/block/loop.c
drivers/block/zram/zram_drv.c
drivers/char/tpm/xen-tpmfront.c
drivers/clk/bcm/clk-bcm2835.c
drivers/clk/ti/clk-3xxx.c
drivers/clk/ti/clock.h
drivers/clk/ti/dpll.c
drivers/clk/ti/dpll3xxx.c
drivers/crypto/caam/caamalg.c
drivers/firmware/efi/arm-init.c
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/gma500/psb_drv.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowacpi.c
drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
drivers/gpu/drm/radeon/radeon_cursor.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/si_dpm.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/multicast.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/input/misc/drv260x.c
drivers/md/Kconfig
drivers/md/dm-crypt.c
drivers/md/dm-flakey.c
drivers/md/dm-verity-target.c
drivers/md/persistent-data/dm-space-map-metadata.c
drivers/md/raid5.c
drivers/media/pci/solo6x10/solo6x10.h
drivers/misc/mei/client.c
drivers/mmc/host/sdhci.c
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/dsa/bcm_sf2.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/marvell/mvpp2.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/geneve.c
drivers/net/virtio_net.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/realtek/rtlwifi/base.c
drivers/net/wireless/realtek/rtlwifi/core.c
drivers/net/wireless/realtek/rtlwifi/pci.c
drivers/net/wireless/realtek/rtlwifi/ps.c
drivers/pci/pci.c
drivers/pci/pcie/aer/aer_inject.c
drivers/pci/probe.c
drivers/platform/x86/asus-nb-wmi.c
drivers/pwm/sysfs.c
drivers/regulator/stw481x-vmmc.c
drivers/s390/char/vmlogrdr.c
drivers/s390/scsi/zfcp_dbf.c
drivers/s390/scsi/zfcp_dbf.h
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fsf.h
drivers/s390/scsi/zfcp_reqlist.h
drivers/s390/scsi/zfcp_scsi.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/sg.c
drivers/ssb/pci.c
drivers/staging/comedi/drivers/ni_mio_common.c
drivers/target/target_core_user.c
drivers/thermal/thermal_hwmon.c
drivers/tty/serial/sc16is7xx.c
drivers/tty/vt/keyboard.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/hub.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/function/f_uac2.c
drivers/usb/gadget/function/uvc_video.c
drivers/usb/host/uhci-pci.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/option.c
drivers/xen/gntdev.c
fs/block_dev.c
fs/btrfs/async-thread.c
fs/btrfs/async-thread.h
fs/btrfs/ctree.h
fs/btrfs/delayed-inode.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/relocation.c
fs/btrfs/tree-log.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/connect.c
fs/cifs/smb2file.c
fs/cifs/smb2pdu.c
fs/cifs/smb2proto.h
fs/exec.c
fs/ext4/ext4_jbd2.h
fs/ext4/inline.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/super.c
fs/f2fs/debug.c
fs/nfs/file.c
fs/xfs/xfs_log_recover.c
include/linux/capability.h
include/linux/compiler-gcc.h
include/linux/cpu.h
include/linux/mm_types.h
include/linux/pci.h
include/linux/ptrace.h
include/linux/sched.h
include/linux/uio.h
include/net/cfg80211.h
include/net/fib_rules.h
include/net/ip6_route.h
include/net/route.h
include/net/sock.h
include/rdma/ib_addr.h
include/trace/events/net.h
include/trace/events/sched.h
include/uapi/linux/can.h
include/uapi/linux/fib_rules.h
include/uapi/linux/rtnetlink.h
kernel/capability.c
kernel/cpu.c
kernel/debug/debug_core.c
kernel/fork.c
kernel/locking/rtmutex.c
kernel/locking/rtmutex_common.h
kernel/ptrace.c
kernel/rcu/tree_plugin.h
kernel/sched/walt.c
kernel/time/timekeeping.c
kernel/trace/trace_functions_graph.c
kernel/watchdog.c
mm/init-mm.c
mm/kasan/kasan.h
mm/vmscan.c
net/batman-adv/translation-table.c
net/can/raw.c
net/ceph/messenger.c
net/core/fib_rules.c
net/core/net_namespace.c
net/core/rtnetlink.c
net/core/sock.c
net/dccp/ipv4.c
net/ipv4/esp4.c
net/ipv4/icmp.c
net/ipv4/inet_connection_sock.c
net/ipv4/ip_output.c
net/ipv4/ping.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/syncookies.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv6/af_inet6.c
net/ipv6/ah6.c
net/ipv6/datagram.c
net/ipv6/esp6.c
net/ipv6/icmp.c
net/ipv6/inet6_connection_sock.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/ipcomp6.c
net/ipv6/netfilter.c
net/ipv6/output_core.c
net/ipv6/ping.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/syncookies.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/l2tp/l2tp_ip.c
net/l2tp/l2tp_ip6.c
net/mac80211/mlme.c
net/netlink/af_netlink.c
net/netlink/af_netlink.h
net/packet/af_packet.c
net/sched/act_pedit.c
net/sched/cls_basic.c
net/sched/cls_bpf.c
net/sched/cls_cgroup.c
net/sched/cls_flow.c
net/sched/cls_flower.c
net/sched/cls_rsvp.h
net/sched/cls_tcindex.c
net/socket.c
net/unix/af_unix.c
net/wireless/core.h
net/wireless/mlme.c
net/wireless/sme.c
scripts/kconfig/nconf.gui.c
sound/core/pcm_lib.c
sound/pci/hda/hda_auto_parser.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/usb/hiface/pcm.c
sound/usb/mixer.c

index 092ee9fbaf2bdc15868475267e5875727a62841f..df8ab4fc240a0c0d98d363c05f9120d9a894b306 100644 (file)
@@ -1991,6 +1991,7 @@ registers, find a list below:
   PPC   | KVM_REG_PPC_TM_VSCR           | 32
   PPC   | KVM_REG_PPC_TM_DSCR           | 64
   PPC   | KVM_REG_PPC_TM_TAR            | 64
+  PPC   | KVM_REG_PPC_TM_XER            | 64
         |                               |
   MIPS  | KVM_REG_MIPS_R0               | 64
           ...
index 39720eeb3d009e81d64fd02dcf92179872729e06..015695919fc01858a58f6291ec32f25be0ad2604 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 4
-SUBLEVEL = 36
+SUBLEVEL = 41
 EXTRAVERSION =
 NAME = Blurry Fish Butt
 
index 8531a7a79e336d534ecb9fc05d6f952e6d9ce94b..f10371a981b7746515de1ddec67aa56c0e89b486 100644 (file)
@@ -139,7 +139,11 @@ CONFIG_PPP_DEFLATE=y
 CONFIG_PPP_MPPE=y
 CONFIG_PREEMPT=y
 CONFIG_PROFILING=y
+CONFIG_QFMT_V2=y
 CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QUOTA_TREE=y
+CONFIG_QUOTACTL=y
 CONFIG_RANDOMIZE_BASE=y
 CONFIG_RTC_CLASS=y
 CONFIG_RT_GROUP_SCHED=y
index fbe3587c4f36f1add284667fd8a04edbe90ea2ef..56aeb5efe6042329bd6d27cf54faaa6cb9f16334 100644 (file)
@@ -85,6 +85,10 @@ void flush_anon_page(struct vm_area_struct *vma,
  */
 #define PG_dc_clean    PG_arch_1
 
+#define CACHE_COLORS_NUM       4
+#define CACHE_COLORS_MSK       (CACHE_COLORS_NUM - 1)
+#define CACHE_COLOR(addr)      (((unsigned long)(addr) >> (PAGE_SHIFT)) & CACHE_COLORS_MSK)
+
 /*
  * Simple wrapper over config option
  * Bootup code ensures that hardware matches kernel configuration
@@ -94,8 +98,6 @@ static inline int cache_is_vipt_aliasing(void)
        return IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING);
 }
 
-#define CACHE_COLOR(addr)      (((unsigned long)(addr) >> (PAGE_SHIFT)) & 1)
-
 /*
  * checks if two addresses (after page aligning) index into same cache set
  */
index 08e7e2a16ac176a597ceb21c3b0f399b6ad98ea6..a36e8601114d2ca2970f257f9f8d7e5c03ec08a2 100644 (file)
 static inline void __delay(unsigned long loops)
 {
        __asm__ __volatile__(
-       "       lp  1f  \n"
-       "       nop     \n"
-       "1:             \n"
-       : "+l"(loops));
+       "       mov lp_count, %0        \n"
+       "       lp  1f                  \n"
+       "       nop                     \n"
+       "1:                             \n"
+       : : "r"(loops));
 }
 
 extern void __bad_udelay(void);
index aaf1e2d1d9003c01b7040a611488dcb9d24d3d3e..d81b6d7e11e79d64b34de28acc798ceaf6a2d1b5 100644 (file)
@@ -960,11 +960,16 @@ void arc_cache_init(void)
                /* check for D-Cache aliasing on ARCompact: ARCv2 has PIPT */
                if (is_isa_arcompact()) {
                        int handled = IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING);
-
-                       if (dc->alias && !handled)
-                               panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
-                       else if (!dc->alias && handled)
+                       int num_colors = dc->sz_k/dc->assoc/TO_KB(PAGE_SIZE);
+
+                       if (dc->alias) {
+                               if (!handled)
+                                       panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
+                               if (CACHE_COLORS_NUM != num_colors)
+                                       panic("CACHE_COLORS_NUM not optimized for config\n");
+                       } else if (!dc->alias && handled) {
                                panic("Disable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
+                       }
                }
        }
 
index 35a90af941a4fbb9193cba380f3ab4ed89d659e3..49e7bbd5825a715f9a8a097be5d1eed8295c9600 100644 (file)
@@ -48,6 +48,7 @@ CONFIG_UNIX=y
 CONFIG_XFRM_USER=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
+CONFIG_INET_DIAG_DESTROY=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_ADVANCED_ROUTER=y
 CONFIG_IP_MULTIPLE_TABLES=y
index fc7ea529f462de75149c31168f01f17a42908e76..52c8c1f642fe337c25c68c36651f05fc9988a856 100644 (file)
@@ -239,8 +239,7 @@ static int __init xen_guest_init(void)
         * for secondary CPUs as they are brought up.
         * For uniformity we use VCPUOP_register_vcpu_info even on cpu0.
         */
-       xen_vcpu_info = __alloc_percpu(sizeof(struct vcpu_info),
-                                              sizeof(struct vcpu_info));
+       xen_vcpu_info = alloc_percpu(struct vcpu_info);
        if (xen_vcpu_info == NULL)
                return -ENOMEM;
 
index ab1cb1fc4e3d6c2891fd0381463020795bfb7b0e..d33041614206b5e8712c1f27c7419d55a5d8e295 100644 (file)
@@ -64,13 +64,13 @@ config DEBUG_SET_MODULE_RONX
 
 config DEBUG_RODATA
        bool "Make kernel text and rodata read-only"
+       default y
        help
          If this is set, kernel text and rodata will be made read-only. This
          is to help catch accidental or malicious attempts to change the
-         kernel's executable code. Additionally splits rodata from kernel
-         text so it can be made explicitly non-executable.
+         kernel's executable code.
 
-          If in doubt, say Y
+         If in doubt, say Y
 
 config DEBUG_ALIGN_RODATA
        depends on DEBUG_RODATA
index 00eb346e0928cf2531b6910e4a16c98dbb0a77e5..fc55008d8c4c9777be3abaa52d9f7db3af575a42 100644 (file)
@@ -50,6 +50,7 @@ CONFIG_UNIX=y
 CONFIG_XFRM_USER=y
 CONFIG_NET_KEY=y
 CONFIG_INET=y
+CONFIG_INET_DIAG_DESTROY=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_ADVANCED_ROUTER=y
 CONFIG_IP_MULTIPLE_TABLES=y
index 46ee050ab747c16b1b3ec2c5ba5ee34d0e516f0c..8e1f826caf992966c18ed9c696ea95021a312e63 100644 (file)
@@ -81,7 +81,7 @@ struct arm64_cpu_capabilities {
        const char *desc;
        u16 capability;
        bool (*matches)(const struct arm64_cpu_capabilities *);
-       void (*enable)(void *);         /* Called on all active CPUs */
+       int (*enable)(void *);          /* Called on all active CPUs */
        union {
                struct {        /* To be used for erratum handling only */
                        u32 midr_model;
index cef1cf398356f1f61ceea854fc564f6df1d316cc..4be934fde40906cac5d3b6e6f2c34ea8f35d695a 100644 (file)
@@ -190,7 +190,7 @@ static inline void spin_lock_prefetch(const void *ptr)
 
 #endif
 
-void cpu_enable_pan(void *__unused);
-void cpu_enable_uao(void *__unused);
+int cpu_enable_pan(void *__unused);
+int cpu_enable_uao(void *__unused);
 
 #endif /* __ASM_PROCESSOR_H */
index a0c41dae0d8118d5b9c888299cad0895f0ac9036..cdf1dca6413385f7ac2bbaa1faeff8198b8d4d92 100644 (file)
@@ -19,7 +19,9 @@
 #define pr_fmt(fmt) "CPU features: " fmt
 
 #include <linux/bsearch.h>
+#include <linux/cpumask.h>
 #include <linux/sort.h>
+#include <linux/stop_machine.h>
 #include <linux/types.h>
 #include <asm/cpu.h>
 #include <asm/cpufeature.h>
@@ -824,7 +826,13 @@ enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
 
        for (i = 0; caps[i].matches; i++)
                if (caps[i].enable && cpus_have_cap(caps[i].capability))
-                       on_each_cpu(caps[i].enable, NULL, true);
+                       /*
+                        * Use stop_machine() as it schedules the work allowing
+                        * us to modify PSTATE, instead of on_each_cpu() which
+                        * uses an IPI, giving us a PSTATE that disappears when
+                        * we return.
+                        */
+                       stop_machine(caps[i].enable, NULL, cpu_online_mask);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
index b616e365cee33fdb2e61520943e2d8a9ae372861..5a0b1088c17c0fa0d9998ee03a67791d111b2e75 100644 (file)
@@ -1,7 +1,9 @@
 #include <linux/ftrace.h>
 #include <linux/percpu.h>
 #include <linux/slab.h>
+#include <asm/alternative.h>
 #include <asm/cacheflush.h>
+#include <asm/cpufeature.h>
 #include <asm/debug-monitors.h>
 #include <asm/pgtable.h>
 #include <asm/memory.h>
@@ -88,11 +90,16 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
                ret = fn(arg);
 
                /*
-                * Never gets here, unless the suspend finisher fails.
-                * Successful cpu_suspend() should return from cpu_resume(),
-                * returning through this code path is considered an error
-                * If the return value is set to 0 force ret = -EOPNOTSUPP
-                * to make sure a proper error condition is propagated
+                * PSTATE was not saved over suspend/resume, re-enable any
+                * detected features that might not have been set correctly.
+                */
+               asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,
+                               CONFIG_ARM64_PAN));
+
+               /*
+                * Restore HW breakpoint registers to sane values
+                * before debug exceptions are possibly reenabled
+                * through local_dbg_restore.
                 */
                if (!ret)
                        ret = -EOPNOTSUPP;
index 7e4423d22d2823e68a4f12f85fc12b297ae2f867..25547993a5ea66e188afdc5680238d1c15d492ff 100644 (file)
@@ -29,7 +29,9 @@
 #include <linux/sched.h>
 #include <linux/highmem.h>
 #include <linux/perf_event.h>
+#include <linux/preempt.h>
 
+#include <asm/bug.h>
 #include <asm/cpufeature.h>
 #include <asm/exception.h>
 #include <asm/debug-monitors.h>
@@ -660,9 +662,17 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
 NOKPROBE_SYMBOL(do_debug_exception);
 
 #ifdef CONFIG_ARM64_PAN
-void cpu_enable_pan(void *__unused)
+int cpu_enable_pan(void *__unused)
 {
+       /*
+        * We modify PSTATE. This won't work from irq context as the PSTATE
+        * is discarded once we return from the exception.
+        */
+       WARN_ON_ONCE(in_interrupt());
+
        config_sctlr_el1(SCTLR_EL1_SPAN, 0);
+       asm(SET_PSTATE_PAN(1));
+       return 0;
 }
 #endif /* CONFIG_ARM64_PAN */
 
@@ -673,8 +683,9 @@ void cpu_enable_pan(void *__unused)
  * We need to enable the feature at runtime (instead of adding it to
  * PSR_MODE_EL1h) as the feature may not be implemented by the cpu.
  */
-void cpu_enable_uao(void *__unused)
+int cpu_enable_uao(void *__unused)
 {
        asm(SET_PSTATE_UAO(1));
+       return 0;
 }
 #endif /* CONFIG_ARM64_UAO */
index d28fa8fe26fece499884fe1c7530ca0ad5dd9af4..c598d847d56b214a653dfa09924471206e44f123 100644 (file)
@@ -114,6 +114,6 @@ static inline void __udelay(unsigned long usecs)
  */
 #define        HZSCALE         (268435456 / (1000000 / HZ))
 
-#define ndelay(n) __delay(DIV_ROUND_UP((n) * ((((HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6), 1000));
+#define ndelay(n) __delay(DIV_ROUND_UP((n) * ((((HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6), 1000))
 
 #endif /* defined(_M68K_DELAY_H) */
index c2c43f71468498828f924ebc54b9aa3f189ba95e..3a4ed9f91d5727a5293780967411328ae8cc6310 100644 (file)
@@ -65,9 +65,9 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
                unsigned long flags;                            \
                spin_lock_irqsave(&pa_tlb_lock, flags);         \
                old_pte = *ptep;                                \
-               set_pte(ptep, pteval);                          \
                if (pte_inserted(old_pte))                      \
                        purge_tlb_entries(mm, addr);            \
+               set_pte(ptep, pteval);                          \
                spin_unlock_irqrestore(&pa_tlb_lock, flags);    \
        } while (0)
 
@@ -478,8 +478,8 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned
                spin_unlock_irqrestore(&pa_tlb_lock, flags);
                return 0;
        }
-       set_pte(ptep, pte_mkold(pte));
        purge_tlb_entries(vma->vm_mm, addr);
+       set_pte(ptep, pte_mkold(pte));
        spin_unlock_irqrestore(&pa_tlb_lock, flags);
        return 1;
 }
@@ -492,9 +492,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
 
        spin_lock_irqsave(&pa_tlb_lock, flags);
        old_pte = *ptep;
-       set_pte(ptep, __pte(0));
        if (pte_inserted(old_pte))
                purge_tlb_entries(mm, addr);
+       set_pte(ptep, __pte(0));
        spin_unlock_irqrestore(&pa_tlb_lock, flags);
 
        return old_pte;
@@ -504,8 +504,8 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
 {
        unsigned long flags;
        spin_lock_irqsave(&pa_tlb_lock, flags);
-       set_pte(ptep, pte_wrprotect(*ptep));
        purge_tlb_entries(mm, addr);
+       set_pte(ptep, pte_wrprotect(*ptep));
        spin_unlock_irqrestore(&pa_tlb_lock, flags);
 }
 
index fd5979f28ada3bdf272621e8a41ad99208386f9b..6857a104b2f9b975034bc61f934178f700b3a0d4 100644 (file)
@@ -375,6 +375,15 @@ void __init parisc_setup_cache_timing(void)
 
        /* calculate TLB flush threshold */
 
+       /* On SMP machines, skip the TLB measure of kernel text which
+        * has been mapped as huge pages. */
+       if (num_online_cpus() > 1 && !parisc_requires_coherency()) {
+               threshold = max(cache_info.it_size, cache_info.dt_size);
+               threshold *= PAGE_SIZE;
+               threshold /= num_online_cpus();
+               goto set_tlb_threshold;
+       }
+
        alltime = mfctl(16);
        flush_tlb_all();
        alltime = mfctl(16) - alltime;
@@ -393,6 +402,8 @@ void __init parisc_setup_cache_timing(void)
                alltime, size, rangetime);
 
        threshold = PAGE_ALIGN(num_online_cpus() * size * alltime / rangetime);
+
+set_tlb_threshold:
        if (threshold)
                parisc_tlb_flush_threshold = threshold;
        printk(KERN_INFO "TLB flush threshold set to %lu KiB\n",
index 6755219192295cc366d2259d0fc8fe8ff88ab76d..a4761b7724060ac6e84a023e4453b85843a249ac 100644 (file)
@@ -886,19 +886,10 @@ ENTRY(flush_dcache_page_asm)
        fdc,m           r31(%r28)
        fdc,m           r31(%r28)
        fdc,m           r31(%r28)
-       cmpb,COND(<<)           %r28, %r25,1b
+       cmpb,COND(<<)   %r28, %r25,1b
        fdc,m           r31(%r28)
 
        sync
-
-#ifdef CONFIG_PA20
-       pdtlb,l         %r0(%r25)
-#else
-       tlb_lock        %r20,%r21,%r22
-       pdtlb           %r0(%r25)
-       tlb_unlock      %r20,%r21,%r22
-#endif
-
        bv              %r0(%r2)
        nop
        .exit
@@ -973,17 +964,6 @@ ENTRY(flush_icache_page_asm)
        fic,m           %r31(%sr4,%r28)
 
        sync
-
-#ifdef CONFIG_PA20
-       pdtlb,l         %r0(%r28)
-       pitlb,l         %r0(%sr4,%r25)
-#else
-       tlb_lock        %r20,%r21,%r22
-       pdtlb           %r0(%r28)
-       pitlb           %r0(%sr4,%r25)
-       tlb_unlock      %r20,%r21,%r22
-#endif
-
        bv              %r0(%r2)
        nop
        .exit
index b6fcbaf5027bedc23c6da663b79453b08f5be4f2..3dc44b05fb9724a9d2761233c6d4bad54c6258cc 100644 (file)
@@ -57,11 +57,6 @@ __system_reset_overlay:
        bctr
 
 1:
-       /* Save the value at addr zero for a null pointer write check later. */
-
-       li      r4, 0
-       lwz     r3, 0(r4)
-
        /* Primary delays then goes to _zimage_start in wrapper. */
 
        or      31, 31, 31 /* db16cyc */
index 4ec2d86d3c50571a2a62f27c31f00739595ed219..a05558a7e51ad3b2698e8cf6f1acb8922ff5bfa0 100644 (file)
@@ -119,13 +119,12 @@ void ps3_copy_vectors(void)
        flush_cache((void *)0x100, 512);
 }
 
-void platform_init(unsigned long null_check)
+void platform_init(void)
 {
        const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
        void *chosen;
        unsigned long ft_addr;
        u64 rm_size;
-       unsigned long val;
 
        console_ops.write = ps3_console_write;
        platform_ops.exit = ps3_exit;
@@ -153,11 +152,6 @@ void platform_init(unsigned long null_check)
 
        printf(" flat tree at 0x%lx\n\r", ft_addr);
 
-       val = *(unsigned long *)0;
-
-       if (val != null_check)
-               printf("null check failed: %lx != %lx\n\r", val, null_check);
-
        ((kernel_entry_t)0)(ft_addr, 0, NULL);
 
        ps3_exit();
index cfa758c6b4f6b639c686026966d73a4b4dcaff3b..a92d95aee42dd81743b99fa3d36ce0abcf6b9f57 100644 (file)
@@ -545,6 +545,7 @@ struct kvm_vcpu_arch {
        u64 tfiar;
 
        u32 cr_tm;
+       u64 xer_tm;
        u64 lr_tm;
        u64 ctr_tm;
        u64 amr_tm;
index ab4d4732c492ebc4dd9514733cbb8461af0dbf87..720b71a636c851739adc2e88a4fc2de024ecf7b8 100644 (file)
@@ -587,6 +587,7 @@ struct kvm_get_htab_header {
 #define KVM_REG_PPC_TM_VSCR    (KVM_REG_PPC_TM | KVM_REG_SIZE_U32 | 0x67)
 #define KVM_REG_PPC_TM_DSCR    (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x68)
 #define KVM_REG_PPC_TM_TAR     (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x69)
+#define KVM_REG_PPC_TM_XER     (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x6a)
 
 /* PPC64 eXternal Interrupt Controller Specification */
 #define KVM_DEV_XICS_GRP_SOURCES       1       /* 64-bit source attributes */
index 221d584d089f9418abfa1087cffd9d0b0117c090..40da69163d5141c0c00812fac2bc82bbe6f482fb 100644 (file)
@@ -584,6 +584,7 @@ int main(void)
        DEFINE(VCPU_VRS_TM, offsetof(struct kvm_vcpu, arch.vr_tm.vr));
        DEFINE(VCPU_VRSAVE_TM, offsetof(struct kvm_vcpu, arch.vrsave_tm));
        DEFINE(VCPU_CR_TM, offsetof(struct kvm_vcpu, arch.cr_tm));
+       DEFINE(VCPU_XER_TM, offsetof(struct kvm_vcpu, arch.xer_tm));
        DEFINE(VCPU_LR_TM, offsetof(struct kvm_vcpu, arch.lr_tm));
        DEFINE(VCPU_CTR_TM, offsetof(struct kvm_vcpu, arch.ctr_tm));
        DEFINE(VCPU_AMR_TM, offsetof(struct kvm_vcpu, arch.amr_tm));
index c07bfb52275e27e307356cf58e48e0ed0db27c72..300382e5a2cc41978163449d33f6fdccf9613e6d 100644 (file)
@@ -612,8 +612,10 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
 
        /* Clear frozen state */
        rc = eeh_clear_pe_frozen_state(pe, false);
-       if (rc)
+       if (rc) {
+               pci_unlock_rescan_remove();
                return rc;
+       }
 
        /* Give the system 5 seconds to finish running the user-space
         * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes,
index 112ccf4975620f899a4747c98a13cd09260b5598..73f638789a38a520fea98819023b36f1da20b1c1 100644 (file)
@@ -44,7 +44,7 @@
        std     r0,0(r1);                                       \
        ptesync;                                                \
        ld      r0,0(r1);                                       \
-1:     cmp     cr0,r0,r0;                                      \
+1:     cmpd    cr0,r0,r0;                                      \
        bne     1b;                                             \
        IDLE_INST;                                              \
        b       .
index a7352b59e6f9b5c74f37556e6858c9ac9c5bb30b..3c3a367b6e59d609d63880f87eab399be749f371 100644 (file)
@@ -1186,6 +1186,9 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
        case KVM_REG_PPC_TM_CR:
                *val = get_reg_val(id, vcpu->arch.cr_tm);
                break;
+       case KVM_REG_PPC_TM_XER:
+               *val = get_reg_val(id, vcpu->arch.xer_tm);
+               break;
        case KVM_REG_PPC_TM_LR:
                *val = get_reg_val(id, vcpu->arch.lr_tm);
                break;
@@ -1393,6 +1396,9 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
        case KVM_REG_PPC_TM_CR:
                vcpu->arch.cr_tm = set_reg_val(id, *val);
                break;
+       case KVM_REG_PPC_TM_XER:
+               vcpu->arch.xer_tm = set_reg_val(id, *val);
+               break;
        case KVM_REG_PPC_TM_LR:
                vcpu->arch.lr_tm = set_reg_val(id, *val);
                break;
index 91700518bbf30491be41c8feebeb0d9df1329529..d509ff5c87b01c9ac0c8f64a6248325b4651fcd9 100644 (file)
@@ -653,6 +653,8 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
                                              HPTE_V_ABSENT);
                        do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags),
                                  true);
+                       /* Don't lose R/C bit updates done by hardware */
+                       r |= be64_to_cpu(hpte[1]) & (HPTE_R_R | HPTE_R_C);
                        hpte[1] = cpu_to_be64(r);
                }
        }
index 974f73df00bbf1533458ad3e713cacd5349c78fb..1a743f87b37d08849e552a4040dbb7fc2e4e6005 100644 (file)
@@ -2514,11 +2514,13 @@ kvmppc_save_tm:
        mfctr   r7
        mfspr   r8, SPRN_AMR
        mfspr   r10, SPRN_TAR
+       mfxer   r11
        std     r5, VCPU_LR_TM(r9)
        stw     r6, VCPU_CR_TM(r9)
        std     r7, VCPU_CTR_TM(r9)
        std     r8, VCPU_AMR_TM(r9)
        std     r10, VCPU_TAR_TM(r9)
+       std     r11, VCPU_XER_TM(r9)
 
        /* Restore r12 as trap number. */
        lwz     r12, VCPU_TRAP(r9)
@@ -2611,11 +2613,13 @@ kvmppc_restore_tm:
        ld      r7, VCPU_CTR_TM(r4)
        ld      r8, VCPU_AMR_TM(r4)
        ld      r9, VCPU_TAR_TM(r4)
+       ld      r10, VCPU_XER_TM(r4)
        mtlr    r5
        mtcr    r6
        mtctr   r7
        mtspr   SPRN_AMR, r8
        mtspr   SPRN_TAR, r9
+       mtxer   r10
 
        /*
         * Load up PPR and DSCR values but don't put them in the actual SPRs
index c3c12efe0bc004053fea6b49c2f34e51e1ffc32f..9c0c8fd0b2922cacd2ad6ad81f3238a707286d69 100644 (file)
@@ -89,7 +89,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
        sf = (struct signal_frame __user *) regs->u_regs[UREG_FP];
 
        /* 1. Make sure we are not getting garbage from the user */
-       if (!invalid_frame_pointer(sf, sizeof(*sf)))
+       if (invalid_frame_pointer(sf, sizeof(*sf)))
                goto segv_and_exit;
 
        if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
@@ -150,7 +150,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
 
        synchronize_user_stack();
        sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP];
-       if (!invalid_frame_pointer(sf, sizeof(*sf)))
+       if (invalid_frame_pointer(sf, sizeof(*sf)))
                goto segv;
 
        if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
index a5331c336b2a9ffd9fa96908a22a1cbc7e34ca67..3d3414c14792ab192d84b8a19600b1d3580fd0ae 100644 (file)
@@ -800,8 +800,10 @@ struct mdesc_mblock {
 };
 static struct mdesc_mblock *mblocks;
 static int num_mblocks;
+static int find_numa_node_for_addr(unsigned long pa,
+                                  struct node_mem_mask *pnode_mask);
 
-static unsigned long ra_to_pa(unsigned long addr)
+static unsigned long __init ra_to_pa(unsigned long addr)
 {
        int i;
 
@@ -817,8 +819,11 @@ static unsigned long ra_to_pa(unsigned long addr)
        return addr;
 }
 
-static int find_node(unsigned long addr)
+static int __init find_node(unsigned long addr)
 {
+       static bool search_mdesc = true;
+       static struct node_mem_mask last_mem_mask = { ~0UL, ~0UL };
+       static int last_index;
        int i;
 
        addr = ra_to_pa(addr);
@@ -828,13 +833,30 @@ static int find_node(unsigned long addr)
                if ((addr & p->mask) == p->val)
                        return i;
        }
-       /* The following condition has been observed on LDOM guests.*/
-       WARN_ONCE(1, "find_node: A physical address doesn't match a NUMA node"
-               " rule. Some physical memory will be owned by node 0.");
-       return 0;
+       /* The following condition has been observed on LDOM guests because
+        * node_masks only contains the best latency mask and value.
+        * LDOM guest's mdesc can contain a single latency group to
+        * cover multiple address range. Print warning message only if the
+        * address cannot be found in node_masks nor mdesc.
+        */
+       if ((search_mdesc) &&
+           ((addr & last_mem_mask.mask) != last_mem_mask.val)) {
+               /* find the available node in the mdesc */
+               last_index = find_numa_node_for_addr(addr, &last_mem_mask);
+               numadbg("find_node: latency group for address 0x%lx is %d\n",
+                       addr, last_index);
+               if ((last_index < 0) || (last_index >= num_node_masks)) {
+                       /* WARN_ONCE() and use default group 0 */
+                       WARN_ONCE(1, "find_node: A physical address doesn't match a NUMA node rule. Some physical memory will be owned by node 0.");
+                       search_mdesc = false;
+                       last_index = 0;
+               }
+       }
+
+       return last_index;
 }
 
-static u64 memblock_nid_range(u64 start, u64 end, int *nid)
+static u64 __init memblock_nid_range(u64 start, u64 end, int *nid)
 {
        *nid = find_node(start);
        start += PAGE_SIZE;
@@ -1158,6 +1180,41 @@ int __node_distance(int from, int to)
        return numa_latency[from][to];
 }
 
+static int find_numa_node_for_addr(unsigned long pa,
+                                  struct node_mem_mask *pnode_mask)
+{
+       struct mdesc_handle *md = mdesc_grab();
+       u64 node, arc;
+       int i = 0;
+
+       node = mdesc_node_by_name(md, MDESC_NODE_NULL, "latency-groups");
+       if (node == MDESC_NODE_NULL)
+               goto out;
+
+       mdesc_for_each_node_by_name(md, node, "group") {
+               mdesc_for_each_arc(arc, md, node, MDESC_ARC_TYPE_FWD) {
+                       u64 target = mdesc_arc_target(md, arc);
+                       struct mdesc_mlgroup *m = find_mlgroup(target);
+
+                       if (!m)
+                               continue;
+                       if ((pa & m->mask) == m->match) {
+                               if (pnode_mask) {
+                                       pnode_mask->mask = m->mask;
+                                       pnode_mask->val = m->match;
+                               }
+                               mdesc_release(md);
+                               return i;
+                       }
+               }
+               i++;
+       }
+
+out:
+       mdesc_release(md);
+       return -1;
+}
+
 static int find_best_numa_node_for_mlgroup(struct mdesc_mlgroup *grp)
 {
        int i;
index 0206eb8cfb61b982bd332c2713af6a1393eea179..65ed8c8f844440634ce3be1d02ef5c6af2452965 100644 (file)
@@ -89,7 +89,7 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_ESP=y
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
+CONFIG_INET_DIAG_DESTROY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
index dd389774bacb8234fa6cffbdde839ec13fc8bde4..d977bd91e390c87aa8d4297bada70506c0f93f9c 100644 (file)
@@ -87,7 +87,7 @@ CONFIG_SYN_COOKIES=y
 CONFIG_INET_ESP=y
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
+CONFIG_INET_DIAG_DESTROY=y
 CONFIG_IPV6_ROUTER_PREF=y
 CONFIG_IPV6_ROUTE_INFO=y
 CONFIG_IPV6_OPTIMISTIC_DAD=y
index f3b6d54e0042b7f08c25a82283f88e8193c70c4a..ae678ad128a94d2e945c15a85e9553bb1df9edd6 100644 (file)
@@ -766,8 +766,8 @@ ftrace_graph_call:
        jmp     ftrace_stub
 #endif
 
-.globl ftrace_stub
-ftrace_stub:
+/* This is weak to keep gas from relaxing the jumps */
+WEAK(ftrace_stub)
        ret
 END(ftrace_caller)
 
index a3aeb2cc361e90827b9c06d3cec228f6b714676c..1a8256dd6729afcc1ef6c7686b14c567463fa000 100644 (file)
@@ -67,7 +67,7 @@ u64 x86_perf_event_update(struct perf_event *event)
        int shift = 64 - x86_pmu.cntval_bits;
        u64 prev_raw_count, new_raw_count;
        int idx = hwc->idx;
-       s64 delta;
+       u64 delta;
 
        if (idx == INTEL_PMC_IDX_FIXED_BTS)
                return 0;
index 5f82cd59f0e5fcc1065837550e2da884bc3c8a19..5cc2242d77c6d187d5306d2b041f7bef32afbdfa 100644 (file)
@@ -3636,7 +3636,7 @@ __init int intel_pmu_init(void)
 
        /* Support full width counters using alternative MSR range */
        if (x86_pmu.intel_cap.full_width_write) {
-               x86_pmu.max_period = x86_pmu.cntval_mask;
+               x86_pmu.max_period = x86_pmu.cntval_mask >> 1;
                x86_pmu.perfctr = MSR_IA32_PMC0;
                pr_cont("full-width counters, ");
        }
index 6bc9ae24b6d2a74930701c0c6ea60fe090a3ebbc..8f1a3f443f7db8b8d381aa25da186615998281c9 100644 (file)
@@ -571,7 +571,7 @@ early_idt_handler_common:
        movl %eax,%ds
        movl %eax,%es
 
-       cmpl $(__KERNEL_CS),32(%esp)
+       cmpw $(__KERNEL_CS),32(%esp)
        jne 10f
 
        leal 28(%esp),%eax      # Pointer to %eip
index 268df707b5ce8f5d7739e3d23c7ab48f8085941a..bb620df05d0dca09fd07cc041935a834efe48dd9 100644 (file)
@@ -1247,10 +1247,10 @@ static inline bool nested_cpu_has_posted_intr(struct vmcs12 *vmcs12)
        return vmcs12->pin_based_vm_exec_control & PIN_BASED_POSTED_INTR;
 }
 
-static inline bool is_exception(u32 intr_info)
+static inline bool is_nmi(u32 intr_info)
 {
        return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK))
-               == (INTR_TYPE_HARD_EXCEPTION | INTR_INFO_VALID_MASK);
+               == (INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK);
 }
 
 static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
@@ -5234,7 +5234,7 @@ static int handle_exception(struct kvm_vcpu *vcpu)
        if (is_machine_check(intr_info))
                return handle_machine_check(vcpu);
 
-       if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR)
+       if (is_nmi(intr_info))
                return 1;  /* already handled by vmx_vcpu_run() */
 
        if (is_no_device(intr_info)) {
@@ -7722,7 +7722,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
 
        switch (exit_reason) {
        case EXIT_REASON_EXCEPTION_NMI:
-               if (!is_exception(intr_info))
+               if (is_nmi(intr_info))
                        return false;
                else if (is_page_fault(intr_info))
                        return enable_ept;
@@ -8329,8 +8329,7 @@ static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)
                kvm_machine_check();
 
        /* We need to handle NMIs before interrupts are enabled */
-       if ((exit_intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR &&
-           (exit_intr_info & INTR_INFO_VALID_MASK)) {
+       if (is_nmi(exit_intr_info)) {
                kvm_before_handle_nmi(&vmx->vcpu);
                asm("int $2");
                kvm_after_handle_nmi(&vmx->vcpu);
index f565e11f465aa145120973bce58ef7ecc192f349..69953bd97e6597f684803b5064662a13abb8c65b 100644 (file)
@@ -90,6 +90,9 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
        if (!iter || !iter->count)
                return -EINVAL;
 
+       if (!iter_is_iovec(iter))
+               return -EINVAL;
+
        iov_for_each(iov, i, *iter) {
                unsigned long uaddr = (unsigned long) iov.iov_base;
 
index c3e461ec40e4c9ceeb7b0595bf088957354ce752..9f99a01b00e8e51751be4ff0a44417cb9645e228 100644 (file)
@@ -1313,9 +1313,9 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
                blk_mq_put_ctx(data.ctx);
                if (!old_rq)
                        goto done;
-               if (!blk_mq_direct_issue_request(old_rq, &cookie))
-                       goto done;
-               blk_mq_insert_request(old_rq, false, true, true);
+               if (test_bit(BLK_MQ_S_STOPPED, &data.hctx->state) ||
+                   blk_mq_direct_issue_request(old_rq, &cookie) != 0)
+                       blk_mq_insert_request(old_rq, false, true, true);
                goto done;
        }
 
index d214e929ce1855bb653808f03482580b45b5344e..b9a53615bdef4945748057e5efbfef56c5cb4847 100644 (file)
@@ -655,6 +655,9 @@ bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 
        dprintk("%s: write %Zd bytes\n", bd->name, count);
 
+       if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
+               return -EINVAL;
+
        bsg_set_block(bd, file);
 
        bytes_written = 0;
index f7aba923458d3895b057ebdda6a4b39f1c385d02..82fbff180ad3599645cc1a02250fae4283fb9c1b 100644 (file)
@@ -33,6 +33,7 @@ obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
 
 $(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h
 $(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h
+$(obj)/rsa_helper.o: $(obj)/rsapubkey-asn1.h $(obj)/rsaprivkey-asn1.h
 clean-files += rsapubkey-asn1.c rsapubkey-asn1.h
 clean-files += rsaprivkey-asn1.c rsaprivkey-asn1.h
 
index fe5b495a434d3c1d5efc2e5b211c7d3863078726..a0ceb41d5cccc17e7f0932eca3f2dbaa71905865 100644 (file)
@@ -258,18 +258,22 @@ out_free_inst:
        goto out;
 }
 
-static inline void mcryptd_check_internal(struct rtattr **tb, u32 *type,
+static inline bool mcryptd_check_internal(struct rtattr **tb, u32 *type,
                                          u32 *mask)
 {
        struct crypto_attr_type *algt;
 
        algt = crypto_get_attr_type(tb);
        if (IS_ERR(algt))
-               return;
-       if ((algt->type & CRYPTO_ALG_INTERNAL))
-               *type |= CRYPTO_ALG_INTERNAL;
-       if ((algt->mask & CRYPTO_ALG_INTERNAL))
-               *mask |= CRYPTO_ALG_INTERNAL;
+               return false;
+
+       *type |= algt->type & CRYPTO_ALG_INTERNAL;
+       *mask |= algt->mask & CRYPTO_ALG_INTERNAL;
+
+       if (*type & *mask & CRYPTO_ALG_INTERNAL)
+               return true;
+       else
+               return false;
 }
 
 static int mcryptd_hash_init_tfm(struct crypto_tfm *tfm)
@@ -498,7 +502,8 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
        u32 mask = 0;
        int err;
 
-       mcryptd_check_internal(tb, &type, &mask);
+       if (!mcryptd_check_internal(tb, &type, &mask))
+               return -EINVAL;
 
        salg = shash_attr_alg(tb[1], type, mask);
        if (IS_ERR(salg))
index 80e55cb0827ba914751dca3140f2d04ca64ca6a6..b48ecbfc4498890be2de685f6a52bf27badb0904 100644 (file)
@@ -271,6 +271,26 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro12,1"),
                },
        },
+       {
+        /* https://bugzilla.redhat.com/show_bug.cgi?id=1123661 */
+        .callback = video_detect_force_native,
+        .ident = "Dell XPS 17 L702X",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+               DMI_MATCH(DMI_PRODUCT_NAME, "Dell System XPS L702X"),
+               },
+       },
+       {
+       /* https://bugzilla.redhat.com/show_bug.cgi?id=1204476 */
+       /* https://bugs.launchpad.net/ubuntu/+source/linux-lts-trusty/+bug/1416940 */
+       .callback = video_detect_force_native,
+       .ident = "HP Pavilion dv6",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6 Notebook PC"),
+               },
+       },
+
        { },
 };
 
index b7d56c5ea3c688fe03c7b5edda4f62c0906a9fc7..f18856f5954b8698462aafe15eeb45fff7d64df5 100644 (file)
@@ -836,11 +836,29 @@ static struct kobject *get_device_parent(struct device *dev,
        return NULL;
 }
 
+static inline bool live_in_glue_dir(struct kobject *kobj,
+                                   struct device *dev)
+{
+       if (!kobj || !dev->class ||
+           kobj->kset != &dev->class->p->glue_dirs)
+               return false;
+       return true;
+}
+
+static inline struct kobject *get_glue_dir(struct device *dev)
+{
+       return dev->kobj.parent;
+}
+
+/*
+ * make sure cleaning up dir as the last step, we need to make
+ * sure .release handler of kobject is run with holding the
+ * global lock
+ */
 static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
 {
        /* see if we live in a "glue" directory */
-       if (!glue_dir || !dev->class ||
-           glue_dir->kset != &dev->class->p->glue_dirs)
+       if (!live_in_glue_dir(glue_dir, dev))
                return;
 
        mutex_lock(&gdp_mutex);
@@ -848,11 +866,6 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
        mutex_unlock(&gdp_mutex);
 }
 
-static void cleanup_device_parent(struct device *dev)
-{
-       cleanup_glue_dir(dev, dev->kobj.parent);
-}
-
 static int device_add_class_symlinks(struct device *dev)
 {
        struct device_node *of_node = dev_of_node(dev);
@@ -1028,6 +1041,7 @@ int device_add(struct device *dev)
        struct kobject *kobj;
        struct class_interface *class_intf;
        int error = -EINVAL;
+       struct kobject *glue_dir = NULL;
 
        dev = get_device(dev);
        if (!dev)
@@ -1072,8 +1086,10 @@ int device_add(struct device *dev)
        /* first, register with generic layer. */
        /* we require the name to be set before, and pass NULL */
        error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
-       if (error)
+       if (error) {
+               glue_dir = get_glue_dir(dev);
                goto Error;
+       }
 
        /* notify platform of device entry */
        if (platform_notify)
@@ -1154,9 +1170,10 @@ done:
        device_remove_file(dev, &dev_attr_uevent);
  attrError:
        kobject_uevent(&dev->kobj, KOBJ_REMOVE);
+       glue_dir = get_glue_dir(dev);
        kobject_del(&dev->kobj);
  Error:
-       cleanup_device_parent(dev);
+       cleanup_glue_dir(dev, glue_dir);
        put_device(parent);
 name_error:
        kfree(dev->p);
@@ -1232,6 +1249,7 @@ EXPORT_SYMBOL_GPL(put_device);
 void device_del(struct device *dev)
 {
        struct device *parent = dev->parent;
+       struct kobject *glue_dir = NULL;
        struct class_interface *class_intf;
 
        /* Notify clients of device removal.  This call must come
@@ -1276,8 +1294,9 @@ void device_del(struct device *dev)
                blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                             BUS_NOTIFY_REMOVED_DEVICE, dev);
        kobject_uevent(&dev->kobj, KOBJ_REMOVE);
-       cleanup_device_parent(dev);
+       glue_dir = get_glue_dir(dev);
        kobject_del(&dev->kobj);
+       cleanup_glue_dir(dev, glue_dir);
        put_device(parent);
 }
 EXPORT_SYMBOL_GPL(device_del);
index 8524450e75bd15d8f97327af84662b4af32fc3a7..ccfd268148a8f5fc0ee0b2642d63267ef12a51aa 100644 (file)
@@ -942,13 +942,14 @@ static int _request_firmware_load(struct firmware_priv *fw_priv,
                timeout = MAX_JIFFY_OFFSET;
        }
 
-       retval = wait_for_completion_interruptible_timeout(&buf->completion,
+       timeout = wait_for_completion_interruptible_timeout(&buf->completion,
                        timeout);
-       if (retval == -ERESTARTSYS || !retval) {
+       if (timeout == -ERESTARTSYS || !timeout) {
+               retval = timeout;
                mutex_lock(&fw_lock);
                fw_load_abort(fw_priv);
                mutex_unlock(&fw_lock);
-       } else if (retval > 0) {
+       } else if (timeout > 0) {
                retval = 0;
        }
 
index 80cf8add46ff3667d896fca88aaea3fbf338ad27..ab0b2dd3f629baf33ff85c4288996fd79a9595b7 100644 (file)
@@ -1657,7 +1657,7 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
        blk_mq_start_request(bd->rq);
 
        if (lo->lo_state != Lo_bound)
-               return -EIO;
+               return BLK_MQ_RQ_QUEUE_ERROR;
 
        if (lo->use_dio && !(cmd->rq->cmd_flags & (REQ_FLUSH |
                                        REQ_DISCARD)))
index 370c2f76016d685820689f543ea96c1006230131..1648de80e230060cd399197c39f098d19767683f 100644 (file)
@@ -1368,7 +1368,8 @@ static ssize_t hot_remove_store(struct class *class,
        zram = idr_find(&zram_index_idr, dev_id);
        if (zram) {
                ret = zram_remove(zram);
-               idr_remove(&zram_index_idr, dev_id);
+               if (!ret)
+                       idr_remove(&zram_index_idr, dev_id);
        } else {
                ret = -ENODEV;
        }
@@ -1377,8 +1378,14 @@ static ssize_t hot_remove_store(struct class *class,
        return ret ? ret : count;
 }
 
+/*
+ * NOTE: hot_add attribute is not the usual read-only sysfs attribute. In a
+ * sense that reading from this file does alter the state of your system -- it
+ * creates a new un-initialized zram device and returns back this device's
+ * device_id (or an error code if it fails to create a new device).
+ */
 static struct class_attribute zram_control_class_attrs[] = {
-       __ATTR_RO(hot_add),
+       __ATTR(hot_add, 0400, hot_add_show, NULL),
        __ATTR_WO(hot_remove),
        __ATTR_NULL,
 };
index 3111f2778079dd49c0f8514d7852c06688a6c4f5..849f2e29c2436f86a3bbe81bfc025f0d1cea0036 100644 (file)
@@ -305,7 +305,6 @@ static int tpmfront_probe(struct xenbus_device *dev,
        rv = setup_ring(dev, priv);
        if (rv) {
                chip = dev_get_drvdata(&dev->dev);
-               tpm_chip_unregister(chip);
                ring_free(priv);
                return rv;
        }
index 6029313aa99586b3088de8ca82e66dd0e0752b70..35ab89fe9d7b126a436c992b5f98b15b21c06b4a 100644 (file)
@@ -1082,7 +1082,9 @@ static void bcm2835_pll_divider_off(struct clk_hw *hw)
        cprman_write(cprman, data->cm_reg,
                     (cprman_read(cprman, data->cm_reg) &
                      ~data->load_mask) | data->hold_mask);
-       cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE);
+       cprman_write(cprman, data->a2w_reg,
+                    cprman_read(cprman, data->a2w_reg) |
+                    A2W_PLL_CHANNEL_DISABLE);
        spin_unlock(&cprman->regs_lock);
 }
 
index 8831e1a05367ad9c7473e3ee723adc3f29dc9936..11d8aa3ec18604a7ce5c04ddded50ff660f554c1 100644 (file)
 
 #include "clock.h"
 
-/*
- * DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
- * that are sourced by DPLL5, and both of these require this clock
- * to be at 120 MHz for proper operation.
- */
-#define DPLL5_FREQ_FOR_USBHOST         120000000
-
 #define OMAP3430ES2_ST_DSS_IDLE_SHIFT                  1
 #define OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT             5
 #define OMAP3430ES2_ST_SSI_IDLE_SHIFT                  8
@@ -546,14 +539,21 @@ void __init omap3_clk_lock_dpll5(void)
        struct clk *dpll5_clk;
        struct clk *dpll5_m2_clk;
 
+       /*
+        * Errata sprz319f advisory 2.1 documents a USB host clock drift issue
+        * that can be worked around using specially crafted dpll5 settings
+        * with a dpll5_m2 divider set to 8. Set the dpll5 rate to 8x the USB
+        * host clock rate, its .set_rate handler() will detect that frequency
+        * and use the errata settings.
+        */
        dpll5_clk = clk_get(NULL, "dpll5_ck");
-       clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
+       clk_set_rate(dpll5_clk, OMAP3_DPLL5_FREQ_FOR_USBHOST * 8);
        clk_prepare_enable(dpll5_clk);
 
-       /* Program dpll5_m2_clk divider for no division */
+       /* Program dpll5_m2_clk divider */
        dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
        clk_prepare_enable(dpll5_m2_clk);
-       clk_set_rate(dpll5_m2_clk, DPLL5_FREQ_FOR_USBHOST);
+       clk_set_rate(dpll5_m2_clk, OMAP3_DPLL5_FREQ_FOR_USBHOST);
 
        clk_disable_unprepare(dpll5_m2_clk);
        clk_disable_unprepare(dpll5_clk);
index 90f3f472ae1c4c70e537c69a7a58e2d1168abddd..13c37f48d9d69d6f4b950671cc735b1ed49fefba 100644 (file)
@@ -257,11 +257,20 @@ long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
 unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
                                    unsigned long parent_rate);
 
+/*
+ * OMAP3_DPLL5_FREQ_FOR_USBHOST: USBHOST and USBTLL are the only clocks
+ * that are sourced by DPLL5, and both of these require this clock
+ * to be at 120 MHz for proper operation.
+ */
+#define OMAP3_DPLL5_FREQ_FOR_USBHOST   120000000
+
 unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
 int omap3_dpll4_set_rate(struct clk_hw *clk, unsigned long rate,
                         unsigned long parent_rate);
 int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
                                    unsigned long parent_rate, u8 index);
+int omap3_dpll5_set_rate(struct clk_hw *hw, unsigned long rate,
+                        unsigned long parent_rate);
 void omap3_clk_lock_dpll5(void);
 
 unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
index 5519b386edc02f74992620d99d8d32921523b5b0..f9a5089ddc79b783326c3a0efc36e0c3384cf7aa 100644 (file)
@@ -114,6 +114,18 @@ static const struct clk_ops omap3_dpll_ck_ops = {
        .round_rate     = &omap2_dpll_round_rate,
 };
 
+static const struct clk_ops omap3_dpll5_ck_ops = {
+       .enable         = &omap3_noncore_dpll_enable,
+       .disable        = &omap3_noncore_dpll_disable,
+       .get_parent     = &omap2_init_dpll_parent,
+       .recalc_rate    = &omap3_dpll_recalc,
+       .set_rate       = &omap3_dpll5_set_rate,
+       .set_parent     = &omap3_noncore_dpll_set_parent,
+       .set_rate_and_parent    = &omap3_noncore_dpll_set_rate_and_parent,
+       .determine_rate = &omap3_noncore_dpll_determine_rate,
+       .round_rate     = &omap2_dpll_round_rate,
+};
+
 static const struct clk_ops omap3_dpll_per_ck_ops = {
        .enable         = &omap3_noncore_dpll_enable,
        .disable        = &omap3_noncore_dpll_disable,
@@ -461,7 +473,12 @@ static void __init of_ti_omap3_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd);
+       if ((of_machine_is_compatible("ti,omap3630") ||
+            of_machine_is_compatible("ti,omap36xx")) &&
+           !strcmp(node->name, "dpll5_ck"))
+               of_ti_dpll_setup(node, &omap3_dpll5_ck_ops, &dd);
+       else
+               of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock",
               of_ti_omap3_dpll_setup);
index f4dec00fb684f7743b0fcda3df6f245ac46b7b43..0e9119fae760288b0a62206b49a19c707526d050 100644 (file)
@@ -815,3 +815,70 @@ int omap3_dpll4_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
        return omap3_noncore_dpll_set_rate_and_parent(hw, rate, parent_rate,
                                                      index);
 }
+
+/* Apply DM3730 errata sprz319 advisory 2.1. */
+static bool omap3_dpll5_apply_errata(struct clk_hw *hw,
+                                    unsigned long parent_rate)
+{
+       struct omap3_dpll5_settings {
+               unsigned int rate, m, n;
+       };
+
+       static const struct omap3_dpll5_settings precomputed[] = {
+               /*
+                * From DM3730 errata advisory 2.1, table 35 and 36.
+                * The N value is increased by 1 compared to the tables as the
+                * errata lists register values while last_rounded_field is the
+                * real divider value.
+                */
+               { 12000000,  80,  0 + 1 },
+               { 13000000, 443,  5 + 1 },
+               { 19200000,  50,  0 + 1 },
+               { 26000000, 443, 11 + 1 },
+               { 38400000,  25,  0 + 1 }
+       };
+
+       const struct omap3_dpll5_settings *d;
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       struct dpll_data *dd;
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(precomputed); ++i) {
+               if (parent_rate == precomputed[i].rate)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(precomputed))
+               return false;
+
+       d = &precomputed[i];
+
+       /* Update the M, N and rounded rate values and program the DPLL. */
+       dd = clk->dpll_data;
+       dd->last_rounded_m = d->m;
+       dd->last_rounded_n = d->n;
+       dd->last_rounded_rate = div_u64((u64)parent_rate * d->m, d->n);
+       omap3_noncore_dpll_program(clk, 0);
+
+       return true;
+}
+
+/**
+ * omap3_dpll5_set_rate - set rate for omap3 dpll5
+ * @hw: clock to change
+ * @rate: target rate for clock
+ * @parent_rate: rate of the parent clock
+ *
+ * Set rate for the DPLL5 clock. Apply the sprz319 advisory 2.1 on OMAP36xx if
+ * the DPLL is used for USB host (detected through the requested rate).
+ */
+int omap3_dpll5_set_rate(struct clk_hw *hw, unsigned long rate,
+                        unsigned long parent_rate)
+{
+       if (rate == OMAP3_DPLL5_FREQ_FOR_USBHOST * 8) {
+               if (omap3_dpll5_apply_errata(hw, parent_rate))
+                       return 0;
+       }
+
+       return omap3_noncore_dpll_set_rate(hw, rate, parent_rate);
+}
index 2cde3796cb827c8370d95d848c2d4c659256b472..f3307fc38e7905e0edac3cb388e811e629f873f4 100644 (file)
@@ -702,7 +702,9 @@ copy_iv:
 
        /* Will read cryptlen */
        append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
-       aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2);
+       append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | KEY_VLF |
+                            FIFOLD_TYPE_MSG1OUT2 | FIFOLD_TYPE_LASTBOTH);
+       append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
 
        /* Write ICV */
        append_seq_store(desc, ctx->authsize, LDST_CLASS_2_CCB |
index 9e15d571b53c2bd759e1b0e6c0d0bda0795740a9..a76c35fc0b927f45782f25607032b7724dd62138 100644 (file)
@@ -203,7 +203,19 @@ void __init efi_init(void)
 
        reserve_regions();
        early_memunmap(memmap.map, params.mmap_size);
-       memblock_mark_nomap(params.mmap & PAGE_MASK,
-                           PAGE_ALIGN(params.mmap_size +
-                                      (params.mmap & ~PAGE_MASK)));
+
+       if (IS_ENABLED(CONFIG_ARM)) {
+               /*
+                * ARM currently does not allow ioremap_cache() to be called on
+                * memory regions that are covered by struct page. So remove the
+                * UEFI memory map from the linear mapping.
+                */
+               memblock_mark_nomap(params.mmap & PAGE_MASK,
+                                   PAGE_ALIGN(params.mmap_size +
+                                              (params.mmap & ~PAGE_MASK)));
+       } else {
+               memblock_reserve(params.mmap & PAGE_MASK,
+                                PAGE_ALIGN(params.mmap_size +
+                                           (params.mmap & ~PAGE_MASK)));
+       }
 }
index e0b4586a26fde79d7a9eb6dbc506c8cc11d85996..9b8f0b975ca6ce6dd711e080186c34e868088d9e 100644 (file)
@@ -223,7 +223,8 @@ static int ast_get_dram_info(struct drm_device *dev)
        ast_write32(ast, 0x10000, 0xfc600309);
 
        do {
-               ;
+               if (pci_channel_offline(dev->pdev))
+                       return -EIO;
        } while (ast_read32(ast, 0x10000) != 0x01);
        data = ast_read32(ast, 0x10004);
 
@@ -429,7 +430,9 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)
        ast_detect_chip(dev, &need_post);
 
        if (ast->chip != AST1180) {
-               ast_get_dram_info(dev);
+               ret = ast_get_dram_info(dev);
+               if (ret)
+                       goto out_free;
                ast->vram_size = ast_get_vram_info(dev);
                DRM_INFO("dram %d %d %d %08x\n", ast->mclk, ast->dram_type, ast->dram_bus_width, ast->vram_size);
        }
index 92e7e5795398e80a6ab46f51d3aad4d22a4e8346..db98ab5cde3d86f04603615013466281b9fd7e40 100644 (file)
@@ -484,6 +484,9 @@ static const struct file_operations psb_gem_fops = {
        .open = drm_open,
        .release = drm_release,
        .unlocked_ioctl = psb_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .mmap = drm_gem_mmap,
        .poll = drm_poll,
        .read = drm_read,
index 4dca65a63b9226fa17c64452feff876b8faebd45..af224fafa21f4655e5433084457684445a0d3103 100644 (file)
@@ -333,6 +333,9 @@ get_fp_strap(struct drm_device *dev, struct nvbios *bios)
        if (bios->major_version < 5 && bios->data[0x48] & 0x4)
                return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf;
 
+       if (drm->device.info.family >= NV_DEVICE_INFO_V0_MAXWELL)
+               return nvif_rd32(device, 0x001800) & 0x0000000f;
+       else
        if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
                return (nvif_rd32(device, NV_PEXTDEV_BOOT_0) >> 24) & 0xf;
        else
index bbc9824af6e037e01bfb60cae32d1a801e8b095f..ece9f4102c0e2cc5ca199cf853fb2706c9ede536 100644 (file)
@@ -1833,7 +1833,7 @@ nvf1_chipset = {
        .fb = gk104_fb_new,
        .fuse = gf100_fuse_new,
        .gpio = gk104_gpio_new,
-       .i2c = gf119_i2c_new,
+       .i2c = gk104_i2c_new,
        .ibus = gk104_ibus_new,
        .imem = nv50_instmem_new,
        .ltc = gk104_ltc_new,
@@ -1941,7 +1941,7 @@ nv117_chipset = {
        .fb = gm107_fb_new,
        .fuse = gm107_fuse_new,
        .gpio = gk104_gpio_new,
-       .i2c = gf119_i2c_new,
+       .i2c = gk104_i2c_new,
        .ibus = gk104_ibus_new,
        .imem = nv50_instmem_new,
        .ltc = gm107_ltc_new,
index e7cbc139c1d4fb831bdf7a1a47f649c45ce121a0..89976ff4b305e401a0e921128337166759695297 100644 (file)
@@ -59,6 +59,7 @@ gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
        struct nvkm_gpuobj *inst = chan->base.inst;
        int ret = 0;
 
+       mutex_lock(&subdev->mutex);
        nvkm_wr32(device, 0x002634, chan->base.chid);
        if (nvkm_msec(device, 2000,
                if (nvkm_rd32(device, 0x002634) == chan->base.chid)
@@ -66,10 +67,12 @@ gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
        ) < 0) {
                nvkm_error(subdev, "channel %d [%s] kick timeout\n",
                           chan->base.chid, chan->base.object.client->name);
-               ret = -EBUSY;
-               if (suspend)
-                       return ret;
+               ret = -ETIMEDOUT;
        }
+       mutex_unlock(&subdev->mutex);
+
+       if (ret && suspend)
+               return ret;
 
        if (offset) {
                nvkm_kmap(inst);
index 0b817540a9e4f7d62a50aacf0a38d0d06c447abe..aa1692e5669fc39361c232f3db2969b720ad6ae4 100644 (file)
@@ -39,7 +39,9 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
        struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
        struct nvkm_device *device = subdev->device;
        struct nvkm_client *client = chan->base.object.client;
+       int ret = 0;
 
+       mutex_lock(&subdev->mutex);
        nvkm_wr32(device, 0x002634, chan->base.chid);
        if (nvkm_msec(device, 2000,
                if (!(nvkm_rd32(device, 0x002634) & 0x00100000))
@@ -47,10 +49,10 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
        ) < 0) {
                nvkm_error(subdev, "channel %d [%s] kick timeout\n",
                           chan->base.chid, client->name);
-               return -EBUSY;
+               ret = -ETIMEDOUT;
        }
-
-       return 0;
+       mutex_unlock(&subdev->mutex);
+       return ret;
 }
 
 static u32
index 212800ecdce99e4eb1a3a23ebdab9c207cd860da..7d1d3c6b4b728dec4711a75883df4d700a1a6290 100644 (file)
@@ -12,6 +12,7 @@ struct nvbios_source {
        bool rw;
        bool ignore_checksum;
        bool no_pcir;
+       bool require_checksum;
 };
 
 int nvbios_extend(struct nvkm_bios *, u32 length);
index b2557e87afdd6d0e95910b3b4b91e37ce9a3e269..7deb81b6dbac6bc5a440da281eca94b51b632f83 100644 (file)
@@ -86,9 +86,12 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
                    nvbios_checksum(&bios->data[image.base], image.size)) {
                        nvkm_debug(subdev, "%08x: checksum failed\n",
                                   image.base);
-                       if (mthd->func->rw)
+                       if (!mthd->func->require_checksum) {
+                               if (mthd->func->rw)
+                                       score += 1;
                                score += 1;
-                       score += 1;
+                       } else
+                               return 0;
                } else {
                        score += 3;
                }
index 8fecb5ff22a0efaaeaed9bc2b4939072fc6513bc..06572f8ce9148805ca37470c978af17f42e72827 100644 (file)
@@ -99,6 +99,7 @@ nvbios_acpi_fast = {
        .init = acpi_init,
        .read = acpi_read_fast,
        .rw = false,
+       .require_checksum = true,
 };
 
 const struct nvbios_source
index 85b1464c01942013f22055be345d751636bc68cb..587c52f08d3f5803b60ca23cd3f2972d611ffed9 100644 (file)
@@ -47,8 +47,10 @@ nvkm_ltc_tags_clear(struct nvkm_ltc *ltc, u32 first, u32 count)
 
        BUG_ON((first > limit) || (limit >= ltc->num_tags));
 
+       mutex_lock(&ltc->subdev.mutex);
        ltc->func->cbc_clear(ltc, first, limit);
        ltc->func->cbc_wait(ltc);
+       mutex_unlock(&ltc->subdev.mutex);
 }
 
 int
index afaf346bd50e7c7628674e29d0eea14c8403e3ec..b5b9cb911111b1c18bb697bc512d7081d126fc48 100644 (file)
@@ -90,6 +90,9 @@ static void radeon_show_cursor(struct drm_crtc *crtc)
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct radeon_device *rdev = crtc->dev->dev_private;
 
+       if (radeon_crtc->cursor_out_of_bounds)
+               return;
+
        if (ASIC_IS_DCE4(rdev)) {
                WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
                       upper_32_bits(radeon_crtc->cursor_addr));
@@ -148,16 +151,17 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
                x += crtc->x;
                y += crtc->y;
        }
-       DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
 
-       if (x < 0) {
+       if (x < 0)
                xorigin = min(-x, radeon_crtc->max_cursor_width - 1);
-               x = 0;
-       }
-       if (y < 0) {
+       if (y < 0)
                yorigin = min(-y, radeon_crtc->max_cursor_height - 1);
-               y = 0;
+
+       if (!ASIC_IS_AVIVO(rdev)) {
+               x += crtc->x;
+               y += crtc->y;
        }
+       DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
 
        /* fixed on DCE6 and newer */
        if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
@@ -180,27 +184,31 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
                if (i > 1) {
                        int cursor_end, frame_end;
 
-                       cursor_end = x - xorigin + w;
+                       cursor_end = x + w;
                        frame_end = crtc->x + crtc->mode.crtc_hdisplay;
                        if (cursor_end >= frame_end) {
                                w = w - (cursor_end - frame_end);
                                if (!(frame_end & 0x7f))
                                        w--;
-                       } else {
-                               if (!(cursor_end & 0x7f))
-                                       w--;
+                       } else if (cursor_end <= 0) {
+                               goto out_of_bounds;
+                       } else if (!(cursor_end & 0x7f)) {
+                               w--;
                        }
                        if (w <= 0) {
-                               w = 1;
-                               cursor_end = x - xorigin + w;
-                               if (!(cursor_end & 0x7f)) {
-                                       x--;
-                                       WARN_ON_ONCE(x < 0);
-                               }
+                               goto out_of_bounds;
                        }
                }
        }
 
+       if (x <= (crtc->x - w) || y <= (crtc->y - radeon_crtc->cursor_height) ||
+           x >= (crtc->x + crtc->mode.crtc_hdisplay) ||
+           y >= (crtc->y + crtc->mode.crtc_vdisplay))
+               goto out_of_bounds;
+
+       x += xorigin;
+       y += yorigin;
+
        if (ASIC_IS_DCE4(rdev)) {
                WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y);
                WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
@@ -212,6 +220,9 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
                WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
                       ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
        } else {
+               x -= crtc->x;
+               y -= crtc->y;
+
                if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
                        y *= 2;
 
@@ -232,6 +243,19 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
        radeon_crtc->cursor_x = x;
        radeon_crtc->cursor_y = y;
 
+       if (radeon_crtc->cursor_out_of_bounds) {
+               radeon_crtc->cursor_out_of_bounds = false;
+               if (radeon_crtc->cursor_bo)
+                       radeon_show_cursor(crtc);
+       }
+
+       return 0;
+
+ out_of_bounds:
+       if (!radeon_crtc->cursor_out_of_bounds) {
+               radeon_hide_cursor(crtc);
+               radeon_crtc->cursor_out_of_bounds = true;
+       }
        return 0;
 }
 
@@ -297,22 +321,23 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
                return ret;
        }
 
-       radeon_crtc->cursor_width = width;
-       radeon_crtc->cursor_height = height;
-
        radeon_lock_cursor(crtc, true);
 
-       if (hot_x != radeon_crtc->cursor_hot_x ||
+       if (width != radeon_crtc->cursor_width ||
+           height != radeon_crtc->cursor_height ||
+           hot_x != radeon_crtc->cursor_hot_x ||
            hot_y != radeon_crtc->cursor_hot_y) {
                int x, y;
 
                x = radeon_crtc->cursor_x + radeon_crtc->cursor_hot_x - hot_x;
                y = radeon_crtc->cursor_y + radeon_crtc->cursor_hot_y - hot_y;
 
-               radeon_cursor_move_locked(crtc, x, y);
-
+               radeon_crtc->cursor_width = width;
+               radeon_crtc->cursor_height = height;
                radeon_crtc->cursor_hot_x = hot_x;
                radeon_crtc->cursor_hot_y = hot_y;
+
+               radeon_cursor_move_locked(crtc, x, y);
        }
 
        radeon_show_cursor(crtc);
index 7a0666ac4e235c3b6ff0795f592ec185f193a031..d8f8be608c19b5e19268e4592c3216b49222d2a6 100644 (file)
@@ -330,6 +330,7 @@ struct radeon_crtc {
        u16 lut_r[256], lut_g[256], lut_b[256];
        bool enabled;
        bool can_tile;
+       bool cursor_out_of_bounds;
        uint32_t crtc_offset;
        struct drm_gem_object *cursor_bo;
        uint64_t cursor_addr;
index 10191b935937c55ea125ace1a55d344bbe4bf146..eb2a2a49974f7ef18e00bb8e9c7078bcd3349e68 100644 (file)
@@ -3026,6 +3026,7 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
                    (rdev->pdev->revision == 0x80) ||
                    (rdev->pdev->revision == 0x81) ||
                    (rdev->pdev->revision == 0x83) ||
+                   (rdev->pdev->revision == 0x87) ||
                    (rdev->pdev->device == 0x6604) ||
                    (rdev->pdev->device == 0x6605)) {
                        max_sclk = 75000;
index 2281de122038e45a5c375f7d7669111ab2aee2de..8d84c563ba75351f053c223841c144e87afd80ec 100644 (file)
@@ -1745,7 +1745,7 @@ find_mad_agent(struct ib_mad_port_private *port_priv,
                        if (!class)
                                goto out;
                        if (convert_mgmt_class(mad_hdr->mgmt_class) >=
-                           IB_MGMT_MAX_METHODS)
+                           ARRAY_SIZE(class->method_table))
                                goto out;
                        method = class->method_table[convert_mgmt_class(
                                                        mad_hdr->mgmt_class)];
index 6aa648cb538139409e658d487102e3510f8489d5..2cd97977b988debeb92d11a2600dca9642d6fed9 100644 (file)
@@ -517,8 +517,11 @@ static void join_handler(int status, struct ib_sa_mcmember_rec *rec,
                process_join_error(group, status);
        else {
                int mgids_changed, is_mgid0;
-               ib_find_pkey(group->port->dev->device, group->port->port_num,
-                            be16_to_cpu(rec->pkey), &pkey_index);
+
+               if (ib_find_pkey(group->port->dev->device,
+                                group->port->port_num, be16_to_cpu(rec->pkey),
+                                &pkey_index))
+                       pkey_index = MCAST_INVALID_PKEY_INDEX;
 
                spin_lock_irq(&group->port->lock);
                if (group->state == MCAST_BUSY &&
index 87799de90a1debb6990f0bcb083a4f52c86a097c..8ec99bdea76b2de5a5a9f87cc4d26b78f4c80d2a 100644 (file)
@@ -563,8 +563,11 @@ void ipoib_mcast_join_task(struct work_struct *work)
        if (!test_bit(IPOIB_FLAG_OPER_UP, &priv->flags))
                return;
 
-       if (ib_query_port(priv->ca, priv->port, &port_attr) ||
-           port_attr.state != IB_PORT_ACTIVE) {
+       if (ib_query_port(priv->ca, priv->port, &port_attr)) {
+               ipoib_dbg(priv, "ib_query_port() failed\n");
+               return;
+       }
+       if (port_attr.state != IB_PORT_ACTIVE) {
                ipoib_dbg(priv, "port state is not ACTIVE (state = %d) suspending join task\n",
                          port_attr.state);
                return;
index 2adfd86c869a5364312a2d8df904d2bd7df68b52..930424e55439d411ec8059f011d198766c8efa46 100644 (file)
@@ -592,7 +592,6 @@ static int drv260x_probe(struct i2c_client *client,
        }
 
        haptics->input_dev->name = "drv260x:haptics";
-       haptics->input_dev->dev.parent = client->dev.parent;
        haptics->input_dev->close = drv260x_close;
        input_set_drvdata(haptics->input_dev, haptics);
        input_set_capability(haptics->input_dev, EV_FF, FF_RUMBLE);
index 6035794bc1f208809aa0175685a3a15f58fc2c7d..3d237a03dab3dbd2ead85526a76e8ddcf9271f2d 100644 (file)
@@ -458,6 +458,21 @@ config DM_VERITY
 
          If unsure, say N.
 
+config DM_VERITY_HASH_PREFETCH_MIN_SIZE_128
+       bool "Prefetch size 128"
+
+config DM_VERITY_HASH_PREFETCH_MIN_SIZE
+       int "Verity hash prefetch minimum size"
+       depends on DM_VERITY
+       range 1 4096
+       default 128 if DM_VERITY_HASH_PREFETCH_MIN_SIZE_128
+       default 1
+       ---help---
+         This sets minimum number of hash blocks to prefetch for dm-verity.
+         For devices like eMMC, having larger prefetch size like 128 can improve
+         performance with increased memory consumption for keeping more hashes
+         in RAM.
+
 config DM_VERITY_FEC
        bool "Verity forward error correction support"
        depends on DM_VERITY
@@ -510,6 +525,7 @@ config DM_ANDROID_VERITY
        depends on ASYMMETRIC_KEY_TYPE
        depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
        depends on MD_LINEAR
+       select DM_VERITY_HASH_PREFETCH_MIN_SIZE_128
        ---help---
          This device-mapper target is virtually a VERITY target. This
          target is setup by reading the metadata contents piggybacked
index e540b7942ebac2b387dd609ed0c7de1f22515040..799b9a5ad4f5d5d5f0fe25a402257e913097e243 100644 (file)
@@ -1500,12 +1500,15 @@ static int crypt_set_key(struct crypt_config *cc, char *key)
        if (!cc->key_size && strcmp(key, "-"))
                goto out;
 
+       /* clear the flag since following operations may invalidate previously valid key */
+       clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
+
        if (cc->key_size && crypt_decode_key(cc->key, key, cc->key_size) < 0)
                goto out;
 
-       set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
-
        r = crypt_setkey_allcpus(cc);
+       if (!r)
+               set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
 
 out:
        /* Hex key string not needed after here, so wipe it. */
index 8e9e928dafba398bb6e1ac19445508594c1c2807..78f403b45ab3eb1b58df3ab5a9dad09ff38f23e5 100644 (file)
@@ -200,11 +200,13 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        if (!(fc->up_interval + fc->down_interval)) {
                ti->error = "Total (up + down) interval is zero";
+               r = -EINVAL;
                goto bad;
        }
 
        if (fc->up_interval + fc->down_interval < fc->up_interval) {
                ti->error = "Interval overflow";
+               r = -EINVAL;
                goto bad;
        }
 
index 9d3d4b2972011f090696e9e9b9105a80b967e272..c7e97cf6e7fb1ac118eebe3df4350b100985ce23 100644 (file)
@@ -501,6 +501,7 @@ static void verity_prefetch_io(struct work_struct *work)
                container_of(work, struct dm_verity_prefetch_work, work);
        struct dm_verity *v = pw->v;
        int i;
+       sector_t prefetch_size;
 
        for (i = v->levels - 2; i >= 0; i--) {
                sector_t hash_block_start;
@@ -523,8 +524,14 @@ static void verity_prefetch_io(struct work_struct *work)
                                hash_block_end = v->hash_blocks - 1;
                }
 no_prefetch_cluster:
+               // for emmc, it is more efficient to send bigger read
+               prefetch_size = max((sector_t)CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE,
+                       hash_block_end - hash_block_start + 1);
+               if ((hash_block_start + prefetch_size) >= (v->hash_start + v->hash_blocks)) {
+                       prefetch_size = hash_block_end - hash_block_start + 1;
+               }
                dm_bufio_prefetch(v->bufio, hash_block_start,
-                                 hash_block_end - hash_block_start + 1);
+                                 prefetch_size);
        }
 
        kfree(pw);
index 7e44005595c1e77d1982e7e89b1259ddea97bf9a..20557e2c60c6236bf16cc35e33d3f9eb0e318779 100644 (file)
@@ -775,17 +775,15 @@ int dm_sm_metadata_create(struct dm_space_map *sm,
        memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm));
 
        r = sm_ll_new_metadata(&smm->ll, tm);
+       if (!r) {
+               if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS)
+                       nr_blocks = DM_SM_METADATA_MAX_BLOCKS;
+               r = sm_ll_extend(&smm->ll, nr_blocks);
+       }
+       memcpy(&smm->sm, &ops, sizeof(smm->sm));
        if (r)
                return r;
 
-       if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS)
-               nr_blocks = DM_SM_METADATA_MAX_BLOCKS;
-       r = sm_ll_extend(&smm->ll, nr_blocks);
-       if (r)
-               return r;
-
-       memcpy(&smm->sm, &ops, sizeof(smm->sm));
-
        /*
         * Now we need to update the newly created data structures with the
         * allocated blocks that they were built from.
index 10ce885445f61dc162159b4fb7bb77c55d28e64b..7af976934441766f3d0978b8bc2b7764a3174fe1 100644 (file)
@@ -6980,6 +6980,15 @@ static int run(struct mddev *mddev)
                        stripe = (stripe | (stripe-1)) + 1;
                mddev->queue->limits.discard_alignment = stripe;
                mddev->queue->limits.discard_granularity = stripe;
+
+               /*
+                * We use 16-bit counter of active stripes in bi_phys_segments
+                * (minus one for over-loaded initialization)
+                */
+               blk_queue_max_hw_sectors(mddev->queue, 0xfffe * STRIPE_SECTORS);
+               blk_queue_max_discard_sectors(mddev->queue,
+                                             0xfffe * STRIPE_SECTORS);
+
                /*
                 * unaligned part of discard request will be ignored, so can't
                 * guarantee discard_zeroes_data
index 4ab6586c0467529ea145452f2e534f30edeb2a73..f53e59e9c0eab2d27c169f5fb4dec0e7d8ea33b2 100644 (file)
@@ -286,7 +286,10 @@ static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg)
 static inline void solo_reg_write(struct solo_dev *solo_dev, int reg,
                                  u32 data)
 {
+       u16 val;
+
        writel(data, solo_dev->reg_base + reg);
+       pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val);
 }
 
 static inline void solo_irq_on(struct solo_dev *dev, u32 mask)
index 958af84884b57e8af7b68df6d3ab7319a963b583..2ff39fbc70d1d0af2d869865fe873de2b10f1119 100644 (file)
@@ -698,7 +698,7 @@ void mei_host_client_init(struct work_struct *work)
 
        pm_runtime_mark_last_busy(dev->dev);
        dev_dbg(dev->dev, "rpm: autosuspend\n");
-       pm_runtime_autosuspend(dev->dev);
+       pm_request_autosuspend(dev->dev);
 }
 
 /**
index d1a07558166959b09d8475f9d4ead3247ca3bf59..2e0173b96252a0bc7aac11a2c445cef92a3b257e 100644 (file)
@@ -2040,7 +2040,27 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
                        ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
                        sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
 
+                       sdhci_do_reset(host, SDHCI_RESET_CMD);
+                       sdhci_do_reset(host, SDHCI_RESET_DATA);
+
                        err = -EIO;
+
+                       if (cmd.opcode != MMC_SEND_TUNING_BLOCK_HS200)
+                               goto out;
+
+                       sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+                       sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+
+                       spin_unlock_irqrestore(&host->lock, flags);
+
+                       memset(&cmd, 0, sizeof(cmd));
+                       cmd.opcode = MMC_STOP_TRANSMISSION;
+                       cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+                       cmd.busy_timeout = 50;
+                       mmc_wait_for_cmd(mmc, &cmd, 0);
+
+                       spin_lock_irqsave(&host->lock, flags);
+
                        goto out;
                }
 
index 5a2e341a6d1ea7b2e2586414fa41592b7ad78099..91be4575b524ac663c585ce0820001c935697d43 100644 (file)
@@ -872,23 +872,25 @@ lbl_free_candev:
 static void peak_usb_disconnect(struct usb_interface *intf)
 {
        struct peak_usb_device *dev;
+       struct peak_usb_device *dev_prev_siblings;
 
        /* unregister as many netdev devices as siblings */
-       for (dev = usb_get_intfdata(intf); dev; dev = dev->prev_siblings) {
+       for (dev = usb_get_intfdata(intf); dev; dev = dev_prev_siblings) {
                struct net_device *netdev = dev->netdev;
                char name[IFNAMSIZ];
 
+               dev_prev_siblings = dev->prev_siblings;
                dev->state &= ~PCAN_USB_STATE_CONNECTED;
                strncpy(name, netdev->name, IFNAMSIZ);
 
                unregister_netdev(netdev);
-               free_candev(netdev);
 
                kfree(dev->cmd_buf);
                dev->next_siblings = NULL;
                if (dev->adapter->dev_free)
                        dev->adapter->dev_free(dev);
 
+               free_candev(netdev);
                dev_info(&intf->dev, "%s removed\n", name);
        }
 
index 6f946fedbb77c1943770b31665a0f5e1e6e4d889..0864f05633a29b2b865da5502a6f516253846729 100644 (file)
@@ -1137,6 +1137,7 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
                                   struct phy_device *phydev)
 {
        struct bcm_sf2_priv *priv = ds_to_priv(ds);
+       struct ethtool_eee *p = &priv->port_sts[port].eee;
        u32 id_mode_dis = 0, port_mode;
        const char *str = NULL;
        u32 reg;
@@ -1211,6 +1212,9 @@ force_link:
                reg |= DUPLX_MODE;
 
        core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port));
+
+       if (!phydev->is_pseudo_fixed_link)
+               p->eee_enabled = bcm_sf2_eee_init(ds, port, phydev);
 }
 
 static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
index 0fb3f8de88e9e8f897ad16abc70db06b54c64bcb..91627561c58d0c2108b0b2716befe0717c0f72c0 100644 (file)
@@ -1168,6 +1168,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
                                          struct bcmgenet_tx_ring *ring)
 {
        struct bcmgenet_priv *priv = netdev_priv(dev);
+       struct device *kdev = &priv->pdev->dev;
        struct enet_cb *tx_cb_ptr;
        struct netdev_queue *txq;
        unsigned int pkts_compl = 0;
@@ -1195,7 +1196,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
                        pkts_compl++;
                        dev->stats.tx_packets++;
                        dev->stats.tx_bytes += tx_cb_ptr->skb->len;
-                       dma_unmap_single(&dev->dev,
+                       dma_unmap_single(kdev,
                                         dma_unmap_addr(tx_cb_ptr, dma_addr),
                                         dma_unmap_len(tx_cb_ptr, dma_len),
                                         DMA_TO_DEVICE);
@@ -1203,7 +1204,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
                } else if (dma_unmap_addr(tx_cb_ptr, dma_addr)) {
                        dev->stats.tx_bytes +=
                                dma_unmap_len(tx_cb_ptr, dma_len);
-                       dma_unmap_page(&dev->dev,
+                       dma_unmap_page(kdev,
                                       dma_unmap_addr(tx_cb_ptr, dma_addr),
                                       dma_unmap_len(tx_cb_ptr, dma_len),
                                       DMA_TO_DEVICE);
@@ -1754,6 +1755,7 @@ static int bcmgenet_alloc_rx_buffers(struct bcmgenet_priv *priv,
 
 static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv)
 {
+       struct device *kdev = &priv->pdev->dev;
        struct enet_cb *cb;
        int i;
 
@@ -1761,7 +1763,7 @@ static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv)
                cb = &priv->rx_cbs[i];
 
                if (dma_unmap_addr(cb, dma_addr)) {
-                       dma_unmap_single(&priv->dev->dev,
+                       dma_unmap_single(kdev,
                                         dma_unmap_addr(cb, dma_addr),
                                         priv->rx_buf_len, DMA_FROM_DEVICE);
                        dma_unmap_addr_set(cb, dma_addr, 0);
index a4beccf1fd46e26483dc796829d444a15f77723f..25aba988699051506c0ae6c72416004227203554 100644 (file)
@@ -772,6 +772,17 @@ struct mvpp2_rx_desc {
        u32 reserved8;
 };
 
+struct mvpp2_txq_pcpu_buf {
+       /* Transmitted SKB */
+       struct sk_buff *skb;
+
+       /* Physical address of transmitted buffer */
+       dma_addr_t phys;
+
+       /* Size transmitted */
+       size_t size;
+};
+
 /* Per-CPU Tx queue control */
 struct mvpp2_txq_pcpu {
        int cpu;
@@ -787,11 +798,8 @@ struct mvpp2_txq_pcpu {
        /* Number of Tx DMA descriptors reserved for each CPU */
        int reserved_num;
 
-       /* Array of transmitted skb */
-       struct sk_buff **tx_skb;
-
-       /* Array of transmitted buffers' physical addresses */
-       dma_addr_t *tx_buffs;
+       /* Infos about transmitted buffers */
+       struct mvpp2_txq_pcpu_buf *buffs;
 
        /* Index of last TX DMA descriptor that was inserted */
        int txq_put_index;
@@ -981,10 +989,11 @@ static void mvpp2_txq_inc_put(struct mvpp2_txq_pcpu *txq_pcpu,
                              struct sk_buff *skb,
                              struct mvpp2_tx_desc *tx_desc)
 {
-       txq_pcpu->tx_skb[txq_pcpu->txq_put_index] = skb;
-       if (skb)
-               txq_pcpu->tx_buffs[txq_pcpu->txq_put_index] =
-                                                        tx_desc->buf_phys_addr;
+       struct mvpp2_txq_pcpu_buf *tx_buf =
+               txq_pcpu->buffs + txq_pcpu->txq_put_index;
+       tx_buf->skb = skb;
+       tx_buf->size = tx_desc->data_size;
+       tx_buf->phys = tx_desc->buf_phys_addr;
        txq_pcpu->txq_put_index++;
        if (txq_pcpu->txq_put_index == txq_pcpu->size)
                txq_pcpu->txq_put_index = 0;
@@ -4403,17 +4412,16 @@ static void mvpp2_txq_bufs_free(struct mvpp2_port *port,
        int i;
 
        for (i = 0; i < num; i++) {
-               dma_addr_t buf_phys_addr =
-                                   txq_pcpu->tx_buffs[txq_pcpu->txq_get_index];
-               struct sk_buff *skb = txq_pcpu->tx_skb[txq_pcpu->txq_get_index];
+               struct mvpp2_txq_pcpu_buf *tx_buf =
+                       txq_pcpu->buffs + txq_pcpu->txq_get_index;
 
                mvpp2_txq_inc_get(txq_pcpu);
 
-               dma_unmap_single(port->dev->dev.parent, buf_phys_addr,
-                                skb_headlen(skb), DMA_TO_DEVICE);
-               if (!skb)
+               dma_unmap_single(port->dev->dev.parent, tx_buf->phys,
+                                tx_buf->size, DMA_TO_DEVICE);
+               if (!tx_buf->skb)
                        continue;
-               dev_kfree_skb_any(skb);
+               dev_kfree_skb_any(tx_buf->skb);
        }
 }
 
@@ -4664,15 +4672,10 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
        for_each_present_cpu(cpu) {
                txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
                txq_pcpu->size = txq->size;
-               txq_pcpu->tx_skb = kmalloc(txq_pcpu->size *
-                                          sizeof(*txq_pcpu->tx_skb),
-                                          GFP_KERNEL);
-               if (!txq_pcpu->tx_skb)
-                       goto error;
-
-               txq_pcpu->tx_buffs = kmalloc(txq_pcpu->size *
-                                            sizeof(dma_addr_t), GFP_KERNEL);
-               if (!txq_pcpu->tx_buffs)
+               txq_pcpu->buffs = kmalloc(txq_pcpu->size *
+                                         sizeof(struct mvpp2_txq_pcpu_buf),
+                                         GFP_KERNEL);
+               if (!txq_pcpu->buffs)
                        goto error;
 
                txq_pcpu->count = 0;
@@ -4686,8 +4689,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
 error:
        for_each_present_cpu(cpu) {
                txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
-               kfree(txq_pcpu->tx_skb);
-               kfree(txq_pcpu->tx_buffs);
+               kfree(txq_pcpu->buffs);
        }
 
        dma_free_coherent(port->dev->dev.parent,
@@ -4706,8 +4708,7 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port,
 
        for_each_present_cpu(cpu) {
                txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
-               kfree(txq_pcpu->tx_skb);
-               kfree(txq_pcpu->tx_buffs);
+               kfree(txq_pcpu->buffs);
        }
 
        if (txq->descs)
index 5606a043063e3a83c5532ea0ebccbaf6fca77259..4b62aa1f9ff881ce9e4855f40c11974473bf491f 100644 (file)
@@ -5220,6 +5220,19 @@ static SIMPLE_DEV_PM_OPS(sky2_pm_ops, sky2_suspend, sky2_resume);
 
 static void sky2_shutdown(struct pci_dev *pdev)
 {
+       struct sky2_hw *hw = pci_get_drvdata(pdev);
+       int port;
+
+       for (port = 0; port < hw->ports; port++) {
+               struct net_device *ndev = hw->dev[port];
+
+               rtnl_lock();
+               if (netif_running(ndev)) {
+                       dev_close(ndev);
+                       netif_device_detach(ndev);
+               }
+               rtnl_unlock();
+       }
        sky2_suspend(&pdev->dev);
        pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev));
        pci_set_power_state(pdev, PCI_D3hot);
index 36fc9427418f325b433349e08700801387b412ba..480f3dae0780deeea215848c44a1126a6ef94d15 100644 (file)
@@ -832,7 +832,7 @@ static struct sh_eth_cpu_data r7s72100_data = {
 
        .ecsr_value     = ECSR_ICD,
        .ecsipr_value   = ECSIPR_ICDIP,
-       .eesipr_value   = 0xff7f009f,
+       .eesipr_value   = 0xe77f009f,
 
        .tx_check       = EESR_TC1 | EESR_FTC,
        .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
index 4827c6987ac3f87234e7b8acb64bb9d6bbd03c94..f0961cbaf87ed610371db39d24b40da0d2488888 100644 (file)
@@ -815,7 +815,6 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        struct geneve_dev *geneve = netdev_priv(dev);
        struct geneve_sock *gs4 = geneve->sock4;
        struct rtable *rt = NULL;
-       const struct iphdr *iip; /* interior IP header */
        int err = -EINVAL;
        struct flowi4 fl4;
        __u8 tos, ttl;
@@ -842,8 +841,6 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
        skb_reset_mac_header(skb);
 
-       iip = ip_hdr(skb);
-
        if (info) {
                const struct ip_tunnel_key *key = &info->key;
                u8 *opts = NULL;
@@ -859,7 +856,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                if (unlikely(err))
                        goto err;
 
-               tos = ip_tunnel_ecn_encap(key->tos, iip, skb);
+               tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
                ttl = key->ttl;
                df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
        } else {
@@ -869,7 +866,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                if (unlikely(err))
                        goto err;
 
-               tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, iip, skb);
+               tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, ip_hdr(skb), skb);
                ttl = geneve->ttl;
                if (!ttl && IN_MULTICAST(ntohl(fl4.daddr)))
                        ttl = 1;
@@ -903,7 +900,6 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        struct geneve_dev *geneve = netdev_priv(dev);
        struct geneve_sock *gs6 = geneve->sock6;
        struct dst_entry *dst = NULL;
-       const struct iphdr *iip; /* interior IP header */
        int err = -EINVAL;
        struct flowi6 fl6;
        __u8 prio, ttl;
@@ -927,8 +923,6 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
        skb_reset_mac_header(skb);
 
-       iip = ip_hdr(skb);
-
        if (info) {
                const struct ip_tunnel_key *key = &info->key;
                u8 *opts = NULL;
@@ -945,7 +939,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                if (unlikely(err))
                        goto err;
 
-               prio = ip_tunnel_ecn_encap(key->tos, iip, skb);
+               prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
                ttl = key->ttl;
        } else {
                udp_csum = false;
@@ -954,7 +948,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                if (unlikely(err))
                        goto err;
 
-               prio = ip_tunnel_ecn_encap(fl6.flowi6_tos, iip, skb);
+               prio = ip_tunnel_ecn_encap(fl6.flowi6_tos, ip_hdr(skb), skb);
                ttl = geneve->ttl;
                if (!ttl && ipv6_addr_is_multicast(&fl6.daddr))
                        ttl = 1;
index f94ab786088fc8fd7f848edeaedd4d2aff160606..0e2a19e589238ef3dcdd04cd7c691095385c9173 100644 (file)
@@ -1465,6 +1465,11 @@ static void virtnet_free_queues(struct virtnet_info *vi)
                netif_napi_del(&vi->rq[i].napi);
        }
 
+       /* We called napi_hash_del() before netif_napi_del(),
+        * we need to respect an RCU grace period before freeing vi->rq
+        */
+       synchronize_net();
+
        kfree(vi->rq);
        kfree(vi->sq);
 }
index 7cdaf40c3057d788dbfa01865c75178871655833..ea7b8c25955f2e78fb14dc46dd728568ec21c9a6 100644 (file)
@@ -27,7 +27,6 @@ static const struct pci_device_id ath_pci_id_table[] = {
        { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI   */
        { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
        { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI   */
-       { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI   */
 
 #ifdef CONFIG_ATH9K_PCOEM
        /* Mini PCI AR9220 MB92 cards: Compex WLM200NX, Wistron DNMA-92 */
@@ -38,7 +37,7 @@ static const struct pci_device_id ath_pci_id_table[] = {
          .driver_data = ATH9K_PCI_LED_ACT_HI },
 #endif
 
-       { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
+       { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI   */
 
 #ifdef CONFIG_ATH9K_PCOEM
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
@@ -86,7 +85,11 @@ static const struct pci_device_id ath_pci_id_table[] = {
                         0x10CF, /* Fujitsu */
                         0x1536),
          .driver_data = ATH9K_PCI_D3_L1_WAR },
+#endif
 
+       { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
+
+#ifdef CONFIG_ATH9K_PCOEM
        /* AR9285 card for Asus */
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
                         0x002B,
index 4073116e6e9fa8915c9fd4d35d932ccd5f3f2a08..c3331d6201c364e45101c0de2c19cc051813af44 100644 (file)
@@ -2144,8 +2144,9 @@ done:
                        is_scanning_required = 1;
                } else {
                        mwifiex_dbg(priv->adapter, MSG,
-                                   "info: trying to associate to '%s' bssid %pM\n",
-                                   (char *)req_ssid.ssid, bss->bssid);
+                                   "info: trying to associate to '%.*s' bssid %pM\n",
+                                   req_ssid.ssid_len, (char *)req_ssid.ssid,
+                                   bss->bssid);
                        memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
                        break;
                }
@@ -2202,8 +2203,8 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        }
 
        mwifiex_dbg(adapter, INFO,
-                   "info: Trying to associate to %s and bssid %pM\n",
-                   (char *)sme->ssid, sme->bssid);
+                   "info: Trying to associate to %.*s and bssid %pM\n",
+                   (int)sme->ssid_len, (char *)sme->ssid, sme->bssid);
 
        ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
                                     priv->bss_mode, sme->channel, sme, 0);
@@ -2333,8 +2334,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
        }
 
        mwifiex_dbg(priv->adapter, MSG,
-                   "info: trying to join to %s and bssid %pM\n",
-                   (char *)params->ssid, params->bssid);
+                   "info: trying to join to %.*s and bssid %pM\n",
+                   params->ssid_len, (char *)params->ssid, params->bssid);
 
        mwifiex_set_ibss_params(priv, params);
 
index 7a40d8dffa36a9b1eb2bc7000689058c9befe2be..aab752328c26940bf5a76b3e9235b08ff7b7d3e4 100644 (file)
@@ -1303,12 +1303,13 @@ EXPORT_SYMBOL_GPL(rtl_action_proc);
 
 static void setup_arp_tx(struct rtl_priv *rtlpriv, struct rtl_ps_ctl *ppsc)
 {
+       struct ieee80211_hw *hw = rtlpriv->hw;
+
        rtlpriv->ra.is_special_data = true;
        if (rtlpriv->cfg->ops->get_btc_status())
                rtlpriv->btcoexist.btc_ops->btc_special_packet_notify(
                                        rtlpriv, 1);
-       rtlpriv->enter_ps = false;
-       schedule_work(&rtlpriv->works.lps_change_work);
+       rtl_lps_leave(hw);
        ppsc->last_delaylps_stamp_jiffies = jiffies;
 }
 
@@ -1381,8 +1382,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx,
 
                if (is_tx) {
                        rtlpriv->ra.is_special_data = true;
-                       rtlpriv->enter_ps = false;
-                       schedule_work(&rtlpriv->works.lps_change_work);
+                       rtl_lps_leave(hw);
                        ppsc->last_delaylps_stamp_jiffies = jiffies;
                }
 
index c925a4dff5995b6934bfc5edcb28a45ec8bbe4c7..e36d8c45627577acfebf6554cc72a09394e59c21 100644 (file)
@@ -1153,10 +1153,8 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
                } else {
                        mstatus = RT_MEDIA_DISCONNECT;
 
-                       if (mac->link_state == MAC80211_LINKED) {
-                               rtlpriv->enter_ps = false;
-                               schedule_work(&rtlpriv->works.lps_change_work);
-                       }
+                       if (mac->link_state == MAC80211_LINKED)
+                               rtl_lps_leave(hw);
                        if (ppsc->p2p_ps_info.p2p_ps_mode > P2P_PS_NONE)
                                rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
                        mac->link_state = MAC80211_NOLINK;
@@ -1432,8 +1430,7 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw,
        }
 
        if (mac->link_state == MAC80211_LINKED) {
-               rtlpriv->enter_ps = false;
-               schedule_work(&rtlpriv->works.lps_change_work);
+               rtl_lps_leave(hw);
                mac->link_state = MAC80211_LINKED_SCANNING;
        } else {
                rtl_ips_nic_on(hw);
index 5b4048041147667356aee1b08a8b64376c0d4dde..a52230377e2c84405ef11ed3c9fbf8e2d5b88159 100644 (file)
@@ -664,11 +664,9 @@ tx_status_ok:
        }
 
        if (((rtlpriv->link_info.num_rx_inperiod +
-               rtlpriv->link_info.num_tx_inperiod) > 8) ||
-               (rtlpriv->link_info.num_rx_inperiod > 2)) {
-               rtlpriv->enter_ps = false;
-               schedule_work(&rtlpriv->works.lps_change_work);
-       }
+             rtlpriv->link_info.num_tx_inperiod) > 8) ||
+             (rtlpriv->link_info.num_rx_inperiod > 2))
+               rtl_lps_leave(hw);
 }
 
 static int _rtl_pci_init_one_rxdesc(struct ieee80211_hw *hw,
@@ -919,10 +917,8 @@ new_trx_end:
                }
                if (((rtlpriv->link_info.num_rx_inperiod +
                      rtlpriv->link_info.num_tx_inperiod) > 8) ||
-                     (rtlpriv->link_info.num_rx_inperiod > 2)) {
-                       rtlpriv->enter_ps = false;
-                       schedule_work(&rtlpriv->works.lps_change_work);
-               }
+                     (rtlpriv->link_info.num_rx_inperiod > 2))
+                       rtl_lps_leave(hw);
                skb = new_skb;
 no_new:
                if (rtlpriv->use_new_trx_flow) {
index b69321d45f043a8727f5e02341b1bc9cd91f4617..626ff300352b7f4aba6dfda73dd79a3b47be2c64 100644 (file)
@@ -414,8 +414,8 @@ void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode)
        }
 }
 
-/*Enter the leisure power save mode.*/
-void rtl_lps_enter(struct ieee80211_hw *hw)
+/* Interrupt safe routine to enter the leisure power save mode.*/
+static void rtl_lps_enter_core(struct ieee80211_hw *hw)
 {
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
@@ -455,10 +455,9 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
 
        spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
 }
-EXPORT_SYMBOL(rtl_lps_enter);
 
-/*Leave the leisure power save mode.*/
-void rtl_lps_leave(struct ieee80211_hw *hw)
+/* Interrupt safe routine to leave the leisure power save mode.*/
+static void rtl_lps_leave_core(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
@@ -488,7 +487,6 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
        }
        spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
 }
-EXPORT_SYMBOL(rtl_lps_leave);
 
 /* For sw LPS*/
 void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len)
@@ -681,12 +679,34 @@ void rtl_lps_change_work_callback(struct work_struct *work)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
 
        if (rtlpriv->enter_ps)
-               rtl_lps_enter(hw);
+               rtl_lps_enter_core(hw);
        else
-               rtl_lps_leave(hw);
+               rtl_lps_leave_core(hw);
 }
 EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback);
 
+void rtl_lps_enter(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       if (!in_interrupt())
+               return rtl_lps_enter_core(hw);
+       rtlpriv->enter_ps = true;
+       schedule_work(&rtlpriv->works.lps_change_work);
+}
+EXPORT_SYMBOL_GPL(rtl_lps_enter);
+
+void rtl_lps_leave(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+       if (!in_interrupt())
+               return rtl_lps_leave_core(hw);
+       rtlpriv->enter_ps = false;
+       schedule_work(&rtlpriv->works.lps_change_work);
+}
+EXPORT_SYMBOL_GPL(rtl_lps_leave);
+
 void rtl_swlps_wq_callback(void *data)
 {
        struct rtl_works *rtlworks = container_of_dwork_rtl(data,
index 42d8617352ae8dff39ce7b56d75b3ac9631fa6f4..e311a9bf2c90d602e3ced4725b22562c733660cf 100644 (file)
@@ -2043,6 +2043,10 @@ bool pci_dev_run_wake(struct pci_dev *dev)
        if (!dev->pme_support)
                return false;
 
+       /* PME-capable in principle, but not from the intended sleep state */
+       if (!pci_pme_capable(dev, pci_target_state(dev)))
+               return false;
+
        while (bus->parent) {
                struct pci_dev *bridge = bus->self;
 
index 182224acedbe79c18dbc357cb45763afef40e387..58f1419a68aef0b7fd1e7eef352400a875f7ad94 100644 (file)
@@ -283,20 +283,6 @@ out:
        return 0;
 }
 
-static struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
-{
-       while (1) {
-               if (!pci_is_pcie(dev))
-                       break;
-               if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
-                       return dev;
-               if (!dev->bus->self)
-                       break;
-               dev = dev->bus->self;
-       }
-       return NULL;
-}
-
 static int find_aer_device_iter(struct device *device, void *data)
 {
        struct pcie_device **result = data;
index 9757cf9037a2b0e9e917ac454b0f107e0e3b3b04..b5843c255263df2d04c12f36e819b60bab47369f 100644 (file)
@@ -1415,6 +1415,21 @@ static void program_hpp_type1(struct pci_dev *dev, struct hpp_type1 *hpp)
                dev_warn(&dev->dev, "PCI-X settings not supported\n");
 }
 
+static bool pcie_root_rcb_set(struct pci_dev *dev)
+{
+       struct pci_dev *rp = pcie_find_root_port(dev);
+       u16 lnkctl;
+
+       if (!rp)
+               return false;
+
+       pcie_capability_read_word(rp, PCI_EXP_LNKCTL, &lnkctl);
+       if (lnkctl & PCI_EXP_LNKCTL_RCB)
+               return true;
+
+       return false;
+}
+
 static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
 {
        int pos;
@@ -1444,9 +1459,20 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
                        ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or);
 
        /* Initialize Link Control Register */
-       if (pcie_cap_has_lnkctl(dev))
+       if (pcie_cap_has_lnkctl(dev)) {
+
+               /*
+                * If the Root Port supports Read Completion Boundary of
+                * 128, set RCB to 128.  Otherwise, clear it.
+                */
+               hpp->pci_exp_lnkctl_and |= PCI_EXP_LNKCTL_RCB;
+               hpp->pci_exp_lnkctl_or &= ~PCI_EXP_LNKCTL_RCB;
+               if (pcie_root_rcb_set(dev))
+                       hpp->pci_exp_lnkctl_or |= PCI_EXP_LNKCTL_RCB;
+
                pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
                        ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or);
+       }
 
        /* Find Advanced Error Reporting Enhanced Capability */
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
index 131fee2b093eadde86ba6c0b0fc53be458150e82..a3661cc44f86fdc205d16ab110187862b7f2f3fb 100644 (file)
@@ -126,6 +126,15 @@ static const struct dmi_system_id asus_quirks[] = {
                },
                .driver_data = &quirk_asus_wapf4,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "ASUSTeK COMPUTER INC. X45U",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X45U"),
+               },
+               .driver_data = &quirk_asus_wapf4,
+       },
        {
                .callback = dmi_matched,
                .ident = "ASUSTeK COMPUTER INC. X456UA",
index c20163b929911d386a4a226dbdc528704eadd451..375008e2be20a5ae057f72fef7898988314cbdc4 100644 (file)
@@ -366,6 +366,8 @@ void pwmchip_sysfs_unexport_children(struct pwm_chip *chip)
                if (test_bit(PWMF_EXPORTED, &pwm->flags))
                        pwm_unexport_child(parent, pwm);
        }
+
+       put_device(parent);
 }
 
 static int __init pwm_sysfs_init(void)
index 7d2ae3e9e942f26f302f526450487213da2cc44d..342f5da799758e0d054ef2aaa64c9ff1c566365e 100644 (file)
@@ -47,7 +47,8 @@ static struct regulator_desc vmmc_regulator = {
        .volt_table = stw481x_vmmc_voltages,
        .enable_time = 200, /* FIXME: look this up */
        .enable_reg = STW_CONF1,
-       .enable_mask = STW_CONF1_PDN_VMMC,
+       .enable_mask = STW_CONF1_PDN_VMMC | STW_CONF1_MMC_LS_STATUS,
+       .enable_val = STW_CONF1_PDN_VMMC,
        .vsel_reg = STW_CONF1,
        .vsel_mask = STW_CONF1_VMMC_MASK,
 };
index 799c1524c779f282387b3ed79c5363f95b1fbd98..4b8de3e70cf2d2d67718b25b522414424d9e6f0e 100644 (file)
@@ -872,7 +872,7 @@ static int __init vmlogrdr_init(void)
                goto cleanup;
 
        for (i=0; i < MAXMINOR; ++i ) {
-               sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL);
+               sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
                if (!sys_ser[i].buffer) {
                        rc = -ENOMEM;
                        break;
index 581001989937ce1e0aaab11c26136d5e11b4fa4d..d5bf36ec8a751326062e47abe80ddd1f61a5f43b 100644 (file)
@@ -289,11 +289,12 @@ void zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter,
 
 
 /**
- * zfcp_dbf_rec_run - trace event related to running recovery
+ * zfcp_dbf_rec_run_lvl - trace event related to running recovery
+ * @level: trace level to be used for event
  * @tag: identifier for event
  * @erp: erp_action running
  */
-void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp)
+void zfcp_dbf_rec_run_lvl(int level, char *tag, struct zfcp_erp_action *erp)
 {
        struct zfcp_dbf *dbf = erp->adapter->dbf;
        struct zfcp_dbf_rec *rec = &dbf->rec_buf;
@@ -319,10 +320,20 @@ void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp)
        else
                rec->u.run.rec_count = atomic_read(&erp->adapter->erp_counter);
 
-       debug_event(dbf->rec, 1, rec, sizeof(*rec));
+       debug_event(dbf->rec, level, rec, sizeof(*rec));
        spin_unlock_irqrestore(&dbf->rec_lock, flags);
 }
 
+/**
+ * zfcp_dbf_rec_run - trace event related to running recovery
+ * @tag: identifier for event
+ * @erp: erp_action running
+ */
+void zfcp_dbf_rec_run(char *tag, struct zfcp_erp_action *erp)
+{
+       zfcp_dbf_rec_run_lvl(1, tag, erp);
+}
+
 /**
  * zfcp_dbf_rec_run_wka - trace wka port event with info like running recovery
  * @tag: identifier for event
index 36d07584271d569d27ec2eeb3706235d6459e026..db186d44cfafb6036a7e452e68e2c8f078cff6d1 100644 (file)
@@ -2,7 +2,7 @@
  * zfcp device driver
  * debug feature declarations
  *
- * Copyright IBM Corp. 2008, 2015
+ * Copyright IBM Corp. 2008, 2016
  */
 
 #ifndef ZFCP_DBF_H
@@ -283,6 +283,30 @@ struct zfcp_dbf {
        struct zfcp_dbf_scsi            scsi_buf;
 };
 
+/**
+ * zfcp_dbf_hba_fsf_resp_suppress - true if we should not trace by default
+ * @req: request that has been completed
+ *
+ * Returns true if FCP response with only benign residual under count.
+ */
+static inline
+bool zfcp_dbf_hba_fsf_resp_suppress(struct zfcp_fsf_req *req)
+{
+       struct fsf_qtcb *qtcb = req->qtcb;
+       u32 fsf_stat = qtcb->header.fsf_status;
+       struct fcp_resp *fcp_rsp;
+       u8 rsp_flags, fr_status;
+
+       if (qtcb->prefix.qtcb_type != FSF_IO_COMMAND)
+               return false; /* not an FCP response */
+       fcp_rsp = (struct fcp_resp *)&qtcb->bottom.io.fcp_rsp;
+       rsp_flags = fcp_rsp->fr_flags;
+       fr_status = fcp_rsp->fr_status;
+       return (fsf_stat == FSF_FCP_RSP_AVAILABLE) &&
+               (rsp_flags == FCP_RESID_UNDER) &&
+               (fr_status == SAM_STAT_GOOD);
+}
+
 static inline
 void zfcp_dbf_hba_fsf_resp(char *tag, int level, struct zfcp_fsf_req *req)
 {
@@ -304,7 +328,9 @@ void zfcp_dbf_hba_fsf_response(struct zfcp_fsf_req *req)
                zfcp_dbf_hba_fsf_resp("fs_perr", 1, req);
 
        } else if (qtcb->header.fsf_status != FSF_GOOD) {
-               zfcp_dbf_hba_fsf_resp("fs_ferr", 1, req);
+               zfcp_dbf_hba_fsf_resp("fs_ferr",
+                                     zfcp_dbf_hba_fsf_resp_suppress(req)
+                                     ? 5 : 1, req);
 
        } else if ((req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) ||
                   (req->fsf_command == FSF_QTCB_OPEN_LUN)) {
@@ -388,4 +414,15 @@ void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag)
        _zfcp_dbf_scsi(tmp_tag, 1, scmnd, NULL);
 }
 
+/**
+ * zfcp_dbf_scsi_nullcmnd() - trace NULLify of SCSI command in dev/tgt-reset.
+ * @scmnd: SCSI command that was NULLified.
+ * @fsf_req: request that owned @scmnd.
+ */
+static inline void zfcp_dbf_scsi_nullcmnd(struct scsi_cmnd *scmnd,
+                                         struct zfcp_fsf_req *fsf_req)
+{
+       _zfcp_dbf_scsi("scfc__1", 3, scmnd, fsf_req);
+}
+
 #endif /* ZFCP_DBF_H */
index a59d678125bd0e0ad0bd1ca74b0d42985abb25d8..7ccfce55903423f5e998fe3d93f6942a5879376f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Error Recovery Procedures (ERP).
  *
- * Copyright IBM Corp. 2002, 2015
+ * Copyright IBM Corp. 2002, 2016
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -1204,6 +1204,62 @@ static void zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
        }
 }
 
+/**
+ * zfcp_erp_try_rport_unblock - unblock rport if no more/new recovery
+ * @port: zfcp_port whose fc_rport we should try to unblock
+ */
+static void zfcp_erp_try_rport_unblock(struct zfcp_port *port)
+{
+       unsigned long flags;
+       struct zfcp_adapter *adapter = port->adapter;
+       int port_status;
+       struct Scsi_Host *shost = adapter->scsi_host;
+       struct scsi_device *sdev;
+
+       write_lock_irqsave(&adapter->erp_lock, flags);
+       port_status = atomic_read(&port->status);
+       if ((port_status & ZFCP_STATUS_COMMON_UNBLOCKED)    == 0 ||
+           (port_status & (ZFCP_STATUS_COMMON_ERP_INUSE |
+                           ZFCP_STATUS_COMMON_ERP_FAILED)) != 0) {
+               /* new ERP of severity >= port triggered elsewhere meanwhile or
+                * local link down (adapter erp_failed but not clear unblock)
+                */
+               zfcp_dbf_rec_run_lvl(4, "ertru_p", &port->erp_action);
+               write_unlock_irqrestore(&adapter->erp_lock, flags);
+               return;
+       }
+       spin_lock(shost->host_lock);
+       __shost_for_each_device(sdev, shost) {
+               struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev);
+               int lun_status;
+
+               if (zsdev->port != port)
+                       continue;
+               /* LUN under port of interest */
+               lun_status = atomic_read(&zsdev->status);
+               if ((lun_status & ZFCP_STATUS_COMMON_ERP_FAILED) != 0)
+                       continue; /* unblock rport despite failed LUNs */
+               /* LUN recovery not given up yet [maybe follow-up pending] */
+               if ((lun_status & ZFCP_STATUS_COMMON_UNBLOCKED) == 0 ||
+                   (lun_status & ZFCP_STATUS_COMMON_ERP_INUSE) != 0) {
+                       /* LUN blocked:
+                        * not yet unblocked [LUN recovery pending]
+                        * or meanwhile blocked [new LUN recovery triggered]
+                        */
+                       zfcp_dbf_rec_run_lvl(4, "ertru_l", &zsdev->erp_action);
+                       spin_unlock(shost->host_lock);
+                       write_unlock_irqrestore(&adapter->erp_lock, flags);
+                       return;
+               }
+       }
+       /* now port has no child or all children have completed recovery,
+        * and no ERP of severity >= port was meanwhile triggered elsewhere
+        */
+       zfcp_scsi_schedule_rport_register(port);
+       spin_unlock(shost->host_lock);
+       write_unlock_irqrestore(&adapter->erp_lock, flags);
+}
+
 static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
 {
        struct zfcp_adapter *adapter = act->adapter;
@@ -1214,6 +1270,7 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
        case ZFCP_ERP_ACTION_REOPEN_LUN:
                if (!(act->status & ZFCP_STATUS_ERP_NO_REF))
                        scsi_device_put(sdev);
+               zfcp_erp_try_rport_unblock(port);
                break;
 
        case ZFCP_ERP_ACTION_REOPEN_PORT:
@@ -1224,7 +1281,7 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
                 */
                if (act->step != ZFCP_ERP_STEP_UNINITIALIZED)
                        if (result == ZFCP_ERP_SUCCEEDED)
-                               zfcp_scsi_schedule_rport_register(port);
+                               zfcp_erp_try_rport_unblock(port);
                /* fall through */
        case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
                put_device(&port->dev);
index c8fed9fa1cca3680015913162ce3ddfee50c85b1..21c8c689b02bb1f507398e3477e507027eec4732 100644 (file)
@@ -3,7 +3,7 @@
  *
  * External function declarations.
  *
- * Copyright IBM Corp. 2002, 2015
+ * Copyright IBM Corp. 2002, 2016
  */
 
 #ifndef ZFCP_EXT_H
@@ -35,6 +35,8 @@ extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *);
 extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *,
                              struct zfcp_port *, struct scsi_device *, u8, u8);
 extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *);
+extern void zfcp_dbf_rec_run_lvl(int level, char *tag,
+                                struct zfcp_erp_action *erp);
 extern void zfcp_dbf_rec_run_wka(char *, struct zfcp_fc_wka_port *, u64);
 extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *);
 extern void zfcp_dbf_hba_fsf_res(char *, int, struct zfcp_fsf_req *);
index be1c04b334c51f678d643e4c488173f8fd6be0ee..ea3c76ac0de14dc8ea9ad147d1f5b9ab80cc1172 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Interface to the FSF support functions.
  *
- * Copyright IBM Corp. 2002, 2015
+ * Copyright IBM Corp. 2002, 2016
  */
 
 #ifndef FSF_H
@@ -78,6 +78,7 @@
 #define FSF_APP_TAG_CHECK_FAILURE              0x00000082
 #define FSF_REF_TAG_CHECK_FAILURE              0x00000083
 #define FSF_ADAPTER_STATUS_AVAILABLE           0x000000AD
+#define FSF_FCP_RSP_AVAILABLE                  0x000000AF
 #define FSF_UNKNOWN_COMMAND                    0x000000E2
 #define FSF_UNKNOWN_OP_SUBTYPE                  0x000000E3
 #define FSF_INVALID_COMMAND_OPTION              0x000000E5
index 7c2c6194dfca58e1eb2fe6466abf64fd928deb96..703fce59befef0be884449e00addad4a49981d61 100644 (file)
@@ -4,7 +4,7 @@
  * Data structure and helper functions for tracking pending FSF
  * requests.
  *
- * Copyright IBM Corp. 2009
+ * Copyright IBM Corp. 2009, 2016
  */
 
 #ifndef ZFCP_REQLIST_H
@@ -180,4 +180,32 @@ static inline void zfcp_reqlist_move(struct zfcp_reqlist *rl,
        spin_unlock_irqrestore(&rl->lock, flags);
 }
 
+/**
+ * zfcp_reqlist_apply_for_all() - apply a function to every request.
+ * @rl: the requestlist that contains the target requests.
+ * @f: the function to apply to each request; the first parameter of the
+ *     function will be the target-request; the second parameter is the same
+ *     pointer as given with the argument @data.
+ * @data: freely chosen argument; passed through to @f as second parameter.
+ *
+ * Uses :c:macro:`list_for_each_entry` to iterate over the lists in the hash-
+ * table (not a 'safe' variant, so don't modify the list).
+ *
+ * Holds @rl->lock over the entire request-iteration.
+ */
+static inline void
+zfcp_reqlist_apply_for_all(struct zfcp_reqlist *rl,
+                          void (*f)(struct zfcp_fsf_req *, void *), void *data)
+{
+       struct zfcp_fsf_req *req;
+       unsigned long flags;
+       unsigned int i;
+
+       spin_lock_irqsave(&rl->lock, flags);
+       for (i = 0; i < ZFCP_REQ_LIST_BUCKETS; i++)
+               list_for_each_entry(req, &rl->buckets[i], list)
+                       f(req, data);
+       spin_unlock_irqrestore(&rl->lock, flags);
+}
+
 #endif /* ZFCP_REQLIST_H */
index 9069f98a18172e754c943010654de65e91c2fb7c..07ffdbb5107f732082e88c94b0362b845e7e17d6 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Interface to Linux SCSI midlayer.
  *
- * Copyright IBM Corp. 2002, 2015
+ * Copyright IBM Corp. 2002, 2016
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -88,9 +88,7 @@ int zfcp_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scpnt)
        }
 
        if (unlikely(!(status & ZFCP_STATUS_COMMON_UNBLOCKED))) {
-               /* This could be either
-                * open LUN pending: this is temporary, will result in
-                *      open LUN or ERP_FAILED, so retry command
+               /* This could be
                 * call to rport_delete pending: mimic retry from
                 *      fc_remote_port_chkready until rport is BLOCKED
                 */
@@ -209,6 +207,57 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
        return retval;
 }
 
+struct zfcp_scsi_req_filter {
+       u8 tmf_scope;
+       u32 lun_handle;
+       u32 port_handle;
+};
+
+static void zfcp_scsi_forget_cmnd(struct zfcp_fsf_req *old_req, void *data)
+{
+       struct zfcp_scsi_req_filter *filter =
+               (struct zfcp_scsi_req_filter *)data;
+
+       /* already aborted - prevent side-effects - or not a SCSI command */
+       if (old_req->data == NULL || old_req->fsf_command != FSF_QTCB_FCP_CMND)
+               return;
+
+       /* (tmf_scope == FCP_TMF_TGT_RESET || tmf_scope == FCP_TMF_LUN_RESET) */
+       if (old_req->qtcb->header.port_handle != filter->port_handle)
+               return;
+
+       if (filter->tmf_scope == FCP_TMF_LUN_RESET &&
+           old_req->qtcb->header.lun_handle != filter->lun_handle)
+               return;
+
+       zfcp_dbf_scsi_nullcmnd((struct scsi_cmnd *)old_req->data, old_req);
+       old_req->data = NULL;
+}
+
+static void zfcp_scsi_forget_cmnds(struct zfcp_scsi_dev *zsdev, u8 tm_flags)
+{
+       struct zfcp_adapter *adapter = zsdev->port->adapter;
+       struct zfcp_scsi_req_filter filter = {
+               .tmf_scope = FCP_TMF_TGT_RESET,
+               .port_handle = zsdev->port->handle,
+       };
+       unsigned long flags;
+
+       if (tm_flags == FCP_TMF_LUN_RESET) {
+               filter.tmf_scope = FCP_TMF_LUN_RESET;
+               filter.lun_handle = zsdev->lun_handle;
+       }
+
+       /*
+        * abort_lock secures against other processings - in the abort-function
+        * and normal cmnd-handler - of (struct zfcp_fsf_req *)->data
+        */
+       write_lock_irqsave(&adapter->abort_lock, flags);
+       zfcp_reqlist_apply_for_all(adapter->req_list, zfcp_scsi_forget_cmnd,
+                                  &filter);
+       write_unlock_irqrestore(&adapter->abort_lock, flags);
+}
+
 static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
 {
        struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
@@ -241,8 +290,10 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
        if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
                zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags);
                retval = FAILED;
-       } else
+       } else {
                zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags);
+               zfcp_scsi_forget_cmnds(zfcp_sdev, tm_flags);
+       }
 
        zfcp_fsf_req_free(fsf_req);
        return retval;
index 021b994fdae8d08e95df2dac143125131aca32ff..96007633ad39b2e266fbc66c34e9eaf40a72ed1e 100644 (file)
@@ -1856,6 +1856,8 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
                io_request->DevHandle = pd_sync->seq[pd_index].devHandle;
                pRAID_Context->regLockFlags |=
                        (MR_RL_FLAGS_SEQ_NUM_ENABLE|MR_RL_FLAGS_GRANT_DESTINATION_CUDA);
+               pRAID_Context->Type = MPI2_TYPE_CUDA;
+               pRAID_Context->nseg = 0x1;
        } else if (fusion->fast_path_io) {
                pRAID_Context->VirtualDiskTgtId = cpu_to_le16(device_id);
                pRAID_Context->configSeqNum = 0;
@@ -1891,12 +1893,10 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
                pRAID_Context->timeoutValue =
                        cpu_to_le16((os_timeout_value > timeout_limit) ?
                        timeout_limit : os_timeout_value);
-               if (fusion->adapter_type == INVADER_SERIES) {
-                       pRAID_Context->Type = MPI2_TYPE_CUDA;
-                       pRAID_Context->nseg = 0x1;
+               if (fusion->adapter_type == INVADER_SERIES)
                        io_request->IoFlags |=
                                cpu_to_le16(MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH);
-               }
+
                cmd->request_desc->SCSIIO.RequestFlags =
                        (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
                                MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
@@ -2648,6 +2648,7 @@ int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance,
                dev_err(&instance->pdev->dev, "pending commands remain after waiting, "
                       "will reset adapter scsi%d.\n",
                       instance->host->host_no);
+               *convert = 1;
                retval = 1;
        }
 out:
index 7232d43e2207d36c0b8368c7c880352e82abe60e..4477e999ec707c7c18b077c3061fb34b6cf85309 100644 (file)
@@ -1031,10 +1031,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
        struct request_queue *rq = sdev->request_queue;
        struct scsi_target *starget = sdev->sdev_target;
 
-       error = scsi_device_set_state(sdev, SDEV_RUNNING);
-       if (error)
-               return error;
-
        error = scsi_target_add(starget);
        if (error)
                return error;
index ae7d9bdf409c816d014ac2d668a1e449fce0c8e9..a1c29b0afb22e10cb4ae741a2080ad8cbcae1cbd 100644 (file)
@@ -592,6 +592,9 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
        sg_io_hdr_t *hp;
        unsigned char cmnd[SG_MAX_CDB_SIZE];
 
+       if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
+               return -EINVAL;
+
        if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
                return -ENXIO;
        SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
index 0f28c08fcb3c76f4a2deaf3cd084a39f800db142..77b551da57288c11d21d6ff40b65b1d8b01ed887 100644 (file)
@@ -909,6 +909,7 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
                        if (err) {
                                ssb_warn("WARNING: Using fallback SPROM failed (err %d)\n",
                                         err);
+                               goto out_free;
                        } else {
                                ssb_dbg("Using SPROM revision %d provided by platform\n",
                                        sprom->revision);
index 35ab4a9ef95d62f02c4058eadaf27d87ebe85ee7..c975f6e8be49eb097b51b79afdbaeff1b69c5214 100644 (file)
@@ -1929,7 +1929,7 @@ static int ni_ai_insn_read(struct comedi_device *dev,
                           unsigned int *data)
 {
        struct ni_private *devpriv = dev->private;
-       unsigned int mask = (s->maxdata + 1) >> 1;
+       unsigned int mask = s->maxdata;
        int i, n;
        unsigned signbits;
        unsigned int d;
@@ -1972,7 +1972,7 @@ static int ni_ai_insn_read(struct comedi_device *dev,
                                return -ETIME;
                        }
                        d += signbits;
-                       data[n] = d;
+                       data[n] = d & 0xffff;
                }
        } else if (devpriv->is_6143) {
                for (n = 0; n < insn->n; n++) {
@@ -2017,8 +2017,8 @@ static int ni_ai_insn_read(struct comedi_device *dev,
                                data[n] = dl;
                        } else {
                                d = ni_readw(dev, NI_E_AI_FIFO_DATA_REG);
-                               d += signbits;  /* subtle: needs to be short addition */
-                               data[n] = d;
+                               d += signbits;
+                               data[n] = d & 0xffff;
                        }
                }
        }
index 5e6d6cb348fc1c902ea74079357430d5dfb0d44a..a7d30e894cab2659aac52c7c59dea950f32c6ef9 100644 (file)
@@ -645,8 +645,6 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
        target_complete_cmd(cmd->se_cmd, SAM_STAT_CHECK_CONDITION);
        cmd->se_cmd = NULL;
 
-       kmem_cache_free(tcmu_cmd_cache, cmd);
-
        return 0;
 }
 
index 06fd2ed9ef9d13bf0ab09f727020f873152b8da9..705b0cafedbb442d6f96e09b606171c4e1e77b9d 100644 (file)
@@ -98,7 +98,7 @@ temp_crit_show(struct device *dev, struct device_attribute *attr, char *buf)
        int temperature;
        int ret;
 
-       ret = tz->ops->get_trip_temp(tz, 0, &temperature);
+       ret = tz->ops->get_crit_temp(tz, &temperature);
        if (ret)
                return ret;
 
index edb5305b9d4da72e388452f66db9e65e40d15f18..7d5ee8a13ac657ea4ee2b959bc15e680349022ea 100644 (file)
@@ -1230,7 +1230,7 @@ static int sc16is7xx_probe(struct device *dev,
 
        /* Setup interrupt */
        ret = devm_request_irq(dev, irq, sc16is7xx_irq,
-                              IRQF_ONESHOT | flags, dev_name(dev), s);
+                              flags, dev_name(dev), s);
        if (!ret)
                return 0;
 
index 41987a55a5383e0560b03a102251e2f0f40ecd92..988c564b61a88bd5019d2dba18b1ee608f8acbb4 100644 (file)
@@ -982,7 +982,7 @@ static void kbd_led_trigger_activate(struct led_classdev *cdev)
        KBD_LED_TRIGGER((_led_bit) + 8, _name)
 
 static struct kbd_led_trigger kbd_led_triggers[] = {
-       KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrollock"),
+       KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrolllock"),
        KBD_LED_TRIGGER(VC_NUMLOCK,   "kbd-numlock"),
        KBD_LED_TRIGGER(VC_CAPSLOCK,  "kbd-capslock"),
        KBD_LED_TRIGGER(VC_KANALOCK,  "kbd-kanalock"),
index 4d77745f439fe5a95cc1994689e1d9d49b64c237..96849e2e7435471e0ce1c63287bf050f060d8784 100644 (file)
@@ -1708,6 +1708,7 @@ static const struct usb_device_id acm_ids[] = {
        { USB_DEVICE(0x20df, 0x0001), /* Simtec Electronics Entropy Key */
        .driver_info = QUIRK_CONTROL_LINE_STATE, },
        { USB_DEVICE(0x2184, 0x001c) }, /* GW Instek AFG-2225 */
+       { USB_DEVICE(0x2184, 0x0036) }, /* GW Instek AFG-125 */
        { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */
        },
        /* Motorola H24 HSPA module: */
index bcc1e1b729adf139cd9452864183195245d79ac3..496d6a558793987c212024729bae58bd3fdb3808 100644 (file)
@@ -101,6 +101,8 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
 
 static void hub_release(struct kref *kref);
 static int usb_reset_and_verify_device(struct usb_device *udev);
+static void hub_usb3_port_prepare_disable(struct usb_hub *hub,
+                                         struct usb_port *port_dev);
 
 static inline char *portspeed(struct usb_hub *hub, int portstatus)
 {
@@ -883,82 +885,28 @@ static int hub_set_port_link_state(struct usb_hub *hub, int port1,
 }
 
 /*
- * If USB 3.0 ports are placed into the Disabled state, they will no longer
- * detect any device connects or disconnects.  This is generally not what the
- * USB core wants, since it expects a disabled port to produce a port status
- * change event when a new device connects.
- *
- * Instead, set the link state to Disabled, wait for the link to settle into
- * that state, clear any change bits, and then put the port into the RxDetect
- * state.
+ * USB-3 does not have a similar link state as USB-2 that will avoid negotiating
+ * a connection with a plugged-in cable but will signal the host when the cable
+ * is unplugged. Disable remote wake and set link state to U3 for USB-3 devices
  */
-static int hub_usb3_port_disable(struct usb_hub *hub, int port1)
-{
-       int ret;
-       int total_time;
-       u16 portchange, portstatus;
-
-       if (!hub_is_superspeed(hub->hdev))
-               return -EINVAL;
-
-       ret = hub_port_status(hub, port1, &portstatus, &portchange);
-       if (ret < 0)
-               return ret;
-
-       /*
-        * USB controller Advanced Micro Devices, Inc. [AMD] FCH USB XHCI
-        * Controller [1022:7814] will have spurious result making the following
-        * usb 3.0 device hotplugging route to the 2.0 root hub and recognized
-        * as high-speed device if we set the usb 3.0 port link state to
-        * Disabled. Since it's already in USB_SS_PORT_LS_RX_DETECT state, we
-        * check the state here to avoid the bug.
-        */
-       if ((portstatus & USB_PORT_STAT_LINK_STATE) ==
-                               USB_SS_PORT_LS_RX_DETECT) {
-               dev_dbg(&hub->ports[port1 - 1]->dev,
-                        "Not disabling port; link state is RxDetect\n");
-               return ret;
-       }
-
-       ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED);
-       if (ret)
-               return ret;
-
-       /* Wait for the link to enter the disabled state. */
-       for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
-               ret = hub_port_status(hub, port1, &portstatus, &portchange);
-               if (ret < 0)
-                       return ret;
-
-               if ((portstatus & USB_PORT_STAT_LINK_STATE) ==
-                               USB_SS_PORT_LS_SS_DISABLED)
-                       break;
-               if (total_time >= HUB_DEBOUNCE_TIMEOUT)
-                       break;
-               msleep(HUB_DEBOUNCE_STEP);
-       }
-       if (total_time >= HUB_DEBOUNCE_TIMEOUT)
-               dev_warn(&hub->ports[port1 - 1]->dev,
-                               "Could not disable after %d ms\n", total_time);
-
-       return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT);
-}
-
 static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
 {
        struct usb_port *port_dev = hub->ports[port1 - 1];
        struct usb_device *hdev = hub->hdev;
        int ret = 0;
 
-       if (port_dev->child && set_state)
-               usb_set_device_state(port_dev->child, USB_STATE_NOTATTACHED);
        if (!hub->error) {
-               if (hub_is_superspeed(hub->hdev))
-                       ret = hub_usb3_port_disable(hub, port1);
-               else
+               if (hub_is_superspeed(hub->hdev)) {
+                       hub_usb3_port_prepare_disable(hub, port_dev);
+                       ret = hub_set_port_link_state(hub, port_dev->portnum,
+                                                     USB_SS_PORT_LS_U3);
+               } else {
                        ret = usb_clear_port_feature(hdev, port1,
                                        USB_PORT_FEAT_ENABLE);
+               }
        }
+       if (port_dev->child && set_state)
+               usb_set_device_state(port_dev->child, USB_STATE_NOTATTACHED);
        if (ret && ret != -ENODEV)
                dev_err(&port_dev->dev, "cannot disable (err = %d)\n", ret);
        return ret;
@@ -4073,6 +4021,26 @@ void usb_unlocked_enable_lpm(struct usb_device *udev)
 }
 EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm);
 
+/* usb3 devices use U3 for disabled, make sure remote wakeup is disabled */
+static void hub_usb3_port_prepare_disable(struct usb_hub *hub,
+                                         struct usb_port *port_dev)
+{
+       struct usb_device *udev = port_dev->child;
+       int ret;
+
+       if (udev && udev->port_is_suspended && udev->do_remote_wakeup) {
+               ret = hub_set_port_link_state(hub, port_dev->portnum,
+                                             USB_SS_PORT_LS_U0);
+               if (!ret) {
+                       msleep(USB_RESUME_TIMEOUT);
+                       ret = usb_disable_remote_wakeup(udev);
+               }
+               if (ret)
+                       dev_warn(&udev->dev,
+                                "Port disable: can't disable remote wake\n");
+               udev->do_remote_wakeup = 0;
+       }
+}
 
 #else  /* CONFIG_PM */
 
@@ -4080,6 +4048,9 @@ EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm);
 #define hub_resume             NULL
 #define hub_reset_resume       NULL
 
+static inline void hub_usb3_port_prepare_disable(struct usb_hub *hub,
+                                                struct usb_port *port_dev) { }
+
 int usb_disable_lpm(struct usb_device *udev)
 {
        return 0;
index eb88b8bfcb11369586dc290926ff4695ac9abb85..f63a9463f87ddb4d274c464a1276ac57800d3c91 100644 (file)
@@ -144,11 +144,16 @@ int config_ep_by_speed(struct usb_gadget *g,
 
 ep_found:
        /* commit results */
-       _ep->maxpacket = usb_endpoint_maxp(chosen_desc);
+       _ep->maxpacket = usb_endpoint_maxp(chosen_desc) & 0x7ff;
        _ep->desc = chosen_desc;
        _ep->comp_desc = NULL;
        _ep->maxburst = 0;
-       _ep->mult = 0;
+       _ep->mult = 1;
+
+       if (g->speed == USB_SPEED_HIGH && (usb_endpoint_xfer_isoc(_ep->desc) ||
+                               usb_endpoint_xfer_int(_ep->desc)))
+               _ep->mult = usb_endpoint_maxp(_ep->desc) & 0x7ff;
+
        if (!want_comp_desc)
                return 0;
 
@@ -165,7 +170,7 @@ ep_found:
                switch (usb_endpoint_type(_ep->desc)) {
                case USB_ENDPOINT_XFER_ISOC:
                        /* mult: bits 1:0 of bmAttributes */
-                       _ep->mult = comp_desc->bmAttributes & 0x3;
+                       _ep->mult = (comp_desc->bmAttributes & 0x3) + 1;
                case USB_ENDPOINT_XFER_BULK:
                case USB_ENDPOINT_XFER_INT:
                        _ep->maxburst = comp_desc->bMaxBurst + 1;
index 12628dd36e55a3aea069863cd5d59ee38d5f63e9..12064d3bddf64a185608082eeb9e8194794c2843 100644 (file)
@@ -1079,13 +1079,13 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
        agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
        if (!agdev->out_ep) {
                dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
-               goto err;
+               return ret;
        }
 
        agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
        if (!agdev->in_ep) {
                dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
-               goto err;
+               return ret;
        }
 
        uac2->p_prm.uac2 = uac2;
@@ -1102,7 +1102,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
 
        ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL);
        if (ret)
-               goto err;
+               return ret;
 
        prm = &agdev->uac2.c_prm;
        prm->max_psize = hs_epout_desc.wMaxPacketSize;
@@ -1117,19 +1117,19 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
        prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
        if (!prm->rbuf) {
                prm->max_psize = 0;
-               goto err_free_descs;
+               goto err;
        }
 
        ret = alsa_uac2_init(agdev);
        if (ret)
-               goto err_free_descs;
+               goto err;
        return 0;
 
-err_free_descs:
-       usb_free_all_descriptors(fn);
 err:
        kfree(agdev->uac2.p_prm.rbuf);
        kfree(agdev->uac2.c_prm.rbuf);
+err_free_descs:
+       usb_free_all_descriptors(fn);
        return -EINVAL;
 }
 
index 3d0d5d94a62f2fe6927983ba6979784eb20eceeb..0f01c04d7cbd856581da53d6e69cba5f50b2c922 100644 (file)
@@ -243,7 +243,7 @@ uvc_video_alloc_requests(struct uvc_video *video)
 
        req_size = video->ep->maxpacket
                 * max_t(unsigned int, video->ep->maxburst, 1)
-                * (video->ep->mult + 1);
+                * (video->ep->mult);
 
        for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
                video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
index 940304c33224574439cea18d83f24b6bc763ba10..02260cfdedb135c92d219a2e5531775355973188 100644 (file)
@@ -129,6 +129,10 @@ static int uhci_pci_init(struct usb_hcd *hcd)
        if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_HP)
                uhci->wait_for_hp = 1;
 
+       /* Intel controllers use non-PME wakeup signalling */
+       if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_INTEL)
+               device_set_run_wake(uhci_dev(uhci), 1);
+
        /* Set up pointers to PCI-specific functions */
        uhci->reset_hc = uhci_pci_reset_hc;
        uhci->check_and_reset_hc = uhci_pci_check_and_reset_hc;
index e020ad28a00c9d566d24143175cb50baf1e07a90..53c90131764d6cfa24d0f28bb25a98853bba0efc 100644 (file)
@@ -296,7 +296,7 @@ static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
        rc = usb_serial_generic_open(tty, port);
        if (rc) {
                retval = rc;
-               goto exit;
+               goto err_free_cfg;
        }
 
        rc = usb_control_msg(port->serial->dev,
@@ -315,17 +315,32 @@ static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
                dev_dbg(&port->dev, "%s - enabled reading\n", __func__);
 
        rc = klsi_105_get_line_state(port, &line_state);
-       if (rc >= 0) {
-               spin_lock_irqsave(&priv->lock, flags);
-               priv->line_state = line_state;
-               spin_unlock_irqrestore(&priv->lock, flags);
-               dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__, line_state);
-               retval = 0;
-       } else
+       if (rc < 0) {
                retval = rc;
+               goto err_disable_read;
+       }
+
+       spin_lock_irqsave(&priv->lock, flags);
+       priv->line_state = line_state;
+       spin_unlock_irqrestore(&priv->lock, flags);
+       dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__,
+                       line_state);
+
+       return 0;
 
-exit:
+err_disable_read:
+       usb_control_msg(port->serial->dev,
+                            usb_sndctrlpipe(port->serial->dev, 0),
+                            KL5KUSB105A_SIO_CONFIGURE,
+                            USB_TYPE_VENDOR | USB_DIR_OUT,
+                            KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+                            0, /* index */
+                            NULL, 0,
+                            KLSI_TIMEOUT);
+       usb_serial_generic_close(port);
+err_free_cfg:
        kfree(cfg);
+
        return retval;
 }
 
index 9894e341c6ac93953a119c224729881a00682ef9..7ce31a4c7e7fd3d186e8e05b20b9a3ca52700b6c 100644 (file)
@@ -268,6 +268,8 @@ static void option_instat_callback(struct urb *urb);
 #define TELIT_PRODUCT_CC864_SINGLE             0x1006
 #define TELIT_PRODUCT_DE910_DUAL               0x1010
 #define TELIT_PRODUCT_UE910_V2                 0x1012
+#define TELIT_PRODUCT_LE922_USBCFG1            0x1040
+#define TELIT_PRODUCT_LE922_USBCFG2            0x1041
 #define TELIT_PRODUCT_LE922_USBCFG0            0x1042
 #define TELIT_PRODUCT_LE922_USBCFG3            0x1043
 #define TELIT_PRODUCT_LE922_USBCFG5            0x1045
@@ -1210,6 +1212,10 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0),
                .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG1),
+               .driver_info = (kernel_ulong_t)&telit_le910_blacklist },
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG2),
+               .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3),
                .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
        { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG5, 0xff),
@@ -1989,6 +1995,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) },
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) },
        { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
+       { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d04, 0xff) },                   /* D-Link DWM-158 */
        { USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff),                     /* D-Link DWM-221 B1 */
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
index 1be5dd048622f6c8c4f9aa805514b9fd5b5c5d7b..308600adf6e09c1737b46910b141f11d33c16f7f 100644 (file)
@@ -804,7 +804,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
 
        vma->vm_ops = &gntdev_vmops;
 
-       vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP | VM_IO;
+       vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP | VM_MIXEDMAP;
 
        if (use_ptemod)
                vma->vm_flags |= VM_DONTCOPY;
index 44d4a1e9244e74e923d7b26018d4b420aa2e1323..198aea66fe71c7d8cb24416be9332c41507173e7 100644 (file)
@@ -759,7 +759,7 @@ static bool bd_may_claim(struct block_device *bdev, struct block_device *whole,
                return true;     /* already a holder */
        else if (bdev->bd_holder != NULL)
                return false;    /* held by someone else */
-       else if (bdev->bd_contains == bdev)
+       else if (whole == bdev)
                return true;     /* is a whole device which isn't held */
 
        else if (whole->bd_holder == bd_may_claim)
@@ -1806,6 +1806,7 @@ void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg)
        spin_lock(&blockdev_superblock->s_inode_list_lock);
        list_for_each_entry(inode, &blockdev_superblock->s_inodes, i_sb_list) {
                struct address_space *mapping = inode->i_mapping;
+               struct block_device *bdev;
 
                spin_lock(&inode->i_lock);
                if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW) ||
@@ -1826,8 +1827,12 @@ void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg)
                 */
                iput(old_inode);
                old_inode = inode;
+               bdev = I_BDEV(inode);
 
-               func(I_BDEV(inode), arg);
+               mutex_lock(&bdev->bd_mutex);
+               if (bdev->bd_openers)
+                       func(bdev, arg);
+               mutex_unlock(&bdev->bd_mutex);
 
                spin_lock(&blockdev_superblock->s_inode_list_lock);
        }
index 9aba42b78253e33a2d0d1d6a06f83ba0cf122ad0..a09264d8b853312057ee3502d5ae10256b78196c 100644 (file)
@@ -70,6 +70,20 @@ void btrfs_##name(struct work_struct *arg)                           \
        normal_work_helper(work);                                       \
 }
 
+bool btrfs_workqueue_normal_congested(struct btrfs_workqueue *wq)
+{
+       /*
+        * We could compare wq->normal->pending with num_online_cpus()
+        * to support "thresh == NO_THRESHOLD" case, but it requires
+        * moving up atomic_inc/dec in thresh_queue/exec_hook. Let's
+        * postpone it until someone needs the support of that case.
+        */
+       if (wq->normal->thresh == NO_THRESHOLD)
+               return false;
+
+       return atomic_read(&wq->normal->pending) > wq->normal->thresh * 2;
+}
+
 BTRFS_WORK_HELPER(worker_helper);
 BTRFS_WORK_HELPER(delalloc_helper);
 BTRFS_WORK_HELPER(flush_delalloc_helper);
index ad4d0647d1a6c03b6b3ba9d1b4aae9a1ceff6df5..8e1d6576d7647666f3360ebde3491d65126568ae 100644 (file)
@@ -80,4 +80,5 @@ void btrfs_queue_work(struct btrfs_workqueue *wq,
 void btrfs_destroy_workqueue(struct btrfs_workqueue *wq);
 void btrfs_workqueue_set_max(struct btrfs_workqueue *wq, int max);
 void btrfs_set_work_high_priority(struct btrfs_work *work);
+bool btrfs_workqueue_normal_congested(struct btrfs_workqueue *wq);
 #endif
index 1391f72c28c30f090d7eff406d2dbf1246db60d8..e847573c6db0889abd6a26e01a90c7098583a4da 100644 (file)
@@ -3070,6 +3070,8 @@ btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu,
        cpu->target = le64_to_cpu(disk->target);
        cpu->flags = le64_to_cpu(disk->flags);
        cpu->limit = le64_to_cpu(disk->limit);
+       cpu->stripes_min = le32_to_cpu(disk->stripes_min);
+       cpu->stripes_max = le32_to_cpu(disk->stripes_max);
 }
 
 static inline void
@@ -3088,6 +3090,8 @@ btrfs_cpu_balance_args_to_disk(struct btrfs_disk_balance_args *disk,
        disk->target = cpu_to_le64(cpu->target);
        disk->flags = cpu_to_le64(cpu->flags);
        disk->limit = cpu_to_le64(cpu->limit);
+       disk->stripes_min = cpu_to_le32(cpu->stripes_min);
+       disk->stripes_max = cpu_to_le32(cpu->stripes_max);
 }
 
 /* struct btrfs_super_block */
index 02b934d0ee655c018148e1ffd21ed9d6997dd802..09fa5af9782e0dd03a8815d012d963b725934eb3 100644 (file)
@@ -1375,7 +1375,8 @@ release_path:
        total_done++;
 
        btrfs_release_prepared_delayed_node(delayed_node);
-       if (async_work->nr == 0 || total_done < async_work->nr)
+       if ((async_work->nr == 0 && total_done < BTRFS_DELAYED_WRITEBACK) ||
+           total_done < async_work->nr)
                goto again;
 
 free_path:
@@ -1391,7 +1392,8 @@ static int btrfs_wq_run_delayed_node(struct btrfs_delayed_root *delayed_root,
 {
        struct btrfs_async_delayed_work *async_work;
 
-       if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND)
+       if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND ||
+           btrfs_workqueue_normal_congested(fs_info->delayed_workers))
                return 0;
 
        async_work = kmalloc(sizeof(*async_work), GFP_NOFS);
index 47cdc6f3390b2f72f0f861c3e6de157bf49c0046..2af08c3de7752ee8d99555a1f5c3ad747c4a2a94 100644 (file)
@@ -8486,14 +8486,13 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
        ret = btrfs_lookup_extent_info(trans, root, bytenr, level - 1, 1,
                                       &wc->refs[level - 1],
                                       &wc->flags[level - 1]);
-       if (ret < 0) {
-               btrfs_tree_unlock(next);
-               return ret;
-       }
+       if (ret < 0)
+               goto out_unlock;
 
        if (unlikely(wc->refs[level - 1] == 0)) {
                btrfs_err(root->fs_info, "Missing references.");
-               BUG();
+               ret = -EIO;
+               goto out_unlock;
        }
        *lookup_info = 0;
 
@@ -8545,7 +8544,12 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
        }
 
        level--;
-       BUG_ON(level != btrfs_header_level(next));
+       ASSERT(level == btrfs_header_level(next));
+       if (level != btrfs_header_level(next)) {
+               btrfs_err(root->fs_info, "mismatched level");
+               ret = -EIO;
+               goto out_unlock;
+       }
        path->nodes[level] = next;
        path->slots[level] = 0;
        path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING;
@@ -8560,8 +8564,15 @@ skip:
                if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
                        parent = path->nodes[level]->start;
                } else {
-                       BUG_ON(root->root_key.objectid !=
+                       ASSERT(root->root_key.objectid ==
                               btrfs_header_owner(path->nodes[level]));
+                       if (root->root_key.objectid !=
+                           btrfs_header_owner(path->nodes[level])) {
+                               btrfs_err(root->fs_info,
+                                               "mismatched block owner");
+                               ret = -EIO;
+                               goto out_unlock;
+                       }
                        parent = 0;
                }
 
@@ -8578,12 +8589,18 @@ skip:
                }
                ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent,
                                root->root_key.objectid, level - 1, 0);
-               BUG_ON(ret); /* -ENOMEM */
+               if (ret)
+                       goto out_unlock;
        }
+
+       *lookup_info = 1;
+       ret = 1;
+
+out_unlock:
        btrfs_tree_unlock(next);
        free_extent_buffer(next);
-       *lookup_info = 1;
-       return 1;
+
+       return ret;
 }
 
 /*
@@ -9686,6 +9703,11 @@ int btrfs_read_block_groups(struct btrfs_root *root)
        struct extent_buffer *leaf;
        int need_clear = 0;
        u64 cache_gen;
+       u64 feature;
+       int mixed;
+
+       feature = btrfs_super_incompat_flags(info->super_copy);
+       mixed = !!(feature & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS);
 
        root = info->extent_root;
        key.objectid = 0;
@@ -9739,6 +9761,15 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                                   btrfs_item_ptr_offset(leaf, path->slots[0]),
                                   sizeof(cache->item));
                cache->flags = btrfs_block_group_flags(&cache->item);
+               if (!mixed &&
+                   ((cache->flags & BTRFS_BLOCK_GROUP_METADATA) &&
+                   (cache->flags & BTRFS_BLOCK_GROUP_DATA))) {
+                       btrfs_err(info,
+"bg %llu is a mixed block group but filesystem hasn't enabled mixed block groups",
+                                 cache->key.objectid);
+                       ret = -EINVAL;
+                       goto error;
+               }
 
                key.objectid = found_key.objectid + found_key.offset;
                btrfs_release_path(path);
index 257bbdcb5df64582236bfc9be9f721f418e957a0..e767f347f2b17b1263553e6118f5fb4592bc6216 100644 (file)
@@ -5294,11 +5294,20 @@ int read_extent_buffer_pages(struct extent_io_tree *tree,
                        lock_page(page);
                }
                locked_pages++;
+       }
+       /*
+        * We need to firstly lock all pages to make sure that
+        * the uptodate bit of our pages won't be affected by
+        * clear_extent_buffer_uptodate().
+        */
+       for (i = start_i; i < num_pages; i++) {
+               page = eb->pages[i];
                if (!PageUptodate(page)) {
                        num_reads++;
                        all_uptodate = 0;
                }
        }
+
        if (all_uptodate) {
                if (start_i == 0)
                        set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags);
index a7e18dbadf748ebaea90da93d982c2369a356833..317b99acdf4bde3016cfb9ab167fea43e27724b0 100644 (file)
@@ -3825,6 +3825,11 @@ process_slot:
                }
                btrfs_release_path(path);
                key.offset = next_key_min_offset;
+
+               if (fatal_signal_pending(current)) {
+                       ret = -EINTR;
+                       goto out;
+               }
        }
        ret = 0;
 
index bcc965ed5fa1797a5c57fb9d561033af6d973a68..88d9b66e2207c721a43b28243491cf3a11cf8dfa 100644 (file)
@@ -2283,10 +2283,6 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work)
        int err = -ENOMEM;
        int ret = 0;
 
-       mutex_lock(&fs_info->qgroup_rescan_lock);
-       fs_info->qgroup_rescan_running = true;
-       mutex_unlock(&fs_info->qgroup_rescan_lock);
-
        path = btrfs_alloc_path();
        if (!path)
                goto out;
@@ -2397,6 +2393,7 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
                sizeof(fs_info->qgroup_rescan_progress));
        fs_info->qgroup_rescan_progress.objectid = progress_objectid;
        init_completion(&fs_info->qgroup_rescan_completion);
+       fs_info->qgroup_rescan_running = true;
 
        spin_unlock(&fs_info->qgroup_lock);
        mutex_unlock(&fs_info->qgroup_rescan_lock);
index b4ca5454ef1a7ebc4fcb8eec476701bc8496a050..8ca9aa92972d2e245db81ad2f6d648e43a324861 100644 (file)
@@ -921,9 +921,16 @@ again:
                        path2->slots[level]--;
 
                eb = path2->nodes[level];
-               WARN_ON(btrfs_node_blockptr(eb, path2->slots[level]) !=
-                       cur->bytenr);
-
+               if (btrfs_node_blockptr(eb, path2->slots[level]) !=
+                   cur->bytenr) {
+                       btrfs_err(root->fs_info,
+       "couldn't find block (%llu) (level %d) in tree (%llu) with key (%llu %u %llu)",
+                                 cur->bytenr, level - 1, root->objectid,
+                                 node_key->objectid, node_key->type,
+                                 node_key->offset);
+                       err = -ENOENT;
+                       goto out;
+               }
                lower = cur;
                need_check = true;
                for (; level < BTRFS_MAX_LEVEL; level++) {
@@ -2343,6 +2350,10 @@ void free_reloc_roots(struct list_head *list)
        while (!list_empty(list)) {
                reloc_root = list_entry(list->next, struct btrfs_root,
                                        root_list);
+               free_extent_buffer(reloc_root->node);
+               free_extent_buffer(reloc_root->commit_root);
+               reloc_root->node = NULL;
+               reloc_root->commit_root = NULL;
                __del_reloc_root(reloc_root);
        }
 }
@@ -2676,11 +2687,15 @@ static int do_relocation(struct btrfs_trans_handle *trans,
 
                if (!upper->eb) {
                        ret = btrfs_search_slot(trans, root, key, path, 0, 1);
-                       if (ret < 0) {
-                               err = ret;
+                       if (ret) {
+                               if (ret < 0)
+                                       err = ret;
+                               else
+                                       err = -ENOENT;
+
+                               btrfs_release_path(path);
                                break;
                        }
-                       BUG_ON(ret > 0);
 
                        if (!upper->eb) {
                                upper->eb = path->nodes[upper->level];
index f7441193bf35aee7565d73f4a9d4e618ab00ea6d..ee7832e2d39d8147420e8fbe47e095da0c133518 100644 (file)
@@ -1923,12 +1923,11 @@ static noinline int find_dir_range(struct btrfs_root *root,
 next:
        /* check the next slot in the tree to see if it is a valid item */
        nritems = btrfs_header_nritems(path->nodes[0]);
+       path->slots[0]++;
        if (path->slots[0] >= nritems) {
                ret = btrfs_next_leaf(root, path);
                if (ret)
                        goto out;
-       } else {
-               path->slots[0]++;
        }
 
        btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
index c669a1471395e329aa7801d966597c9c0649ba93..b76883606e4b47d961785f524b1f24e35c4b63a3 100644 (file)
@@ -627,6 +627,8 @@ struct TCP_Server_Info {
 #ifdef CONFIG_CIFS_SMB2
        unsigned int    max_read;
        unsigned int    max_write;
+       struct delayed_work reconnect; /* reconnect workqueue job */
+       struct mutex reconnect_mutex; /* prevent simultaneous reconnects */
 #endif /* CONFIG_CIFS_SMB2 */
 };
 
@@ -826,6 +828,7 @@ cap_unix(struct cifs_ses *ses)
 struct cifs_tcon {
        struct list_head tcon_list;
        int tc_count;
+       struct list_head rlist; /* reconnect list */
        struct list_head openFileList;
        spinlock_t open_file_lock; /* protects list above */
        struct cifs_ses *ses;   /* pointer to session associated with */
index c63fd1dde25b861b011f604522572c5619f177f1..54590fd33df122e780069691e1e7fdacd8d58247 100644 (file)
@@ -205,6 +205,9 @@ extern void cifs_add_pending_open_locked(struct cifs_fid *fid,
                                         struct tcon_link *tlink,
                                         struct cifs_pending_open *open);
 extern void cifs_del_pending_open(struct cifs_pending_open *open);
+extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
+                                int from_reconnect);
+extern void cifs_put_tcon(struct cifs_tcon *tcon);
 
 #if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
 extern void cifs_dfs_release_automount_timer(void);
index 812a8cb07c632b855c7e4deee62d3b1eaf626e3f..5d59f25521ce12a25bd02c062756412bf234f7ab 100644 (file)
@@ -52,6 +52,9 @@
 #include "nterr.h"
 #include "rfc1002pdu.h"
 #include "fscache.h"
+#ifdef CONFIG_CIFS_SMB2
+#include "smb2proto.h"
+#endif
 
 #define CIFS_PORT 445
 #define RFC1001_PORT 139
@@ -2113,8 +2116,8 @@ cifs_find_tcp_session(struct smb_vol *vol)
        return NULL;
 }
 
-static void
-cifs_put_tcp_session(struct TCP_Server_Info *server)
+void
+cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
 {
        struct task_struct *task;
 
@@ -2131,6 +2134,19 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
 
        cancel_delayed_work_sync(&server->echo);
 
+#ifdef CONFIG_CIFS_SMB2
+       if (from_reconnect)
+               /*
+                * Avoid deadlock here: reconnect work calls
+                * cifs_put_tcp_session() at its end. Need to be sure
+                * that reconnect work does nothing with server pointer after
+                * that step.
+                */
+               cancel_delayed_work(&server->reconnect);
+       else
+               cancel_delayed_work_sync(&server->reconnect);
+#endif
+
        spin_lock(&GlobalMid_Lock);
        server->tcpStatus = CifsExiting;
        spin_unlock(&GlobalMid_Lock);
@@ -2195,6 +2211,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
        INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
        INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
        INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
+#ifdef CONFIG_CIFS_SMB2
+       INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
+       mutex_init(&tcp_ses->reconnect_mutex);
+#endif
        memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
               sizeof(tcp_ses->srcaddr));
        memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
@@ -2347,7 +2367,7 @@ cifs_put_smb_ses(struct cifs_ses *ses)
        spin_unlock(&cifs_tcp_ses_lock);
 
        sesInfoFree(ses);
-       cifs_put_tcp_session(server);
+       cifs_put_tcp_session(server, 0);
 }
 
 #ifdef CONFIG_KEYS
@@ -2521,7 +2541,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
                mutex_unlock(&ses->session_mutex);
 
                /* existing SMB ses has a server reference already */
-               cifs_put_tcp_session(server);
+               cifs_put_tcp_session(server, 0);
                free_xid(xid);
                return ses;
        }
@@ -2611,7 +2631,7 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
        return NULL;
 }
 
-static void
+void
 cifs_put_tcon(struct cifs_tcon *tcon)
 {
        unsigned int xid;
@@ -3767,7 +3787,7 @@ mount_fail_check:
                else if (ses)
                        cifs_put_smb_ses(ses);
                else
-                       cifs_put_tcp_session(server);
+                       cifs_put_tcp_session(server, 0);
                bdi_destroy(&cifs_sb->bdi);
        }
 
@@ -4078,7 +4098,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
        ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
        if (IS_ERR(ses)) {
                tcon = (struct cifs_tcon *)ses;
-               cifs_put_tcp_session(master_tcon->ses->server);
+               cifs_put_tcp_session(master_tcon->ses->server, 0);
                goto out;
        }
 
index f9e766f464beec408b628146c4e0d4e04010e0f2..b2aff0c6f22c528eb628a25247bad85b1d096a3c 100644 (file)
@@ -260,7 +260,7 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
         * and check it for zero before using.
         */
        max_buf = tlink_tcon(cfile->tlink)->ses->server->maxBuf;
-       if (!max_buf) {
+       if (max_buf < sizeof(struct smb2_lock_element)) {
                free_xid(xid);
                return -EINVAL;
        }
index 0dbbdf5e4aeeb2fc56e7a9d4df235c18c188430e..2fa754c5fd6299aecedf7969b23c31d6f33e6e80 100644 (file)
@@ -278,7 +278,7 @@ out:
        case SMB2_CHANGE_NOTIFY:
        case SMB2_QUERY_INFO:
        case SMB2_SET_INFO:
-               return -EAGAIN;
+               rc = -EAGAIN;
        }
        unload_nls(nls_codepage);
        return rc;
@@ -1822,6 +1822,54 @@ smb2_echo_callback(struct mid_q_entry *mid)
        add_credits(server, credits_received, CIFS_ECHO_OP);
 }
 
+void smb2_reconnect_server(struct work_struct *work)
+{
+       struct TCP_Server_Info *server = container_of(work,
+                                       struct TCP_Server_Info, reconnect.work);
+       struct cifs_ses *ses;
+       struct cifs_tcon *tcon, *tcon2;
+       struct list_head tmp_list;
+       int tcon_exist = false;
+
+       /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
+       mutex_lock(&server->reconnect_mutex);
+
+       INIT_LIST_HEAD(&tmp_list);
+       cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n");
+
+       spin_lock(&cifs_tcp_ses_lock);
+       list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
+               list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+                       if (tcon->need_reconnect) {
+                               tcon->tc_count++;
+                               list_add_tail(&tcon->rlist, &tmp_list);
+                               tcon_exist = true;
+                       }
+               }
+       }
+       /*
+        * Get the reference to server struct to be sure that the last call of
+        * cifs_put_tcon() in the loop below won't release the server pointer.
+        */
+       if (tcon_exist)
+               server->srv_count++;
+
+       spin_unlock(&cifs_tcp_ses_lock);
+
+       list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
+               smb2_reconnect(SMB2_ECHO, tcon);
+               list_del_init(&tcon->rlist);
+               cifs_put_tcon(tcon);
+       }
+
+       cifs_dbg(FYI, "Reconnecting tcons finished\n");
+       mutex_unlock(&server->reconnect_mutex);
+
+       /* now we can safely release srv struct */
+       if (tcon_exist)
+               cifs_put_tcp_session(server, 1);
+}
+
 int
 SMB2_echo(struct TCP_Server_Info *server)
 {
@@ -1834,32 +1882,11 @@ SMB2_echo(struct TCP_Server_Info *server)
        cifs_dbg(FYI, "In echo request\n");
 
        if (server->tcpStatus == CifsNeedNegotiate) {
-               struct list_head *tmp, *tmp2;
-               struct cifs_ses *ses;
-               struct cifs_tcon *tcon;
-
-               cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n");
-               spin_lock(&cifs_tcp_ses_lock);
-               list_for_each(tmp, &server->smb_ses_list) {
-                       ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
-                       list_for_each(tmp2, &ses->tcon_list) {
-                               tcon = list_entry(tmp2, struct cifs_tcon,
-                                                 tcon_list);
-                               /* add check for persistent handle reconnect */
-                               if (tcon && tcon->need_reconnect) {
-                                       spin_unlock(&cifs_tcp_ses_lock);
-                                       rc = smb2_reconnect(SMB2_ECHO, tcon);
-                                       spin_lock(&cifs_tcp_ses_lock);
-                               }
-                       }
-               }
-               spin_unlock(&cifs_tcp_ses_lock);
+               /* No need to send echo on newly established connections */
+               queue_delayed_work(cifsiod_wq, &server->reconnect, 0);
+               return rc;
        }
 
-       /* if no session, renegotiate failed above */
-       if (server->tcpStatus == CifsNeedNegotiate)
-               return -EIO;
-
        rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req);
        if (rc)
                return rc;
index 9bc59f9c12fb5168daf8efbc6be90bdace302f74..0a406ae78129a3fbd5676a426ca0562bd5eaea23 100644 (file)
@@ -95,6 +95,7 @@ extern int smb2_open_file(const unsigned int xid,
 extern int smb2_unlock_range(struct cifsFileInfo *cfile,
                             struct file_lock *flock, const unsigned int xid);
 extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile);
+extern void smb2_reconnect_server(struct work_struct *work);
 
 /*
  * SMB2 Worker functions - most of protocol specific implementation details
index b06623a9347f4f206fb466c80574ec4bdd7d13fa..3a6de10d38918db2dca9e3d0067b7bc0b456875f 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -19,7 +19,7 @@
  * current->executable is only used by the procfs.  This allows a dispatch
  * table to check for several different types  of binary formats.  We keep
  * trying until we recognize the file or we run out of supported binary
- * formats. 
+ * formats.
  */
 
 #include <linux/slab.h>
@@ -56,6 +56,7 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/oom.h>
 #include <linux/compat.h>
+#include <linux/user_namespace.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -1114,6 +1115,13 @@ int flush_old_exec(struct linux_binprm * bprm)
        flush_thread();
        current->personality &= ~bprm->per_clear;
 
+       /*
+        * We have to apply CLOEXEC before we change whether the process is
+        * dumpable (in setup_new_exec) to avoid a race with a process in userspace
+        * trying to access the should-be-closed file descriptors of a process
+        * undergoing exec(2).
+        */
+       do_close_on_exec(current->files);
        return 0;
 
 out:
@@ -1123,8 +1131,22 @@ EXPORT_SYMBOL(flush_old_exec);
 
 void would_dump(struct linux_binprm *bprm, struct file *file)
 {
-       if (inode_permission(file_inode(file), MAY_READ) < 0)
+       struct inode *inode = file_inode(file);
+       if (inode_permission(inode, MAY_READ) < 0) {
+               struct user_namespace *old, *user_ns;
                bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+
+               /* Ensure mm->user_ns contains the executable */
+               user_ns = old = bprm->mm->user_ns;
+               while ((user_ns != &init_user_ns) &&
+                      !privileged_wrt_inode_uidgid(user_ns, inode))
+                       user_ns = user_ns->parent;
+
+               if (old != user_ns) {
+                       bprm->mm->user_ns = get_user_ns(user_ns);
+                       put_user_ns(old);
+               }
+       }
 }
 EXPORT_SYMBOL(would_dump);
 
@@ -1154,7 +1176,6 @@ void setup_new_exec(struct linux_binprm * bprm)
            !gid_eq(bprm->cred->gid, current_egid())) {
                current->pdeath_signal = 0;
        } else {
-               would_dump(bprm, bprm->file);
                if (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)
                        set_dumpable(current->mm, suid_dumpable);
        }
@@ -1163,7 +1184,6 @@ void setup_new_exec(struct linux_binprm * bprm)
           group */
        current->self_exec_id++;
        flush_signal_handlers(current, 0);
-       do_close_on_exec(current->files);
 }
 EXPORT_SYMBOL(setup_new_exec);
 
@@ -1254,7 +1274,7 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
        unsigned n_fs;
 
        if (p->ptrace) {
-               if (p->ptrace & PT_PTRACE_CAP)
+               if (ptracer_capable(p, current_user_ns()))
                        bprm->unsafe |= LSM_UNSAFE_PTRACE_CAP;
                else
                        bprm->unsafe |= LSM_UNSAFE_PTRACE;
@@ -1587,6 +1607,8 @@ static int do_execveat_common(int fd, struct filename *filename,
        if (retval < 0)
                goto out;
 
+       would_dump(bprm, bprm->file);
+
        retval = exec_binprm(bprm);
        if (retval < 0)
                goto out;
index 5f58462110953dc61c9bd85101acd69c33a51331..f817ed58f5ad44512dbe21eb17761c1586b09422 100644 (file)
@@ -395,17 +395,19 @@ static inline int ext4_inode_journal_mode(struct inode *inode)
                return EXT4_INODE_WRITEBACK_DATA_MODE;  /* writeback */
        /* We do not support data journalling with delayed allocation */
        if (!S_ISREG(inode->i_mode) ||
-           test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
-               return EXT4_INODE_JOURNAL_DATA_MODE;    /* journal data */
-       if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
-           !test_opt(inode->i_sb, DELALLOC))
+           test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA ||
+           (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
+           !test_opt(inode->i_sb, DELALLOC))) {
+               /* We do not support data journalling for encrypted data */
+               if (S_ISREG(inode->i_mode) && ext4_encrypted_inode(inode))
+                       return EXT4_INODE_ORDERED_DATA_MODE;  /* ordered */
                return EXT4_INODE_JOURNAL_DATA_MODE;    /* journal data */
+       }
        if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
                return EXT4_INODE_ORDERED_DATA_MODE;    /* ordered */
        if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
                return EXT4_INODE_WRITEBACK_DATA_MODE;  /* writeback */
-       else
-               BUG();
+       BUG();
 }
 
 static inline int ext4_should_journal_data(struct inode *inode)
index af34979684a4df6f7f35f22a4cf30bcb57007a1b..43dcaab8520186d6dbac69c21d7ae5d677402b2b 100644 (file)
@@ -337,8 +337,10 @@ static int ext4_update_inline_data(handle_t *handle, struct inode *inode,
 
        len -= EXT4_MIN_INLINE_DATA_SIZE;
        value = kzalloc(len, GFP_NOFS);
-       if (!value)
+       if (!value) {
+               error = -ENOMEM;
                goto out;
+       }
 
        error = ext4_xattr_ibody_get(inode, i.name_index, i.name,
                                     value, len);
index a4149cc2c6c0e329e2060ce83b5644bf46cfcf50..c33fcb4f8533cb4632b146b8cc6a59d94cb064be 100644 (file)
@@ -4202,6 +4202,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
        struct inode *inode;
        journal_t *journal = EXT4_SB(sb)->s_journal;
        long ret;
+       loff_t size;
        int block;
        uid_t i_uid;
        gid_t i_gid;
@@ -4293,6 +4294,11 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
                ei->i_file_acl |=
                        ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
        inode->i_size = ext4_isize(raw_inode);
+       if ((size = i_size_read(inode)) < 0) {
+               EXT4_ERROR_INODE(inode, "bad i_size value: %lld", size);
+               ret = -EFSCORRUPTED;
+               goto bad_inode;
+       }
        ei->i_disksize = inode->i_size;
 #ifdef CONFIG_QUOTA
        ei->i_reserved_quota = 0;
index 0b1c97875686bbe2732c0dbb9cb2a131c4d52c80..be1227c196d88471bb0aac3a6604c54e160bf45d 100644 (file)
@@ -669,7 +669,7 @@ static void ext4_mb_mark_free_simple(struct super_block *sb,
        ext4_grpblk_t min;
        ext4_grpblk_t max;
        ext4_grpblk_t chunk;
-       unsigned short border;
+       unsigned int border;
 
        BUG_ON(len > EXT4_CLUSTERS_PER_GROUP(sb));
 
@@ -2287,7 +2287,7 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
        struct ext4_group_info *grinfo;
        struct sg {
                struct ext4_group_info info;
-               ext4_grpblk_t counters[16];
+               ext4_grpblk_t counters[EXT4_MAX_BLOCK_LOG_SIZE + 2];
        } sg;
 
        group--;
index 127155b82e6e1d67f6f21cd5d6c9eeeee0bffed3..68640e6f95c597f808cde4db724659b1fc08ad55 100644 (file)
@@ -3037,10 +3037,15 @@ static int count_overhead(struct super_block *sb, ext4_group_t grp,
                        ext4_set_bit(s++, buf);
                        count++;
                }
-               for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) {
-                       ext4_set_bit(EXT4_B2C(sbi, s++), buf);
-                       count++;
+               j = ext4_bg_num_gdb(sb, grp);
+               if (s + j > EXT4_BLOCKS_PER_GROUP(sb)) {
+                       ext4_error(sb, "Invalid number of block group "
+                                  "descriptor blocks: %d", j);
+                       j = EXT4_BLOCKS_PER_GROUP(sb) - s;
                }
+               count += j;
+               for (; j > 0; j--)
+                       ext4_set_bit(EXT4_B2C(sbi, s++), buf);
        }
        if (!count)
                return 0;
@@ -3130,7 +3135,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        char *orig_data = kstrdup(data, GFP_KERNEL);
        struct buffer_head *bh;
        struct ext4_super_block *es = NULL;
-       struct ext4_sb_info *sbi;
+       struct ext4_sb_info *sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        ext4_fsblk_t block;
        ext4_fsblk_t sb_block = get_sb_block(&data);
        ext4_fsblk_t logical_sb_block;
@@ -3149,16 +3154,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
        ext4_group_t first_not_zeroed;
 
-       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-       if (!sbi)
-               goto out_free_orig;
+       if ((data && !orig_data) || !sbi)
+               goto out_free_base;
 
        sbi->s_blockgroup_lock =
                kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL);
-       if (!sbi->s_blockgroup_lock) {
-               kfree(sbi);
-               goto out_free_orig;
-       }
+       if (!sbi->s_blockgroup_lock)
+               goto out_free_base;
+
        sb->s_fs_info = sbi;
        sbi->s_sb = sb;
        sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS;
@@ -3304,11 +3307,19 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
         */
        sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
 
-       if (!parse_options((char *) sbi->s_es->s_mount_opts, sb,
-                          &journal_devnum, &journal_ioprio, 0)) {
-               ext4_msg(sb, KERN_WARNING,
-                        "failed to parse options in superblock: %s",
-                        sbi->s_es->s_mount_opts);
+       if (sbi->s_es->s_mount_opts[0]) {
+               char *s_mount_opts = kstrndup(sbi->s_es->s_mount_opts,
+                                             sizeof(sbi->s_es->s_mount_opts),
+                                             GFP_KERNEL);
+               if (!s_mount_opts)
+                       goto failed_mount;
+               if (!parse_options(s_mount_opts, sb, &journal_devnum,
+                                  &journal_ioprio, 0)) {
+                       ext4_msg(sb, KERN_WARNING,
+                                "failed to parse options in superblock: %s",
+                                s_mount_opts);
+               }
+               kfree(s_mount_opts);
        }
        sbi->s_def_mount_opt = sbi->s_mount_opt;
        if (!parse_options((char *) data, sb, &journal_devnum,
@@ -3334,6 +3345,11 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                                 "both data=journal and dax");
                        goto failed_mount;
                }
+               if (ext4_has_feature_encrypt(sb)) {
+                       ext4_msg(sb, KERN_WARNING,
+                                "encrypted files will use data=ordered "
+                                "instead of data journaling mode");
+               }
                if (test_opt(sb, DELALLOC))
                        clear_opt(sb, DELALLOC);
        } else {
@@ -3496,12 +3512,16 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 
        sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
        sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
-       if (EXT4_INODE_SIZE(sb) == 0 || EXT4_INODES_PER_GROUP(sb) == 0)
-               goto cantfind_ext4;
 
        sbi->s_inodes_per_block = blocksize / EXT4_INODE_SIZE(sb);
        if (sbi->s_inodes_per_block == 0)
                goto cantfind_ext4;
+       if (sbi->s_inodes_per_group < sbi->s_inodes_per_block ||
+           sbi->s_inodes_per_group > blocksize * 8) {
+               ext4_msg(sb, KERN_ERR, "invalid inodes per group: %lu\n",
+                        sbi->s_blocks_per_group);
+               goto failed_mount;
+       }
        sbi->s_itb_per_group = sbi->s_inodes_per_group /
                                        sbi->s_inodes_per_block;
        sbi->s_desc_per_block = blocksize / EXT4_DESC_SIZE(sb);
@@ -3584,13 +3604,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        }
        sbi->s_cluster_ratio = clustersize / blocksize;
 
-       if (sbi->s_inodes_per_group > blocksize * 8) {
-               ext4_msg(sb, KERN_ERR,
-                      "#inodes per group too big: %lu",
-                      sbi->s_inodes_per_group);
-               goto failed_mount;
-       }
-
        /* Do we have standard group size of clustersize * 8 blocks ? */
        if (sbi->s_blocks_per_group == clustersize << 3)
                set_opt2(sb, STD_GROUP_SIZE);
@@ -3994,7 +4007,9 @@ no_journal:
 
        if (___ratelimit(&ext4_mount_msg_ratelimit, "EXT4-fs mount"))
                ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
-                        "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
+                        "Opts: %.*s%s%s", descr,
+                        (int) sizeof(sbi->s_es->s_mount_opts),
+                        sbi->s_es->s_mount_opts,
                         *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
 
        if (es->s_error_count)
@@ -4064,8 +4079,8 @@ failed_mount:
 out_fail:
        sb->s_fs_info = NULL;
        kfree(sbi->s_blockgroup_lock);
+out_free_base:
        kfree(sbi);
-out_free_orig:
        kfree(orig_data);
        return err ? err : ret;
 }
index 478e5d54154f5b8e1faed3f5b2414c43475b06d5..24d6a51b48d1ff17911dc27fd38db14e75ccf3e1 100644 (file)
@@ -352,6 +352,7 @@ static int stat_open(struct inode *inode, struct file *file)
 }
 
 static const struct file_operations stat_fops = {
+       .owner = THIS_MODULE,
        .open = stat_open,
        .read = seq_read,
        .llseek = seq_lseek,
index 93e236429c5d785a1711d643d0b4676dfe4396cf..dc875cd0e11d52386c893ee83c1c71ff40f855ef 100644 (file)
@@ -407,7 +407,7 @@ static int nfs_write_end(struct file *file, struct address_space *mapping,
         */
        if (!PageUptodate(page)) {
                unsigned pglen = nfs_page_length(page);
-               unsigned end = offset + len;
+               unsigned end = offset + copied;
 
                if (pglen == 0) {
                        zero_user_segments(page, 0, offset,
index 5991cdcb9040970609b779c6f20cb72577c2ec37..8cab78eeb0c252a4677d174f3d9cc700d3b034d3 100644 (file)
@@ -3980,6 +3980,7 @@ xlog_recover_clear_agi_bucket(
        agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
        offset = offsetof(xfs_agi_t, agi_unlinked) +
                 (sizeof(xfs_agino_t) * bucket);
+       xfs_trans_buf_set_type(tp, agibp, XFS_BLFT_AGI_BUF);
        xfs_trans_log_buf(tp, agibp, offset,
                          (offset + sizeof(xfs_agino_t) - 1));
 
index 5f8249d378a237445cdf678a2fc3e567cbc00217..2654f75a4c46afff3644a69cfd3f01150e8a54a4 100644 (file)
@@ -247,8 +247,10 @@ static inline bool ns_capable_noaudit(struct user_namespace *ns, int cap)
        return true;
 }
 #endif /* CONFIG_MULTIUSER */
+extern bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct inode *inode);
 extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
 extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
+extern bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns);
 
 /* audit system wants to get cap info from files as well */
 extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
index eeae401a2412e5e8d32381805be1c13798b7a8fb..287e698c28deec27e8b9245de540b1b69914b9b7 100644 (file)
 #endif
 #endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */
 
-#if GCC_VERSION >= 50000
+#if GCC_VERSION >= 70000
+#define KASAN_ABI_VERSION 5
+#elif GCC_VERSION >= 50000
 #define KASAN_ABI_VERSION 4
 #elif GCC_VERSION >= 40902
 #define KASAN_ABI_VERSION 3
index 7c73824def83a9e7dda328a79485d830df375361..1c95ef5a6ed91d5b99a89a2069234f019f9a2639 100644 (file)
@@ -131,22 +131,16 @@ enum {
                { .notifier_call = fn, .priority = pri };       \
        __register_cpu_notifier(&fn##_nb);                      \
 }
-#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
-#define cpu_notifier(fn, pri)  do { (void)(fn); } while (0)
-#define __cpu_notifier(fn, pri)        do { (void)(fn); } while (0)
-#endif /* #else #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
 
-#ifdef CONFIG_HOTPLUG_CPU
 extern int register_cpu_notifier(struct notifier_block *nb);
 extern int __register_cpu_notifier(struct notifier_block *nb);
 extern void unregister_cpu_notifier(struct notifier_block *nb);
 extern void __unregister_cpu_notifier(struct notifier_block *nb);
-#else
 
-#ifndef MODULE
-extern int register_cpu_notifier(struct notifier_block *nb);
-extern int __register_cpu_notifier(struct notifier_block *nb);
-#else
+#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
+#define cpu_notifier(fn, pri)  do { (void)(fn); } while (0)
+#define __cpu_notifier(fn, pri)        do { (void)(fn); } while (0)
+
 static inline int register_cpu_notifier(struct notifier_block *nb)
 {
        return 0;
@@ -156,7 +150,6 @@ static inline int __register_cpu_notifier(struct notifier_block *nb)
 {
        return 0;
 }
-#endif
 
 static inline void unregister_cpu_notifier(struct notifier_block *nb)
 {
index 0a732c5e0de1a0a880ae10048566df7a0af9ae50..af25bc12472bfb9a7f7a79a7c452a0745861ae40 100644 (file)
@@ -476,6 +476,7 @@ struct mm_struct {
         */
        struct task_struct __rcu *owner;
 #endif
+       struct user_namespace *user_ns;
 
        /* store ref to file /proc/<pid>/exe symlink points to */
        struct file __rcu *exe_file;
index 1d1cfbac9f251214b001be9bfa532e5bf41241a8..c51d2798643c40ce4258a3892b821a8576d60f0c 100644 (file)
@@ -1805,6 +1805,20 @@ static inline int pci_pcie_type(const struct pci_dev *dev)
        return (pcie_caps_reg(dev) & PCI_EXP_FLAGS_TYPE) >> 4;
 }
 
+static inline struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
+{
+       while (1) {
+               if (!pci_is_pcie(dev))
+                       break;
+               if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
+                       return dev;
+               if (!dev->bus->self)
+                       break;
+               dev = dev->bus->self;
+       }
+       return NULL;
+}
+
 void pci_request_acs(void);
 bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags);
 bool pci_acs_path_enabled(struct pci_dev *start,
index 504c98a278d46606d27f09d109589e0a1e2263d8..e13bfdf7f314784e326b245e1f1ab5465da9e7dc 100644 (file)
@@ -19,7 +19,6 @@
 #define PT_SEIZED      0x00010000      /* SEIZE used, enable new behavior */
 #define PT_PTRACED     0x00000001
 #define PT_DTRACE      0x00000002      /* delayed trace (used on m68k, i386) */
-#define PT_PTRACE_CAP  0x00000004      /* ptracer can follow suid-exec */
 
 #define PT_OPT_FLAG_SHIFT      3
 /* PT_TRACE_* event enable flags */
index ede29e8db82ddaa03698dd9a778124b935e204fd..8be9f0dbdd0cc0daf426ae7b0e704e407fe295d5 100644 (file)
@@ -1626,6 +1626,7 @@ struct task_struct {
        struct list_head cpu_timers[3];
 
 /* process credentials */
+       const struct cred __rcu *ptracer_cred; /* Tracer's credentials at attach */
        const struct cred __rcu *real_cred; /* objective and real subjective task
                                         * credentials (COW) */
        const struct cred __rcu *cred;  /* effective (overridable) subjective task
index 5f9c59da978bb19cf87e96526769e36a3b78e880..e2225109b816a2ed45a0847830b202098bc211ea 100644 (file)
@@ -101,12 +101,12 @@ int iov_iter_npages(const struct iov_iter *i, int maxpages);
 
 const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags);
 
-static inline size_t iov_iter_count(struct iov_iter *i)
+static inline size_t iov_iter_count(const struct iov_iter *i)
 {
        return i->count;
 }
 
-static inline bool iter_is_iovec(struct iov_iter *i)
+static inline bool iter_is_iovec(const struct iov_iter *i)
 {
        return !(i->type & (ITER_BVEC | ITER_KVEC));
 }
index 2c7bdb81d30c80725b9e7d704f908609a38da6b8..b5f3693fe5b614172fb089674c9999980772621d 100644 (file)
@@ -4257,6 +4257,17 @@ void cfg80211_rx_assoc_resp(struct net_device *dev,
  */
 void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss);
 
+/**
+ * cfg80211_abandon_assoc - notify cfg80211 of abandoned association attempt
+ * @dev: network device
+ * @bss: The BSS entry with which association was abandoned.
+ *
+ * Call this whenever - for reasons reported through other API, like deauth RX,
+ * an association attempt was abandoned.
+ * This function may sleep. The caller must hold the corresponding wdev's mutex.
+ */
+void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss);
+
 /**
  * cfg80211_tx_mlme_mgmt - notification of transmitted deauth/disassoc frame
  * @dev: network device
index bdd985f41022416ea04594b2a4ae7b6676d1d111..bd2b5c00756161e001491ebac83aa952cdb0715b 100644 (file)
@@ -8,6 +8,11 @@
 #include <net/flow.h>
 #include <net/rtnetlink.h>
 
+struct fib_kuid_range {
+       kuid_t start;
+       kuid_t end;
+};
+
 struct fib_rule {
        struct list_head        list;
        int                     iifindex;
@@ -29,8 +34,7 @@ struct fib_rule {
        int                     suppress_prefixlen;
        char                    iifname[IFNAMSIZ];
        char                    oifname[IFNAMSIZ];
-       kuid_t                  uid_start;
-       kuid_t                  uid_end;
+       struct fib_kuid_range   uid_range;
        struct rcu_head         rcu;
 };
 
@@ -89,11 +93,10 @@ struct fib_rules_ops {
        [FRA_FWMARK]    = { .type = NLA_U32 }, \
        [FRA_FWMASK]    = { .type = NLA_U32 }, \
        [FRA_TABLE]     = { .type = NLA_U32 }, \
-       [FRA_UID_START] = { .type = NLA_U32 }, \
-       [FRA_UID_END]   = { .type = NLA_U32 }, \
        [FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32 }, \
        [FRA_SUPPRESS_IFGROUP] = { .type = NLA_U32 }, \
-       [FRA_GOTO]      = { .type = NLA_U32 }
+       [FRA_GOTO]      = { .type = NLA_U32 }, \
+       [FRA_UID_RANGE] = { .len = sizeof(struct fib_rule_uid_range) }
 
 static inline void fib_rule_get(struct fib_rule *rule)
 {
index ba82feec2590f401b5a332ebf47b72c1f3319b7e..af0e8c081191b1a1b49221cb8536b1c2822df735 100644 (file)
@@ -118,7 +118,8 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
 void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, int oif,
                     u32 mark, kuid_t uid);
 void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu);
-void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
+void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
+                 kuid_t uid);
 void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
                            u32 mark);
 void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
index d016a8cb45cfb14684bbec4b04702592d65c72e9..3adb9c724818d080293b5dee2bae98c2ddaee958 100644 (file)
@@ -154,8 +154,7 @@ static inline struct rtable *ip_route_output_ports(struct net *net, struct flowi
        flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos,
                           RT_SCOPE_UNIVERSE, proto,
                           sk ? inet_sk_flowi_flags(sk) : 0,
-                          daddr, saddr, dport, sport,
-                          sk ? sock_i_uid(sk) : GLOBAL_ROOT_UID);
+                          daddr, saddr, dport, sport, sock_net_uid(net, sk));
        if (sk)
                security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
        return ip_route_output_flow(net, fl4, sk);
@@ -269,7 +268,7 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32
 
        flowi4_init_output(fl4, oif, sk->sk_mark, tos, RT_SCOPE_UNIVERSE,
                           protocol, flow_flags, dst, src, dport, sport,
-                          sock_i_uid(sk));
+                          sk->sk_uid);
 }
 
 static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
index 8f77df63a8f46670d8ff9be2be3b62d4e76032f8..62c9e2268d635d1341133df6f0cfe0c4c8978a02 100644 (file)
@@ -446,6 +446,7 @@ struct sock {
        void                    *sk_security;
 #endif
        __u32                   sk_mark;
+       kuid_t                  sk_uid;
 #ifdef CONFIG_CGROUP_NET_CLASSID
        u32                     sk_classid;
 #endif
@@ -1692,6 +1693,7 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
        sk->sk_wq = parent->wq;
        parent->sk = sk;
        sk_set_socket(sk, parent);
+       sk->sk_uid = SOCK_INODE(parent)->i_uid;
        security_sock_graft(sk, parent);
        write_unlock_bh(&sk->sk_callback_lock);
 }
@@ -1699,6 +1701,11 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
 kuid_t sock_i_uid(struct sock *sk);
 unsigned long sock_i_ino(struct sock *sk);
 
+static inline kuid_t sock_net_uid(const struct net *net, const struct sock *sk)
+{
+       return sk ? sk->sk_uid : make_kuid(net->user_ns, 0);
+}
+
 static inline u32 net_tx_rndhash(void)
 {
        u32 v = prandom_u32();
index 11528591d0d714f3ea1004566cb799952a9ca5bd..a78ff97eb249fa068b9e1f00387e86861add22eb 100644 (file)
@@ -197,10 +197,12 @@ static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr,
 
        dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
        if (dev) {
-               ip4 = (struct in_device *)dev->ip_ptr;
-               if (ip4 && ip4->ifa_list && ip4->ifa_list->ifa_address)
+               ip4 = in_dev_get(dev);
+               if (ip4 && ip4->ifa_list && ip4->ifa_list->ifa_address) {
                        ipv6_addr_set_v4mapped(ip4->ifa_list->ifa_address,
                                               (struct in6_addr *)gid);
+                       in_dev_put(ip4);
+               }
                dev_put(dev);
        }
 }
index 49cc7c3de25221f2e014c80f12189bb1edc3b946..89d009e1093876cd9d0bfec3b14592cc4e75dc26 100644 (file)
@@ -57,7 +57,7 @@ TRACE_EVENT(net_dev_start_xmit,
                __entry->gso_type = skb_shinfo(skb)->gso_type;
        ),
 
-       TP_printk("dev=%s queue_mapping=%u skbaddr=%p vlan_tagged=%d vlan_proto=0x%04x vlan_tci=0x%04x protocol=0x%04x ip_summed=%d len=%u data_len=%u network_offset=%d transport_offset_valid=%d transport_offset=%d tx_flags=%d gso_size=%d gso_segs=%d gso_type=%#x",
+       TP_printk("dev=%s queue_mapping=%u skbaddr=%pK vlan_tagged=%d vlan_proto=0x%04x vlan_tci=0x%04x protocol=0x%04x ip_summed=%d len=%u data_len=%u network_offset=%d transport_offset_valid=%d transport_offset=%d tx_flags=%d gso_size=%d gso_segs=%d gso_type=%#x",
                  __get_str(name), __entry->queue_mapping, __entry->skbaddr,
                  __entry->vlan_tagged, __entry->vlan_proto, __entry->vlan_tci,
                  __entry->protocol, __entry->ip_summed, __entry->len,
@@ -90,7 +90,7 @@ TRACE_EVENT(net_dev_xmit,
                __assign_str(name, dev->name);
        ),
 
-       TP_printk("dev=%s skbaddr=%p len=%u rc=%d",
+       TP_printk("dev=%s skbaddr=%pK len=%u rc=%d",
                __get_str(name), __entry->skbaddr, __entry->len, __entry->rc)
 );
 
@@ -112,7 +112,7 @@ DECLARE_EVENT_CLASS(net_dev_template,
                __assign_str(name, skb->dev->name);
        ),
 
-       TP_printk("dev=%s skbaddr=%p len=%u",
+       TP_printk("dev=%s skbaddr=%pK len=%u",
                __get_str(name), __entry->skbaddr, __entry->len)
 )
 
@@ -191,7 +191,7 @@ DECLARE_EVENT_CLASS(net_dev_rx_verbose_template,
                __entry->gso_type = skb_shinfo(skb)->gso_type;
        ),
 
-       TP_printk("dev=%s napi_id=%#x queue_mapping=%u skbaddr=%p vlan_tagged=%d vlan_proto=0x%04x vlan_tci=0x%04x protocol=0x%04x ip_summed=%d hash=0x%08x l4_hash=%d len=%u data_len=%u truesize=%u mac_header_valid=%d mac_header=%d nr_frags=%d gso_size=%d gso_type=%#x",
+       TP_printk("dev=%s napi_id=%#x queue_mapping=%u skbaddr=%pK vlan_tagged=%d vlan_proto=0x%04x vlan_tci=0x%04x protocol=0x%04x ip_summed=%d hash=0x%08x l4_hash=%d len=%u data_len=%u truesize=%u mac_header_valid=%d mac_header=%d nr_frags=%d gso_size=%d gso_type=%#x",
                  __get_str(name), __entry->napi_id, __entry->queue_mapping,
                  __entry->skbaddr, __entry->vlan_tagged, __entry->vlan_proto,
                  __entry->vlan_tci, __entry->protocol, __entry->ip_summed,
index dffaffab4bc88696b8c8d0cbb98f518341648fd7..c18d8c89bd12f9ef174f15ae3fba028ad32c3596 100644 (file)
@@ -1044,7 +1044,7 @@ TRACE_EVENT(walt_update_history,
                __field(         int,   samples                 )
                __field(         int,   evt                     )
                __field(         u64,   demand                  )
-               __field(unsigned int,   walt_avg                )
+               __field(         u64,   walt_avg                )
                __field(unsigned int,   pelt_avg                )
                __array(         u32,   hist, RAVG_HIST_SIZE_MAX)
                __field(         int,   cpu                     )
@@ -1066,7 +1066,7 @@ TRACE_EVENT(walt_update_history,
        ),
 
        TP_printk("%d (%s): runtime %u samples %d event %d demand %llu"
-               " walt %u pelt %u (hist: %u %u %u %u %u) cpu %d",
+               " walt %llu pelt %u (hist: %u %u %u %u %u) cpu %d",
                __entry->pid, __entry->comm,
                __entry->runtime, __entry->samples, __entry->evt,
                __entry->demand,
index 9692cda5f8fc2fe7789de59f93281cf4c0bd2a5e..c48d93a28d1acbb905b5d62cb2e8436c20ec8c7e 100644 (file)
@@ -196,5 +196,6 @@ struct can_filter {
 };
 
 #define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */
+#define CAN_RAW_FILTER_MAX 512 /* maximum number of can_filter set via setsockopt() */
 
 #endif /* !_UAPI_CAN_H */
index ce19c5bf51f7ed279ae23cd64afebec322bb187e..bbf02a63a01133351ea49392f1bb06da13b4130d 100644 (file)
@@ -29,6 +29,11 @@ struct fib_rule_hdr {
        __u32           flags;
 };
 
+struct fib_rule_uid_range {
+       __u32           start;
+       __u32           end;
+};
+
 enum {
        FRA_UNSPEC,
        FRA_DST,        /* destination address */
@@ -49,8 +54,9 @@ enum {
        FRA_TABLE,      /* Extended table id */
        FRA_FWMASK,     /* mask for netfilter mark */
        FRA_OIFNAME,
-       FRA_UID_START,  /* UID range */
-       FRA_UID_END,
+       FRA_PAD,
+       FRA_L3MDEV,     /* iif or oif is l3mdev goto its table */
+       FRA_UID_RANGE,  /* UID range */
        __FRA_MAX
 };
 
index a2fad11894ffd16e5640ad3501eed3aca4b60438..d7d7599b112a990c9a50c717b9c45a5ea2c4bad6 100644 (file)
@@ -306,12 +306,14 @@ enum rtattr_type_t {
        RTA_TABLE,
        RTA_MARK,
        RTA_MFC_STATS,
-       RTA_UID,
        RTA_VIA,
        RTA_NEWDST,
        RTA_PREF,
        RTA_ENCAP_TYPE,
        RTA_ENCAP,
+       RTA_EXPIRES,
+       RTA_PAD,
+       RTA_UID,
        __RTA_MAX
 };
 
index 00411c82dac57c4cac0254c823f9adcb2a951549..4984e1f552ebfb97fa460b527b35c67ebd0f324d 100644 (file)
@@ -456,6 +456,19 @@ bool file_ns_capable(const struct file *file, struct user_namespace *ns,
 }
 EXPORT_SYMBOL(file_ns_capable);
 
+/**
+ * privileged_wrt_inode_uidgid - Do capabilities in the namespace work over the inode?
+ * @ns: The user namespace in question
+ * @inode: The inode in question
+ *
+ * Return true if the inode uid and gid are within the namespace.
+ */
+bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct inode *inode)
+{
+       return kuid_has_mapping(ns, inode->i_uid) &&
+               kgid_has_mapping(ns, inode->i_gid);
+}
+
 /**
  * capable_wrt_inode_uidgid - Check nsown_capable and uid and gid mapped
  * @inode: The inode in question
@@ -469,7 +482,26 @@ bool capable_wrt_inode_uidgid(const struct inode *inode, int cap)
 {
        struct user_namespace *ns = current_user_ns();
 
-       return ns_capable(ns, cap) && kuid_has_mapping(ns, inode->i_uid) &&
-               kgid_has_mapping(ns, inode->i_gid);
+       return ns_capable(ns, cap) && privileged_wrt_inode_uidgid(ns, inode);
 }
 EXPORT_SYMBOL(capable_wrt_inode_uidgid);
+
+/**
+ * ptracer_capable - Determine if the ptracer holds CAP_SYS_PTRACE in the namespace
+ * @tsk: The task that may be ptraced
+ * @ns: The user namespace to search for CAP_SYS_PTRACE in
+ *
+ * Return true if the task that is ptracing the current task had CAP_SYS_PTRACE
+ * in the specified user namespace.
+ */
+bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns)
+{
+       int ret = 0;  /* An absent tracer adds no restrictions */
+       const struct cred *cred;
+       rcu_read_lock();
+       cred = rcu_dereference(tsk->ptracer_cred);
+       if (cred)
+               ret = security_capable_noaudit(cred, ns, CAP_SYS_PTRACE);
+       rcu_read_unlock();
+       return (ret == 0);
+}
index c8a1751be2244233f7ebeea0db601593b3e468a3..a2dd1d7af74f869a1483ea493ba80c867e74b2c5 100644 (file)
@@ -232,8 +232,6 @@ static int cpu_notify(unsigned long val, void *v)
        return __cpu_notify(val, v, -1, NULL);
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-
 static void cpu_notify_nofail(unsigned long val, void *v)
 {
        BUG_ON(cpu_notify(val, v));
@@ -255,6 +253,7 @@ void __unregister_cpu_notifier(struct notifier_block *nb)
 }
 EXPORT_SYMBOL(__unregister_cpu_notifier);
 
+#ifdef CONFIG_HOTPLUG_CPU
 /**
  * clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU
  * @cpu: a CPU id
index 0874e2edd2756bcbe5542a496fb6b131b092b3ea..79517e5549f119aff663ff5572507c70671a2b41 100644 (file)
@@ -598,11 +598,11 @@ return_normal:
        /*
         * Wait for the other CPUs to be notified and be waiting for us:
         */
-       time_left = loops_per_jiffy * HZ;
+       time_left = MSEC_PER_SEC;
        while (kgdb_do_roundup && --time_left &&
               (atomic_read(&masters_in_kgdb) + atomic_read(&slaves_in_kgdb)) !=
                   online_cpus)
-               cpu_relax();
+               udelay(1000);
        if (!time_left)
                pr_crit("Timed out waiting for secondary CPUs.\n");
 
index 18a5cb17035a1b23c9df9323ee05da774ad6e60b..c85efa77e82528c4ea55aae0e3ccff1836c1fab8 100644 (file)
@@ -585,7 +585,8 @@ static void mm_init_owner(struct mm_struct *mm, struct task_struct *p)
 #endif
 }
 
-static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
+static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
+       struct user_namespace *user_ns)
 {
        mm->mmap = NULL;
        mm->mm_rb = RB_ROOT;
@@ -625,6 +626,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p)
        if (init_new_context(p, mm))
                goto fail_nocontext;
 
+       mm->user_ns = get_user_ns(user_ns);
        return mm;
 
 fail_nocontext:
@@ -670,7 +672,7 @@ struct mm_struct *mm_alloc(void)
                return NULL;
 
        memset(mm, 0, sizeof(*mm));
-       return mm_init(mm, current);
+       return mm_init(mm, current, current_user_ns());
 }
 
 /*
@@ -685,6 +687,7 @@ void __mmdrop(struct mm_struct *mm)
        destroy_context(mm);
        mmu_notifier_mm_destroy(mm);
        check_mm(mm);
+       put_user_ns(mm->user_ns);
        free_mm(mm);
 }
 EXPORT_SYMBOL_GPL(__mmdrop);
@@ -943,7 +946,7 @@ static struct mm_struct *dup_mm(struct task_struct *tsk)
 
        memcpy(mm, oldmm, sizeof(*mm));
 
-       if (!mm_init(mm, tsk))
+       if (!mm_init(mm, tsk, mm->user_ns))
                goto fail_nomem;
 
        err = dup_mmap(mm, oldmm);
index 8251e75dd9c0bd67337754baf6f03fb2cf1f956f..b066724d7a5beb8717e1e200bdb91c93c51771b3 100644 (file)
@@ -65,8 +65,72 @@ static inline void clear_rt_mutex_waiters(struct rt_mutex *lock)
 
 static void fixup_rt_mutex_waiters(struct rt_mutex *lock)
 {
-       if (!rt_mutex_has_waiters(lock))
-               clear_rt_mutex_waiters(lock);
+       unsigned long owner, *p = (unsigned long *) &lock->owner;
+
+       if (rt_mutex_has_waiters(lock))
+               return;
+
+       /*
+        * The rbtree has no waiters enqueued, now make sure that the
+        * lock->owner still has the waiters bit set, otherwise the
+        * following can happen:
+        *
+        * CPU 0        CPU 1           CPU2
+        * l->owner=T1
+        *              rt_mutex_lock(l)
+        *              lock(l->lock)
+        *              l->owner = T1 | HAS_WAITERS;
+        *              enqueue(T2)
+        *              boost()
+        *                unlock(l->lock)
+        *              block()
+        *
+        *                              rt_mutex_lock(l)
+        *                              lock(l->lock)
+        *                              l->owner = T1 | HAS_WAITERS;
+        *                              enqueue(T3)
+        *                              boost()
+        *                                unlock(l->lock)
+        *                              block()
+        *              signal(->T2)    signal(->T3)
+        *              lock(l->lock)
+        *              dequeue(T2)
+        *              deboost()
+        *                unlock(l->lock)
+        *                              lock(l->lock)
+        *                              dequeue(T3)
+        *                               ==> wait list is empty
+        *                              deboost()
+        *                               unlock(l->lock)
+        *              lock(l->lock)
+        *              fixup_rt_mutex_waiters()
+        *                if (wait_list_empty(l) {
+        *                  l->owner = owner
+        *                  owner = l->owner & ~HAS_WAITERS;
+        *                    ==> l->owner = T1
+        *                }
+        *                              lock(l->lock)
+        * rt_mutex_unlock(l)           fixup_rt_mutex_waiters()
+        *                                if (wait_list_empty(l) {
+        *                                  owner = l->owner & ~HAS_WAITERS;
+        * cmpxchg(l->owner, T1, NULL)
+        *  ===> Success (l->owner = NULL)
+        *
+        *                                  l->owner = owner
+        *                                    ==> l->owner = T1
+        *                                }
+        *
+        * With the check for the waiter bit in place T3 on CPU2 will not
+        * overwrite. All tasks fiddling with the waiters bit are
+        * serialized by l->lock, so nothing else can modify the waiters
+        * bit. If the bit is set then nothing can change l->owner either
+        * so the simple RMW is safe. The cmpxchg() will simply fail if it
+        * happens in the middle of the RMW because the waiters bit is
+        * still set.
+        */
+       owner = READ_ONCE(*p);
+       if (owner & RT_MUTEX_HAS_WAITERS)
+               WRITE_ONCE(*p, owner & ~RT_MUTEX_HAS_WAITERS);
 }
 
 /*
index 4f5f83c7d2d3515cb31dce798815e9614155d291..e317e1cbb3eba80098fa018de8573c1a1c7a86c0 100644 (file)
@@ -75,8 +75,9 @@ task_top_pi_waiter(struct task_struct *p)
 
 static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock)
 {
-       return (struct task_struct *)
-               ((unsigned long)lock->owner & ~RT_MUTEX_OWNER_MASKALL);
+       unsigned long owner = (unsigned long) READ_ONCE(lock->owner);
+
+       return (struct task_struct *) (owner & ~RT_MUTEX_OWNER_MASKALL);
 }
 
 /*
index 3189e51db7e896c9596d607dd1ef7926367509c5..a46c40bfb5f669f04f6b42c8c06ea0c61ba63360 100644 (file)
@@ -39,6 +39,9 @@ void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
        BUG_ON(!list_empty(&child->ptrace_entry));
        list_add(&child->ptrace_entry, &new_parent->ptraced);
        child->parent = new_parent;
+       rcu_read_lock();
+       child->ptracer_cred = get_cred(__task_cred(new_parent));
+       rcu_read_unlock();
 }
 
 /**
@@ -71,11 +74,15 @@ void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
  */
 void __ptrace_unlink(struct task_struct *child)
 {
+       const struct cred *old_cred;
        BUG_ON(!child->ptrace);
 
        child->ptrace = 0;
        child->parent = child->real_parent;
        list_del_init(&child->ptrace_entry);
+       old_cred = child->ptracer_cred;
+       child->ptracer_cred = NULL;
+       put_cred(old_cred);
 
        spin_lock(&child->sighand->siglock);
 
@@ -219,7 +226,7 @@ static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
 static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
 {
        const struct cred *cred = current_cred(), *tcred;
-       int dumpable = 0;
+       struct mm_struct *mm;
        kuid_t caller_uid;
        kgid_t caller_gid;
 
@@ -270,16 +277,11 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
        return -EPERM;
 ok:
        rcu_read_unlock();
-       smp_rmb();
-       if (task->mm)
-               dumpable = get_dumpable(task->mm);
-       rcu_read_lock();
-       if (dumpable != SUID_DUMP_USER &&
-           !ptrace_has_cap(__task_cred(task)->user_ns, mode)) {
-               rcu_read_unlock();
-               return -EPERM;
-       }
-       rcu_read_unlock();
+       mm = task->mm;
+       if (mm &&
+           ((get_dumpable(mm) != SUID_DUMP_USER) &&
+            !ptrace_has_cap(mm->user_ns, mode)))
+           return -EPERM;
 
        return security_ptrace_access_check(task, mode);
 }
@@ -343,10 +345,6 @@ static int ptrace_attach(struct task_struct *task, long request,
 
        if (seize)
                flags |= PT_SEIZED;
-       rcu_read_lock();
-       if (ns_capable(__task_cred(task)->user_ns, CAP_SYS_PTRACE))
-               flags |= PT_PTRACE_CAP;
-       rcu_read_unlock();
        task->ptrace = flags;
 
        __ptrace_link(task, current);
index 630c19772630cc0c2cac42e2cf751dec002e81e2..32cbe72bf5458b1f3d080541d864846c66eb8931 100644 (file)
@@ -2275,6 +2275,7 @@ static int rcu_nocb_kthread(void *arg)
                                cl++;
                        c++;
                        local_bh_enable();
+                       cond_resched_rcu_qs();
                        list = next;
                }
                trace_rcu_batch_end(rdp->rsp->name, c, !!list, 0, 0, 1);
index 2ffb1680b380e542bd767ab3b8d75e87ff0f75e9..6e053bd9830c785fdf68de27f635d9380f017cdb 100644 (file)
@@ -62,8 +62,6 @@ static unsigned int max_possible_freq = 1;
  */
 static unsigned int min_max_freq = 1;
 
-static unsigned int max_capacity = 1024;
-static unsigned int min_capacity = 1024;
 static unsigned int max_load_scale_factor = 1024;
 static unsigned int max_possible_capacity = 1024;
 
@@ -869,39 +867,6 @@ void walt_fixup_busy_time(struct task_struct *p, int new_cpu)
                double_rq_unlock(src_rq, dest_rq);
 }
 
-/* Keep track of max/min capacity possible across CPUs "currently" */
-static void __update_min_max_capacity(void)
-{
-       int i;
-       int max = 0, min = INT_MAX;
-
-       for_each_online_cpu(i) {
-               if (cpu_rq(i)->capacity > max)
-                       max = cpu_rq(i)->capacity;
-               if (cpu_rq(i)->capacity < min)
-                       min = cpu_rq(i)->capacity;
-       }
-
-       max_capacity = max;
-       min_capacity = min;
-}
-
-static void update_min_max_capacity(void)
-{
-       unsigned long flags;
-       int i;
-
-       local_irq_save(flags);
-       for_each_possible_cpu(i)
-               raw_spin_lock(&cpu_rq(i)->lock);
-
-       __update_min_max_capacity();
-
-       for_each_possible_cpu(i)
-               raw_spin_unlock(&cpu_rq(i)->lock);
-       local_irq_restore(flags);
-}
-
 /*
  * Return 'capacity' of a cpu in reference to "least" efficient cpu, such that
  * least efficient cpu gets capacity of 1024
@@ -984,15 +949,9 @@ static int cpufreq_notifier_policy(struct notifier_block *nb,
        /* Initialized to policy->max in case policy->related_cpus is empty! */
        unsigned int orig_max_freq = policy->max;
 
-       if (val != CPUFREQ_NOTIFY && val != CPUFREQ_REMOVE_POLICY &&
-                                               val != CPUFREQ_CREATE_POLICY)
+       if (val != CPUFREQ_NOTIFY)
                return 0;
 
-       if (val == CPUFREQ_REMOVE_POLICY || val == CPUFREQ_CREATE_POLICY) {
-               update_min_max_capacity();
-               return 0;
-       }
-
        for_each_cpu(i, policy->related_cpus) {
                cpumask_copy(&cpu_rq(i)->freq_domain_cpumask,
                             policy->related_cpus);
@@ -1082,8 +1041,6 @@ static int cpufreq_notifier_policy(struct notifier_block *nb,
                max_load_scale_factor = highest_mplsf;
        }
 
-       __update_min_max_capacity();
-
        return 0;
 }
 
index ede4bf13d3e93649be0a474000607c6a3b898965..5fa544f3f560416c3962b88c7cca392f94dac20e 100644 (file)
@@ -298,10 +298,10 @@ u32 (*arch_gettimeoffset)(void) = default_arch_gettimeoffset;
 static inline u32 arch_gettimeoffset(void) { return 0; }
 #endif
 
-static inline s64 timekeeping_delta_to_ns(struct tk_read_base *tkr,
+static inline u64 timekeeping_delta_to_ns(struct tk_read_base *tkr,
                                          cycle_t delta)
 {
-       s64 nsec;
+       u64 nsec;
 
        nsec = delta * tkr->mult + tkr->xtime_nsec;
        nsec >>= tkr->shift;
index 4641bdb40f8ff50aeee0f9c2d06eb462b3c19e40..96c75b0e983130f68b886b5400994573f5e86dc6 100644 (file)
@@ -785,6 +785,10 @@ print_graph_entry_leaf(struct trace_iterator *iter,
 
                cpu_data = per_cpu_ptr(data->cpu_data, cpu);
 
+               /* If a graph tracer ignored set_graph_notrace */
+               if (call->depth < -1)
+                       call->depth += FTRACE_NOTRACE_DEPTH;
+
                /*
                 * Comments display at + 1 to depth. Since
                 * this is a leaf function, keep the comments
@@ -793,7 +797,8 @@ print_graph_entry_leaf(struct trace_iterator *iter,
                cpu_data->depth = call->depth - 1;
 
                /* No need to keep this function around for this depth */
-               if (call->depth < FTRACE_RETFUNC_DEPTH)
+               if (call->depth < FTRACE_RETFUNC_DEPTH &&
+                   !WARN_ON_ONCE(call->depth < 0))
                        cpu_data->enter_funcs[call->depth] = 0;
        }
 
@@ -823,11 +828,16 @@ print_graph_entry_nested(struct trace_iterator *iter,
                struct fgraph_cpu_data *cpu_data;
                int cpu = iter->cpu;
 
+               /* If a graph tracer ignored set_graph_notrace */
+               if (call->depth < -1)
+                       call->depth += FTRACE_NOTRACE_DEPTH;
+
                cpu_data = per_cpu_ptr(data->cpu_data, cpu);
                cpu_data->depth = call->depth;
 
                /* Save this function pointer to see if the exit matches */
-               if (call->depth < FTRACE_RETFUNC_DEPTH)
+               if (call->depth < FTRACE_RETFUNC_DEPTH &&
+                   !WARN_ON_ONCE(call->depth < 0))
                        cpu_data->enter_funcs[call->depth] = call->func;
        }
 
@@ -1057,7 +1067,8 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
                 */
                cpu_data->depth = trace->depth - 1;
 
-               if (trace->depth < FTRACE_RETFUNC_DEPTH) {
+               if (trace->depth < FTRACE_RETFUNC_DEPTH &&
+                   !WARN_ON_ONCE(trace->depth < 0)) {
                        if (cpu_data->enter_funcs[trace->depth] != trace->func)
                                func_match = 0;
                        cpu_data->enter_funcs[trace->depth] = 0;
index 1f1b05f5a94b8edaf014495a985168b39d73877f..b718530034d23b10415c5fb39f9c5018b8ef811f 100644 (file)
@@ -403,7 +403,6 @@ static void watchdog_overflow_callback(struct perf_event *event,
         */
        if (is_hardlockup()) {
                int this_cpu = smp_processor_id();
-               struct pt_regs *regs = get_irq_regs();
 
                /* only print hardlockups once */
                if (__this_cpu_read(hard_watchdog_warn) == true)
index a56a851908d245248803a602f68d5833cf1f8412..975e49f00f34c1b282dee5840740effb9a999bed 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/cpumask.h>
 
 #include <linux/atomic.h>
+#include <linux/user_namespace.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 
@@ -21,5 +22,6 @@ struct mm_struct init_mm = {
        .mmap_sem       = __RWSEM_INITIALIZER(init_mm.mmap_sem),
        .page_table_lock =  __SPIN_LOCK_UNLOCKED(init_mm.page_table_lock),
        .mmlist         = LIST_HEAD_INIT(init_mm.mmlist),
+       .user_ns        = &init_user_ns,
        INIT_MM_CONTEXT(init_mm)
 };
index 4f6c62e5c21edd2d800484b2f18025e45ce034fb..37ff0ab6a8ff7f1cb87ce1f6eea13de34538d05b 100644 (file)
@@ -52,6 +52,9 @@ struct kasan_global {
 #if KASAN_ABI_VERSION >= 4
        struct kasan_source_location *location;
 #endif
+#if KASAN_ABI_VERSION >= 5
+       char *odr_indicator;
+#endif
 };
 
 static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
index de1c59d8daa32ac3908e549cfdfd2df16f99b669..bfc5050cbd01ba94ff3d1305b4a5b7ce87941a10 100644 (file)
@@ -277,6 +277,7 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
        int nid = shrinkctl->nid;
        long batch_size = shrinker->batch ? shrinker->batch
                                          : SHRINK_BATCH;
+       long scanned = 0, next_deferred;
 
        freeable = shrinker->count_objects(shrinker, shrinkctl);
        if (freeable == 0)
@@ -298,7 +299,9 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
                pr_err("shrink_slab: %pF negative objects to delete nr=%ld\n",
                       shrinker->scan_objects, total_scan);
                total_scan = freeable;
-       }
+               next_deferred = nr;
+       } else
+               next_deferred = total_scan;
 
        /*
         * We need to avoid excessive windup on filesystem shrinkers
@@ -355,17 +358,22 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
 
                count_vm_events(SLABS_SCANNED, nr_to_scan);
                total_scan -= nr_to_scan;
+               scanned += nr_to_scan;
 
                cond_resched();
        }
 
+       if (next_deferred >= scanned)
+               next_deferred -= scanned;
+       else
+               next_deferred = 0;
        /*
         * move the unused scan count back into the shrinker in a
         * manner that handles concurrent updates. If we exhausted the
         * scan, there is no need to do an update.
         */
-       if (total_scan > 0)
-               new_nr = atomic_long_add_return(total_scan,
+       if (next_deferred > 0)
+               new_nr = atomic_long_add_return(next_deferred,
                                                &shrinker->nr_deferred[nid]);
        else
                new_nr = atomic_long_read(&shrinker->nr_deferred[nid]);
index 83b0ca27a45e44a08e5f04835489d0471075e3cb..f2079acb555d2dcb13d083dd812b88b070048a83 100644 (file)
@@ -2764,7 +2764,7 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
                                                             &tvlv_tt_data,
                                                             &tt_change,
                                                             &tt_len);
-               if (!tt_len)
+               if (!tt_len || !tvlv_len)
                        goto unlock;
 
                /* Copy the last orig_node's OGM buffer */
@@ -2782,7 +2782,7 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
                                                             &tvlv_tt_data,
                                                             &tt_change,
                                                             &tt_len);
-               if (!tt_len)
+               if (!tt_len || !tvlv_len)
                        goto out;
 
                /* fill the rest of the tvlv with the real TT entries */
index 2e67b1423cd32d82cbf34742bf9208cb494eaa28..56af689ca9992d2566607d0251aa4f97a57ed51d 100644 (file)
@@ -499,6 +499,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
                if (optlen % sizeof(struct can_filter) != 0)
                        return -EINVAL;
 
+               if (optlen > CAN_RAW_FILTER_MAX * sizeof(struct can_filter))
+                       return -EINVAL;
+
                count = optlen / sizeof(struct can_filter);
 
                if (count > 1) {
index 63ae5dd24fc597277ac384cb06b27ea16c6db25b..b8d927c564942fb7984f39b57e9ce27925a49042 100644 (file)
@@ -2042,6 +2042,19 @@ static int process_connect(struct ceph_connection *con)
 
        dout("process_connect on %p tag %d\n", con, (int)con->in_tag);
 
+       if (con->auth_reply_buf) {
+               /*
+                * Any connection that defines ->get_authorizer()
+                * should also define ->verify_authorizer_reply().
+                * See get_connect_authorizer().
+                */
+               ret = con->ops->verify_authorizer_reply(con, 0);
+               if (ret < 0) {
+                       con->error_msg = "bad authorize reply";
+                       return ret;
+               }
+       }
+
        switch (con->in_reply.tag) {
        case CEPH_MSGR_TAG_FEATURES:
                pr_err("%s%lld %s feature set mismatch,"
index 3fbd839f6d20739996773eb15c2c0c0fb028f9d9..cb744a352167b48b252c1f59239c2ead281bebe4 100644 (file)
 #include <net/fib_rules.h>
 #include <net/ip_tunnels.h>
 
+static const struct fib_kuid_range fib_kuid_range_unset = {
+       KUIDT_INIT(0),
+       KUIDT_INIT(~0),
+};
+
 int fib_default_rule_add(struct fib_rules_ops *ops,
                         u32 pref, u32 table, u32 flags)
 {
@@ -33,8 +38,7 @@ int fib_default_rule_add(struct fib_rules_ops *ops,
        r->table = table;
        r->flags = flags;
        r->fr_net = ops->fro_net;
-       r->uid_start = INVALID_UID;
-       r->uid_end = INVALID_UID;
+       r->uid_range = fib_kuid_range_unset;
 
        r->suppress_prefixlen = -1;
        r->suppress_ifgroup = -1;
@@ -174,21 +178,32 @@ void fib_rules_unregister(struct fib_rules_ops *ops)
 }
 EXPORT_SYMBOL_GPL(fib_rules_unregister);
 
-static inline kuid_t fib_nl_uid(struct nlattr *nla)
+static int uid_range_set(struct fib_kuid_range *range)
 {
-       return make_kuid(current_user_ns(), nla_get_u32(nla));
+       return uid_valid(range->start) && uid_valid(range->end);
 }
 
-static int nla_put_uid(struct sk_buff *skb, int idx, kuid_t uid)
+static struct fib_kuid_range nla_get_kuid_range(struct nlattr **tb)
 {
-       return nla_put_u32(skb, idx, from_kuid_munged(current_user_ns(), uid));
+       struct fib_rule_uid_range *in;
+       struct fib_kuid_range out;
+
+       in = (struct fib_rule_uid_range *)nla_data(tb[FRA_UID_RANGE]);
+
+       out.start = make_kuid(current_user_ns(), in->start);
+       out.end = make_kuid(current_user_ns(), in->end);
+
+       return out;
 }
 
-static int fib_uid_range_match(struct flowi *fl, struct fib_rule *rule)
+static int nla_put_uid_range(struct sk_buff *skb, struct fib_kuid_range *range)
 {
-       return (!uid_valid(rule->uid_start) && !uid_valid(rule->uid_end)) ||
-              (uid_gte(fl->flowi_uid, rule->uid_start) &&
-               uid_lte(fl->flowi_uid, rule->uid_end));
+       struct fib_rule_uid_range out = {
+               from_kuid_munged(current_user_ns(), range->start),
+               from_kuid_munged(current_user_ns(), range->end)
+       };
+
+       return nla_put(skb, FRA_UID_RANGE, sizeof(out), &out);
 }
 
 static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
@@ -208,7 +223,8 @@ static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
        if (rule->tun_id && (rule->tun_id != fl->flowi_tun_key.tun_id))
                goto out;
 
-       if (!fib_uid_range_match(fl, rule))
+       if (uid_lt(fl->flowi_uid, rule->uid_range.start) ||
+           uid_gt(fl->flowi_uid, rule->uid_range.end))
                goto out;
 
        ret = ops->match(rule, fl, flags);
@@ -393,17 +409,19 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
        } else if (rule->action == FR_ACT_GOTO)
                goto errout_free;
 
-       /* UID start and end must either both be valid or both unspecified. */
-       rule->uid_start = rule->uid_end = INVALID_UID;
-       if (tb[FRA_UID_START] || tb[FRA_UID_END]) {
-               if (tb[FRA_UID_START] && tb[FRA_UID_END]) {
-                       rule->uid_start = fib_nl_uid(tb[FRA_UID_START]);
-                       rule->uid_end = fib_nl_uid(tb[FRA_UID_END]);
+       if (tb[FRA_UID_RANGE]) {
+               if (current_user_ns() != net->user_ns) {
+                       err = -EPERM;
+                       goto errout_free;
                }
-               if (!uid_valid(rule->uid_start) ||
-                   !uid_valid(rule->uid_end) ||
-                   !uid_lte(rule->uid_start, rule->uid_end))
-               goto errout_free;
+
+               rule->uid_range = nla_get_kuid_range(tb);
+
+               if (!uid_range_set(&rule->uid_range) ||
+                   !uid_lte(rule->uid_range.start, rule->uid_range.end))
+                       goto errout_free;
+       } else {
+               rule->uid_range = fib_kuid_range_unset;
        }
 
        err = ops->configure(rule, skb, frh, tb);
@@ -467,6 +485,7 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)
        struct fib_rules_ops *ops = NULL;
        struct fib_rule *rule, *tmp;
        struct nlattr *tb[FRA_MAX+1];
+       struct fib_kuid_range range;
        int err = -EINVAL;
 
        if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh)))
@@ -486,6 +505,14 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)
        if (err < 0)
                goto errout;
 
+       if (tb[FRA_UID_RANGE]) {
+               range = nla_get_kuid_range(tb);
+               if (!uid_range_set(&range))
+                       goto errout;
+       } else {
+               range = fib_kuid_range_unset;
+       }
+
        list_for_each_entry(rule, &ops->rules_list, list) {
                if (frh->action && (frh->action != rule->action))
                        continue;
@@ -518,12 +545,9 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)
                    (rule->tun_id != nla_get_be64(tb[FRA_TUN_ID])))
                        continue;
 
-               if (tb[FRA_UID_START] &&
-                   !uid_eq(rule->uid_start, fib_nl_uid(tb[FRA_UID_START])))
-                       continue;
-
-               if (tb[FRA_UID_END] &&
-                   !uid_eq(rule->uid_end, fib_nl_uid(tb[FRA_UID_END])))
+               if (uid_range_set(&range) &&
+                   (!uid_eq(rule->uid_range.start, range.start) ||
+                    !uid_eq(rule->uid_range.end, range.end)))
                        continue;
 
                if (!ops->compare(rule, frh, tb))
@@ -592,9 +616,8 @@ static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
                         + nla_total_size(4) /* FRA_SUPPRESS_IFGROUP */
                         + nla_total_size(4) /* FRA_FWMARK */
                         + nla_total_size(4) /* FRA_FWMASK */
-                        + nla_total_size(8) /* FRA_TUN_ID */
-                        + nla_total_size(4) /* FRA_UID_START */
-                        + nla_total_size(4); /* FRA_UID_END */
+                        + nla_total_size(8); /* FRA_TUN_ID */
+                        + nla_total_size(sizeof(struct fib_kuid_range));
 
        if (ops->nlmsg_payload)
                payload += ops->nlmsg_payload(rule);
@@ -653,10 +676,8 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
             nla_put_u32(skb, FRA_GOTO, rule->target)) ||
            (rule->tun_id &&
             nla_put_be64(skb, FRA_TUN_ID, rule->tun_id)) ||
-           (uid_valid(rule->uid_start) &&
-            nla_put_uid(skb, FRA_UID_START, rule->uid_start)) ||
-           (uid_valid(rule->uid_end) &&
-            nla_put_uid(skb, FRA_UID_END, rule->uid_end)))
+           (uid_range_set(&rule->uid_range) &&
+            nla_put_uid_range(skb, &rule->uid_range)))
                goto nla_put_failure;
 
        if (rule->suppress_ifgroup != -1) {
index 2c2eb1b629b11d6911abfa885549e32d927815a6..2e9a1c2818c7ab2d378cd112e70cb27ba9f369a3 100644 (file)
@@ -217,6 +217,8 @@ int peernet2id_alloc(struct net *net, struct net *peer)
        bool alloc;
        int id;
 
+       if (atomic_read(&net->count) == 0)
+               return NETNSA_NSID_NOT_ASSIGNED;
        spin_lock_irqsave(&net->nsid_lock, flags);
        alloc = atomic_read(&peer->count) == 0 ? false : true;
        id = __peernet2id_alloc(net, peer, &alloc);
index 87b91ffbdec313a7c599c3892325ddf6b2b50262..b94e165a4f7911a5591c39380bba5b7c6a4bda57 100644 (file)
@@ -2600,7 +2600,10 @@ nla_put_failure:
 
 static inline size_t rtnl_fdb_nlmsg_size(void)
 {
-       return NLMSG_ALIGN(sizeof(struct ndmsg)) + nla_total_size(ETH_ALEN);
+       return NLMSG_ALIGN(sizeof(struct ndmsg)) +
+              nla_total_size(ETH_ALEN) +       /* NDA_LLADDR */
+              nla_total_size(sizeof(u16)) +    /* NDA_VLAN */
+              0;
 }
 
 static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, u16 vid, int type)
index 88f017854509ef08eb97227f353716e13e6badb3..f367df38c264532a582b8135becd858b4368c03d 100644 (file)
@@ -745,7 +745,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
                val = min_t(u32, val, sysctl_wmem_max);
 set_sndbuf:
                sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
-               sk->sk_sndbuf = max_t(u32, val * 2, SOCK_MIN_SNDBUF);
+               sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF);
                /* Wake up sending tasks if we upped the value. */
                sk->sk_write_space(sk);
                break;
@@ -781,7 +781,7 @@ set_rcvbuf:
                 * returning the value we actually used in getsockopt
                 * is the most desirable behavior.
                 */
-               sk->sk_rcvbuf = max_t(u32, val * 2, SOCK_MIN_RCVBUF);
+               sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF);
                break;
 
        case SO_RCVBUFFORCE:
@@ -2384,8 +2384,11 @@ void sock_init_data(struct socket *sock, struct sock *sk)
                sk->sk_type     =       sock->type;
                sk->sk_wq       =       sock->wq;
                sock->sk        =       sk;
-       } else
+               sk->sk_uid      =       SOCK_INODE(sock)->i_uid;
+       } else {
                sk->sk_wq       =       NULL;
+               sk->sk_uid      =       make_kuid(sock_net(sk)->user_ns, 0);
+       }
 
        rwlock_init(&sk->sk_callback_lock);
        lockdep_set_class_and_name(&sk->sk_callback_lock,
index 861e1fa25d5e424de3475a89aedfaeda6d64a246..0759f5b9180e56056d2a365c58ef7aa49a7567e5 100644 (file)
@@ -698,6 +698,7 @@ int dccp_invalid_packet(struct sk_buff *skb)
 {
        const struct dccp_hdr *dh;
        unsigned int cscov;
+       u8 dccph_doff;
 
        if (skb->pkt_type != PACKET_HOST)
                return 1;
@@ -719,18 +720,19 @@ int dccp_invalid_packet(struct sk_buff *skb)
        /*
         * If P.Data Offset is too small for packet type, drop packet and return
         */
-       if (dh->dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) {
-               DCCP_WARN("P.Data Offset(%u) too small\n", dh->dccph_doff);
+       dccph_doff = dh->dccph_doff;
+       if (dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) {
+               DCCP_WARN("P.Data Offset(%u) too small\n", dccph_doff);
                return 1;
        }
        /*
         * If P.Data Offset is too too large for packet, drop packet and return
         */
-       if (!pskb_may_pull(skb, dh->dccph_doff * sizeof(u32))) {
-               DCCP_WARN("P.Data Offset(%u) too large\n", dh->dccph_doff);
+       if (!pskb_may_pull(skb, dccph_doff * sizeof(u32))) {
+               DCCP_WARN("P.Data Offset(%u) too large\n", dccph_doff);
                return 1;
        }
-
+       dh = dccp_hdr(skb);
        /*
         * If P.type is not Data, Ack, or DataAck and P.X == 0 (the packet
         * has short sequence numbers), drop packet and return
index d95631d0924899f17549e69801567bed076491b9..20fb25e3027bbbf8b8c2068751caf40df939546d 100644 (file)
@@ -476,7 +476,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
                esph = (void *)skb_push(skb, 4);
                *seqhi = esph->spi;
                esph->spi = esph->seq_no;
-               esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.input.hi);
+               esph->seq_no = XFRM_SKB_CB(skb)->seq.input.hi;
                aead_request_set_callback(req, 0, esp_input_done_esn, skb);
        }
 
index 36e26977c9088c1dbd09cd13e9a5e2c43369fe31..ef2d4322aba7f7e6daa02224f8feca1a2d31a823 100644 (file)
@@ -425,6 +425,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
        fl4.daddr = daddr;
        fl4.saddr = saddr;
        fl4.flowi4_mark = mark;
+       fl4.flowi4_uid = sock_net_uid(net, NULL);
        fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
        fl4.flowi4_proto = IPPROTO_ICMP;
        fl4.flowi4_oif = l3mdev_master_ifindex(skb->dev);
@@ -473,6 +474,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
                      param->replyopts.opt.opt.faddr : iph->saddr);
        fl4->saddr = saddr;
        fl4->flowi4_mark = mark;
+       fl4->flowi4_uid = sock_net_uid(net, NULL);
        fl4->flowi4_tos = RT_TOS(tos);
        fl4->flowi4_proto = IPPROTO_ICMP;
        fl4->fl4_icmp_type = type;
index 030cd09dd2a24d2480346a0e19fece73356c8c0e..c97a2108cd61420c133aba51e6c999724b79d91d 100644 (file)
@@ -420,7 +420,7 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk,
                           sk->sk_protocol, inet_sk_flowi_flags(sk),
                           (opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
                           ireq->ir_loc_addr, ireq->ir_rmt_port,
-                          htons(ireq->ir_num), sock_i_uid((struct sock *)sk));
+                          htons(ireq->ir_num), sk->sk_uid);
        security_req_classify_flow(req, flowi4_to_flowi(fl4));
        rt = ip_route_output_flow(net, fl4, sk);
        if (IS_ERR(rt))
@@ -457,7 +457,7 @@ struct dst_entry *inet_csk_route_child_sock(const struct sock *sk,
                           sk->sk_protocol, inet_sk_flowi_flags(sk),
                           (opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
                           ireq->ir_loc_addr, ireq->ir_rmt_port,
-                          htons(ireq->ir_num), sock_i_uid((struct sock *)sk));
+                          htons(ireq->ir_num), sk->sk_uid);
        security_req_classify_flow(req, flowi4_to_flowi(fl4));
        rt = ip_route_output_flow(net, fl4, sk);
        if (IS_ERR(rt))
index dbf7f7ee2958a0b2bb01d83eddab0cf919012074..661bda968594acee601a85096f87f6b4fcff8768 100644 (file)
@@ -102,6 +102,9 @@ int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
 
        iph->tot_len = htons(skb->len);
        ip_send_check(iph);
+
+       skb->protocol = htons(ETH_P_IP);
+
        return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,
                       net, sk, skb, NULL, skb_dst(skb)->dev,
                       dst_output);
index 0d5278ca47773e467dcc9fcc87ee60e017295b9c..495fefe6a89828268c0737700b6accf1b4d28fa9 100644 (file)
@@ -660,6 +660,10 @@ int ping_common_sendmsg(int family, struct msghdr *msg, size_t len,
        if (len > 0xFFFF)
                return -EMSGSIZE;
 
+       /* Must have at least a full ICMP header. */
+       if (len < icmph_len)
+               return -EINVAL;
+
        /*
         *      Check the flags.
         */
@@ -792,7 +796,7 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos,
                           RT_SCOPE_UNIVERSE, sk->sk_protocol,
                           inet_sk_flowi_flags(sk), faddr, saddr, 0, 0,
-                          sock_i_uid(sk));
+                          sk->sk_uid);
 
        security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
        rt = ip_route_output_flow(net, &fl4, sk);
index a9b479a1c4a0ef737ce599dd4323431e3619ab81..6287418c1dfedcc29b51cda8938fdfbaaada5753 100644 (file)
@@ -601,8 +601,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                           inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
                           inet_sk_flowi_flags(sk) |
                            (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
-                          daddr, saddr, 0, 0,
-                          sock_i_uid(sk));
+                          daddr, saddr, 0, 0, sk->sk_uid);
 
        if (!saddr && ipc.oif) {
                err = l3mdev_get_saddr(net, ipc.oif, &fl4);
index f75b5658a3a0534d26d882db1fd86fff26d62070..3708ff083211f6faf9b467ad28edf4e21d5c55f3 100644 (file)
@@ -501,7 +501,8 @@ void __ip_select_ident(struct net *net, struct iphdr *iph, int segs)
 }
 EXPORT_SYMBOL(__ip_select_ident);
 
-static void __build_flow_key(struct flowi4 *fl4, struct sock *sk,
+static void __build_flow_key(const struct net *net, struct flowi4 *fl4,
+                            const struct sock *sk,
                             const struct iphdr *iph,
                             int oif, u8 tos,
                             u8 prot, u32 mark, int flow_flags)
@@ -518,22 +519,23 @@ static void __build_flow_key(struct flowi4 *fl4, struct sock *sk,
                           RT_SCOPE_UNIVERSE, prot,
                           flow_flags,
                           iph->daddr, iph->saddr, 0, 0,
-                          sk ? sock_i_uid(sk) : GLOBAL_ROOT_UID);
+                          sock_net_uid(net, sk));
 }
 
 static void build_skb_flow_key(struct flowi4 *fl4, const struct sk_buff *skb,
-                              struct sock *sk)
+                              const struct sock *sk)
 {
+       const struct net *net = dev_net(skb->dev);
        const struct iphdr *iph = ip_hdr(skb);
        int oif = skb->dev->ifindex;
        u8 tos = RT_TOS(iph->tos);
        u8 prot = iph->protocol;
        u32 mark = skb->mark;
 
-       __build_flow_key(fl4, sk, iph, oif, tos, prot, mark, 0);
+       __build_flow_key(net, fl4, sk, iph, oif, tos, prot, mark, 0);
 }
 
-static void build_sk_flow_key(struct flowi4 *fl4, struct sock *sk)
+static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
 {
        const struct inet_sock *inet = inet_sk(sk);
        const struct ip_options_rcu *inet_opt;
@@ -547,12 +549,11 @@ static void build_sk_flow_key(struct flowi4 *fl4, struct sock *sk)
                           RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
                           inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
                           inet_sk_flowi_flags(sk),
-                          daddr, inet->inet_saddr, 0, 0,
-                          sock_i_uid(sk));
+                          daddr, inet->inet_saddr, 0, 0, sk->sk_uid);
        rcu_read_unlock();
 }
 
-static void ip_rt_build_flow_key(struct flowi4 *fl4, struct sock *sk,
+static void ip_rt_build_flow_key(struct flowi4 *fl4, const struct sock *sk,
                                 const struct sk_buff *skb)
 {
        if (skb)
@@ -798,7 +799,7 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
 
        rt = (struct rtable *) dst;
 
-       __build_flow_key(&fl4, sk, iph, oif, tos, prot, mark, 0);
+       __build_flow_key(sock_net(sk), &fl4, sk, iph, oif, tos, prot, mark, 0);
        __ip_do_redirect(rt, skb, &fl4, true);
 }
 
@@ -1016,7 +1017,7 @@ void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
        if (!mark)
                mark = IP4_REPLY_MARK(net, skb->mark);
 
-       __build_flow_key(&fl4, NULL, iph, oif,
+       __build_flow_key(net, &fl4, NULL, iph, oif,
                         RT_TOS(iph->tos), protocol, mark, flow_flags);
        rt = __ip_route_output_key(net, &fl4);
        if (!IS_ERR(rt)) {
@@ -1032,7 +1033,7 @@ static void __ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
        struct flowi4 fl4;
        struct rtable *rt;
 
-       __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
+       __build_flow_key(sock_net(sk), &fl4, sk, iph, 0, 0, 0, 0, 0);
 
        if (!fl4.flowi4_mark)
                fl4.flowi4_mark = IP4_REPLY_MARK(sock_net(sk), skb->mark);
@@ -1051,6 +1052,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
        struct rtable *rt;
        struct dst_entry *odst = NULL;
        bool new = false;
+       struct net *net = sock_net(sk);
 
        bh_lock_sock(sk);
 
@@ -1064,7 +1066,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
                goto out;
        }
 
-       __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
+       __build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
 
        rt = (struct rtable *)odst;
        if (odst->obsolete && !odst->ops->check(odst, 0)) {
@@ -1104,7 +1106,7 @@ void ipv4_redirect(struct sk_buff *skb, struct net *net,
        struct flowi4 fl4;
        struct rtable *rt;
 
-       __build_flow_key(&fl4, NULL, iph, oif,
+       __build_flow_key(net, &fl4, NULL, iph, oif,
                         RT_TOS(iph->tos), protocol, mark, flow_flags);
        rt = __ip_route_output_key(net, &fl4);
        if (!IS_ERR(rt)) {
@@ -1119,9 +1121,10 @@ void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk)
        const struct iphdr *iph = (const struct iphdr *) skb->data;
        struct flowi4 fl4;
        struct rtable *rt;
+       struct net *net = sock_net(sk);
 
-       __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
-       rt = __ip_route_output_key(sock_net(sk), &fl4);
+       __build_flow_key(net, &fl4, sk, iph, 0, 0, 0, 0, 0);
+       rt = __ip_route_output_key(net, &fl4);
        if (!IS_ERR(rt)) {
                __ip_do_redirect(rt, skb, &fl4, false);
                ip_rt_put(rt);
index 31b6a4c9db32782edf8687501760f9a28efd9158..2dc982b15df8f8e9b44e1d731521bc8ff02eff96 100644 (file)
@@ -374,9 +374,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
        flowi4_init_output(&fl4, sk->sk_bound_dev_if, ireq->ir_mark,
                           RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP,
                           inet_sk_flowi_flags(sk),
-                          (opt && opt->srr) ? opt->faddr : ireq->ir_rmt_addr,
-                          ireq->ir_loc_addr, th->source, th->dest,
-                          sock_i_uid(sk));
+                          opt->srr ? opt->faddr : ireq->ir_rmt_addr,
+                          ireq->ir_loc_addr, th->source, th->dest, sk->sk_uid);
        security_req_classify_flow(req, flowi4_to_flowi(&fl4));
        rt = ip_route_output_key(sock_net(sk), &fl4);
        if (IS_ERR(rt)) {
index b6a48d4a3794ae62f4bad5ac91c06c88c54a6f07..25309b137c43e4fc93c22fbdcf5f5ea7de7ba1a0 100644 (file)
@@ -687,6 +687,7 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
                arg.bound_dev_if = sk->sk_bound_dev_if;
 
        arg.tos = ip_hdr(skb)->tos;
+       arg.uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
        ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
                              skb, &TCP_SKB_CB(skb)->header.h4.opt,
                              ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
@@ -708,7 +709,7 @@ release_sk1:
    outside socket context is ugly, certainly. What can I do?
  */
 
-static void tcp_v4_send_ack(struct net *net,
+static void tcp_v4_send_ack(const struct sock *sk,
                            struct sk_buff *skb, u32 seq, u32 ack,
                            u32 win, u32 tsval, u32 tsecr, int oif,
                            struct tcp_md5sig_key *key,
@@ -723,6 +724,7 @@ static void tcp_v4_send_ack(struct net *net,
 #endif
                        ];
        } rep;
+       struct net *net = sock_net(sk);
        struct ip_reply_arg arg;
 
        memset(&rep.th, 0, sizeof(struct tcphdr));
@@ -772,6 +774,7 @@ static void tcp_v4_send_ack(struct net *net,
        if (oif)
                arg.bound_dev_if = oif;
        arg.tos = tos;
+       arg.uid = sock_net_uid(net, sk_fullsock(sk) ? sk : NULL);
        ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
                              skb, &TCP_SKB_CB(skb)->header.h4.opt,
                              ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
@@ -785,7 +788,7 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
        struct inet_timewait_sock *tw = inet_twsk(sk);
        struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
 
-       tcp_v4_send_ack(sock_net(sk), skb,
+       tcp_v4_send_ack(sk, skb,
                        tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
                        tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
                        tcp_time_stamp + tcptw->tw_ts_offset,
@@ -813,7 +816,7 @@ static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
         * exception of <SYN> segments, MUST be right-shifted by
         * Rcv.Wind.Shift bits:
         */
-       tcp_v4_send_ack(sock_net(sk), skb, seq,
+       tcp_v4_send_ack(sk, skb, seq,
                        tcp_rsk(req)->rcv_nxt,
                        req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
                        tcp_time_stamp,
index 381a035fcfa1ca57e28ddbd33a94f5ab6344112d..ad3d1534c524bb67bb8f492c0d660f99ee36017e 100644 (file)
@@ -1026,7 +1026,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                                   RT_SCOPE_UNIVERSE, sk->sk_protocol,
                                   flow_flags,
                                   faddr, saddr, dport, inet->inet_sport,
-                                  sock_i_uid(sk));
+                                  sk->sk_uid);
 
                if (!saddr && ipc.oif) {
                        err = l3mdev_get_saddr(net, ipc.oif, fl4);
index d9b25bd17bf14ed2225ae379c10f6f7a3ddf79e1..1604163c28508215be179bf465c1a38f89867d29 100644 (file)
@@ -678,7 +678,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
                fl6.flowi6_mark = sk->sk_mark;
                fl6.fl6_dport = inet->inet_dport;
                fl6.fl6_sport = inet->inet_sport;
-               fl6.flowi6_uid = sock_i_uid(sk);
+               fl6.flowi6_uid = sk->sk_uid;
                security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
                rcu_read_lock();
index c52b8fc904c978344f9aaafd7d6de3b43108cf2f..189eb10b742d02fa5b39ac7206703e31e30c3cf7 100644 (file)
@@ -662,9 +662,10 @@ static int ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                return 0;
 
        if (type == NDISC_REDIRECT)
-               ip6_redirect(skb, net, skb->dev->ifindex, 0);
+               ip6_redirect(skb, net, skb->dev->ifindex, 0,
+                            sock_net_uid(net, NULL));
        else
-               ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+               ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
        xfrm_state_put(x);
 
        return 0;
index 183ff87dacf33f2f95f80fc043c939d217d36b68..cf2dfb222230eb432043a5c9bac6f862c9e0b071 100644 (file)
@@ -161,7 +161,7 @@ ipv4_connected:
        fl6.flowi6_mark = sk->sk_mark;
        fl6.fl6_dport = inet->inet_dport;
        fl6.fl6_sport = inet->inet_sport;
-       fl6.flowi6_uid = sock_i_uid(sk);
+       fl6.flowi6_uid = sk->sk_uid;
 
        if (!fl6.flowi6_oif)
                fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
index f921368c32c99b79aec721eb85100b1cc97a4799..cbcdd5db31f473f75011c2346345dd752c9a7424 100644 (file)
@@ -418,7 +418,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
                esph = (void *)skb_push(skb, 4);
                *seqhi = esph->spi;
                esph->spi = esph->seq_no;
-               esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.input.hi);
+               esph->seq_no = XFRM_SKB_CB(skb)->seq.input.hi;
                aead_request_set_callback(req, 0, esp_input_done_esn, skb);
        }
 
@@ -474,9 +474,10 @@ static int esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                return 0;
 
        if (type == NDISC_REDIRECT)
-               ip6_redirect(skb, net, skb->dev->ifindex, 0);
+               ip6_redirect(skb, net, skb->dev->ifindex, 0,
+                            sock_net_uid(net, NULL));
        else
-               ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+               ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
        xfrm_state_put(x);
 
        return 0;
index 41e5c9520c7d47d8753f3ab374511e7844192c4a..3ae2fbe07b25cb9f82a3e4ba67ce69f355e2c490 100644 (file)
@@ -92,9 +92,10 @@ static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        struct net *net = dev_net(skb->dev);
 
        if (type == ICMPV6_PKT_TOOBIG)
-               ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+               ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
        else if (type == NDISC_REDIRECT)
-               ip6_redirect(skb, net, skb->dev->ifindex, 0);
+               ip6_redirect(skb, net, skb->dev->ifindex, 0,
+                            sock_net_uid(net, NULL));
 
        if (!(type & ICMPV6_INFOMSG_MASK))
                if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST)
@@ -478,6 +479,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
        fl6.flowi6_oif = iif;
        fl6.fl6_icmp_type = type;
        fl6.fl6_icmp_code = code;
+       fl6.flowi6_uid = sock_net_uid(net, NULL);
        security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
        sk = icmpv6_xmit_lock(net);
@@ -585,6 +587,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
        fl6.flowi6_oif = l3mdev_fib_oif(skb->dev);
        fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY;
        fl6.flowi6_mark = mark;
+       fl6.flowi6_uid = sock_net_uid(net, NULL);
        security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
        sk = icmpv6_xmit_lock(net);
index 897bb6eb575125f378b491f01d0fe2b3c4b24a33..dc79ebc141891d0f983fa50bb4249d940261c09f 100644 (file)
@@ -86,7 +86,7 @@ struct dst_entry *inet6_csk_route_req(const struct sock *sk,
        fl6->flowi6_mark = ireq->ir_mark;
        fl6->fl6_dport = ireq->ir_rmt_port;
        fl6->fl6_sport = htons(ireq->ir_num);
-       fl6->flowi6_uid = sock_i_uid((struct sock *)sk);
+       fl6->flowi6_uid = sk->sk_uid;
        security_req_classify_flow(req, flowi6_to_flowi(fl6));
 
        dst = ip6_dst_lookup_flow(sk, fl6, final_p);
@@ -135,7 +135,7 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
        fl6->flowi6_mark = sk->sk_mark;
        fl6->fl6_sport = inet->inet_sport;
        fl6->fl6_dport = inet->inet_dport;
-       fl6->flowi6_uid = sock_i_uid(sk);
+       fl6->flowi6_uid = sk->sk_uid;
        security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
 
        rcu_read_lock();
index 17430f3410737fc1ae3fd0bd3375d18017454772..eba61b42cd422ff74cf91ad10583cdbf5cd4084d 100644 (file)
@@ -794,6 +794,8 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
                fl6.flowi6_mark = skb->mark;
 
+       fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
        err = ip6gre_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu);
        if (err != 0) {
                /* XXX: send ICMP error even if DF is not set. */
@@ -844,6 +846,8 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
                fl6.flowi6_mark = skb->mark;
 
+       fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
        err = ip6gre_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu);
        if (err != 0) {
                if (err == -EMSGSIZE)
index e8878886eba425fe39c4b95ae399d0bf551f30cd..c9bd1ee1f1453bb53aa5e10d932d0a7f26cceac8 100644 (file)
@@ -1043,6 +1043,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
        struct ipv6_tel_txoption opt;
        struct dst_entry *dst = NULL, *ndst = NULL;
        struct net_device *tdev;
+       bool use_cache = false;
        int mtu;
        unsigned int max_headroom = sizeof(struct ipv6hdr);
        u8 proto;
@@ -1070,7 +1071,15 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
 
                memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
                neigh_release(neigh);
-       } else if (!fl6->flowi6_mark)
+       } else if (!(t->parms.flags &
+                    (IP6_TNL_F_USE_ORIG_TCLASS | IP6_TNL_F_USE_ORIG_FWMARK))) {
+               /* enable the cache only only if the routing decision does
+                * not depend on the current inner header value
+                */
+               use_cache = true;
+       }
+
+       if (use_cache)
                dst = ip6_tnl_dst_get(t);
 
        if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr))
@@ -1134,7 +1143,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
                skb = new_skb;
        }
 
-       if (!fl6->flowi6_mark && ndst)
+       if (use_cache && ndst)
                ip6_tnl_dst_set(t, ndst);
        skb_dst_set(skb, dst);
 
@@ -1194,6 +1203,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
        memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
        fl6.flowi6_proto = IPPROTO_IPIP;
 
+       fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
+
        dsfield = ipv4_get_dsfield(iph);
 
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
@@ -1247,6 +1258,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 
        memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
        fl6.flowi6_proto = IPPROTO_IPV6;
+       fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL);
 
        dsfield = ipv6_get_dsfield(ipv6h);
        if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
index c76ebc7fc52d1169819d9ad78b9c954191d854e1..24fb9c0efd008c6aa7c27c9cc7271cece4b0dd23 100644 (file)
@@ -597,9 +597,10 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                return 0;
 
        if (type == NDISC_REDIRECT)
-               ip6_redirect(skb, net, skb->dev->ifindex, 0);
+               ip6_redirect(skb, net, skb->dev->ifindex, 0,
+                            sock_net_uid(net, NULL));
        else
-               ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+               ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
        xfrm_state_put(x);
 
        return 0;
index b247baceb797d004b0b911366fff75498c8a9379..54d165b9845a02c24f735477f48abdb0c944bae2 100644 (file)
@@ -74,9 +74,10 @@ static int ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                return 0;
 
        if (type == NDISC_REDIRECT)
-               ip6_redirect(skb, net, skb->dev->ifindex, 0);
+               ip6_redirect(skb, net, skb->dev->ifindex, 0,
+                            sock_net_uid(net, NULL));
        else
-               ip6_update_pmtu(skb, net, info, 0, 0, INVALID_UID);
+               ip6_update_pmtu(skb, net, info, 0, 0, sock_net_uid(net, NULL));
        xfrm_state_put(x);
 
        return 0;
index d11c46833d615b394797e193008f1cc8e4592935..39970e212ad574ae36406b5354e0550698249387 100644 (file)
@@ -26,6 +26,7 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
        struct flowi6 fl6 = {
                .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
                .flowi6_mark = skb->mark,
+               .flowi6_uid = sock_net_uid(net, skb->sk),
                .daddr = iph->daddr,
                .saddr = iph->saddr,
        };
index 462f2a76b5c2270dba806e193a4c5bde57e14a39..1d184322a7b1eec00b1b3345b774c1fb363b9f9f 100644 (file)
@@ -148,6 +148,8 @@ int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
        ipv6_hdr(skb)->payload_len = htons(len);
        IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
 
+       skb->protocol = htons(ETH_P_IPV6);
+
        return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
                       net, sk, skb, NULL, skb_dst(skb)->dev,
                       dst_output);
index fa65e92e9510b3369bddf874f0d1a9a0681e36a2..1737fc0f2988ceddc909c448da6ac8a3cdce42f6 100644 (file)
@@ -141,7 +141,7 @@ int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        fl6.daddr = *daddr;
        fl6.flowi6_oif = oif;
        fl6.flowi6_mark = sk->sk_mark;
-       fl6.flowi6_uid = sock_i_uid(sk);
+       fl6.flowi6_uid = sk->sk_uid;
        fl6.fl6_icmp_type = user_icmph.icmp6_type;
        fl6.fl6_icmp_code = user_icmph.icmp6_code;
        security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
index d9ad71a01b4cac79b6fbbf536f3d1938bd398fea..58eb8ee19f34f29c7493ff234585d0e906748cd9 100644 (file)
@@ -768,7 +768,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        memset(&fl6, 0, sizeof(fl6));
 
        fl6.flowi6_mark = sk->sk_mark;
-       fl6.flowi6_uid = sock_i_uid(sk);
+       fl6.flowi6_uid = sk->sk_uid;
 
        if (sin6) {
                if (addr_len < SIN6_LEN_RFC2133)
index 46476a3af2ad68682c964060004ace0d7097b20b..3c5d6bb3b850353119bf649f764d65e8e36b7198 100644 (file)
@@ -1406,7 +1406,7 @@ EXPORT_SYMBOL_GPL(ip6_update_pmtu);
 void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
 {
        ip6_update_pmtu(skb, sock_net(sk), mtu,
-                       sk->sk_bound_dev_if, sk->sk_mark, sock_i_uid(sk));
+                       sk->sk_bound_dev_if, sk->sk_mark, sk->sk_uid);
 }
 EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu);
 
@@ -1487,7 +1487,8 @@ static struct dst_entry *ip6_route_redirect(struct net *net,
                                flags, __ip6_route_redirect);
 }
 
-void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
+void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
+                 kuid_t uid)
 {
        const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
        struct dst_entry *dst;
@@ -1500,6 +1501,7 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
        fl6.daddr = iph->daddr;
        fl6.saddr = iph->saddr;
        fl6.flowlabel = ip6_flowinfo(iph);
+       fl6.flowi6_uid = uid;
 
        dst = ip6_route_redirect(net, &fl6, &ipv6_hdr(skb)->saddr);
        rt6_do_redirect(dst, NULL, skb);
@@ -1521,6 +1523,7 @@ void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
        fl6.flowi6_mark = mark;
        fl6.daddr = msg->dest;
        fl6.saddr = iph->daddr;
+       fl6.flowi6_uid = sock_net_uid(net, NULL);
 
        dst = ip6_route_redirect(net, &fl6, &iph->saddr);
        rt6_do_redirect(dst, NULL, skb);
@@ -1529,7 +1532,8 @@ void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
 
 void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
 {
-       ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark);
+       ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark,
+                    sk->sk_uid);
 }
 EXPORT_SYMBOL_GPL(ip6_sk_redirect);
 
@@ -3256,6 +3260,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
                                           nla_get_u32(tb[RTA_UID]));
        else
                fl6.flowi6_uid = iif ? INVALID_UID : current_uid();
+
        if (iif) {
                struct net_device *dev;
                int flags = 0;
index a22015fab95eb69b7e7e17a22c0aaacf9cefd92d..336843ca4e6b28d16bd4c780825e51ae2e479421 100644 (file)
@@ -228,7 +228,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
                fl6.flowi6_mark = ireq->ir_mark;
                fl6.fl6_dport = ireq->ir_rmt_port;
                fl6.fl6_sport = inet_sk(sk)->inet_sport;
-               fl6.flowi6_uid = sock_i_uid(sk);
+               fl6.flowi6_uid = sk->sk_uid;
                security_req_classify_flow(req, flowi6_to_flowi(&fl6));
 
                dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
index 50e71e784e850dc787d38f4454a596c1d2546c90..8ed00c8a128aa86ee84ddbed40659c73903cae6c 100644 (file)
@@ -234,7 +234,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
        fl6.flowi6_mark = sk->sk_mark;
        fl6.fl6_dport = usin->sin6_port;
        fl6.fl6_sport = inet->inet_sport;
-       fl6.flowi6_uid = sock_i_uid(sk);
+       fl6.flowi6_uid = sk->sk_uid;
 
        opt = rcu_dereference_protected(np->opt, sock_owned_by_user(sk));
        final_p = fl6_update_dst(&fl6, opt, &final);
@@ -814,6 +814,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
        fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark);
        fl6.fl6_dport = t1->dest;
        fl6.fl6_sport = t1->source;
+       fl6.flowi6_uid = sock_net_uid(net, sk && sk_fullsock(sk) ? sk : NULL);
        security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
        /* Pass a socket to ip6_dst_lookup either it is for RST
index 1207379c1cce3a214afef4c2a39230360aa4bdc7..156a13c7ada85582f4da1009a85882786adb014d 100644 (file)
@@ -1244,7 +1244,7 @@ do_udp_sendmsg:
                fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
 
        fl6.flowi6_mark = sk->sk_mark;
-       fl6.flowi6_uid = sock_i_uid(sk);
+       fl6.flowi6_uid = sk->sk_uid;
 
        if (msg->msg_controllen) {
                opt = &opt_space;
index 42de4ccd159f6f6853930afd44cea239e2011a54..d0e906d3964281d4cbcd4a9c2d97b25d6eb85b80 100644 (file)
@@ -251,8 +251,6 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        int ret;
        int chk_addr_ret;
 
-       if (!sock_flag(sk, SOCK_ZAPPED))
-               return -EINVAL;
        if (addr_len < sizeof(struct sockaddr_l2tpip))
                return -EINVAL;
        if (addr->l2tp_family != AF_INET)
@@ -267,6 +265,9 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        read_unlock_bh(&l2tp_ip_lock);
 
        lock_sock(sk);
+       if (!sock_flag(sk, SOCK_ZAPPED))
+               goto out;
+
        if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_l2tpip))
                goto out;
 
index 9ee4ddb6b3973899995e6e3f5766f7e210f90370..0289208b0346821dd805ab67b150a034997b4dc0 100644 (file)
@@ -266,8 +266,6 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        int addr_type;
        int err;
 
-       if (!sock_flag(sk, SOCK_ZAPPED))
-               return -EINVAL;
        if (addr->l2tp_family != AF_INET6)
                return -EINVAL;
        if (addr_len < sizeof(*addr))
@@ -293,6 +291,9 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        lock_sock(sk);
 
        err = -EINVAL;
+       if (!sock_flag(sk, SOCK_ZAPPED))
+               goto out_unlock;
+
        if (sk->sk_state != TCP_CLOSE)
                goto out_unlock;
 
@@ -517,6 +518,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        memset(&fl6, 0, sizeof(fl6));
 
        fl6.flowi6_mark = sk->sk_mark;
+       fl6.flowi6_uid = sk->sk_uid;
 
        if (lsa) {
                if (addr_len < SIN6_LEN_RFC2133)
index 83097c3832d129228226dbdcc3e2f2d8af188671..23095d5e019940b245c2577ce2b00fd64d61f0bb 100644 (file)
@@ -2517,7 +2517,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
 }
 
 static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
-                                        bool assoc)
+                                        bool assoc, bool abandon)
 {
        struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
 
@@ -2539,6 +2539,9 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
                mutex_lock(&sdata->local->mtx);
                ieee80211_vif_release_channel(sdata);
                mutex_unlock(&sdata->local->mtx);
+
+               if (abandon)
+                       cfg80211_abandon_assoc(sdata->dev, assoc_data->bss);
        }
 
        kfree(assoc_data);
@@ -2768,7 +2771,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
                           bssid, reason_code,
                           ieee80211_get_reason_code_string(reason_code));
 
-               ieee80211_destroy_assoc_data(sdata, false);
+               ieee80211_destroy_assoc_data(sdata, false, true);
 
                cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
                return;
@@ -3173,14 +3176,14 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        if (status_code != WLAN_STATUS_SUCCESS) {
                sdata_info(sdata, "%pM denied association (code=%d)\n",
                           mgmt->sa, status_code);
-               ieee80211_destroy_assoc_data(sdata, false);
+               ieee80211_destroy_assoc_data(sdata, false, false);
                event.u.mlme.status = MLME_DENIED;
                event.u.mlme.reason = status_code;
                drv_event_callback(sdata->local, sdata, &event);
        } else {
                if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) {
                        /* oops -- internal error -- send timeout for now */
-                       ieee80211_destroy_assoc_data(sdata, false);
+                       ieee80211_destroy_assoc_data(sdata, false, false);
                        cfg80211_assoc_timeout(sdata->dev, bss);
                        return;
                }
@@ -3193,7 +3196,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
                 * recalc after assoc_data is NULL but before associated
                 * is set can cause the interface to go idle
                 */
-               ieee80211_destroy_assoc_data(sdata, true);
+               ieee80211_destroy_assoc_data(sdata, true, false);
 
                /* get uapsd queues configuration */
                uapsd_queues = 0;
@@ -3888,7 +3891,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
                                .u.mlme.status = MLME_TIMEOUT,
                        };
 
-                       ieee80211_destroy_assoc_data(sdata, false);
+                       ieee80211_destroy_assoc_data(sdata, false, false);
                        cfg80211_assoc_timeout(sdata->dev, bss);
                        drv_event_callback(sdata->local, sdata, &event);
                }
@@ -4029,7 +4032,7 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
                                               WLAN_REASON_DEAUTH_LEAVING,
                                               false, frame_buf);
                if (ifmgd->assoc_data)
-                       ieee80211_destroy_assoc_data(sdata, false);
+                       ieee80211_destroy_assoc_data(sdata, false, true);
                if (ifmgd->auth_data)
                        ieee80211_destroy_auth_data(sdata, false);
                cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
@@ -4905,7 +4908,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
                                               IEEE80211_STYPE_DEAUTH,
                                               req->reason_code, tx,
                                               frame_buf);
-               ieee80211_destroy_assoc_data(sdata, false);
+               ieee80211_destroy_assoc_data(sdata, false, true);
                ieee80211_report_disconnect(sdata, frame_buf,
                                            sizeof(frame_buf), true,
                                            req->reason_code);
@@ -4980,7 +4983,7 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
        sdata_lock(sdata);
        if (ifmgd->assoc_data) {
                struct cfg80211_bss *bss = ifmgd->assoc_data->bss;
-               ieee80211_destroy_assoc_data(sdata, false);
+               ieee80211_destroy_assoc_data(sdata, false, false);
                cfg80211_assoc_timeout(sdata->dev, bss);
        }
        if (ifmgd->auth_data)
index 28fc283c1ec1fbf4b5049b8d52e087b48628aae6..360700a2f46cae18630d7f4a97bcd398e6304e37 100644 (file)
@@ -931,7 +931,6 @@ static void netlink_sock_destruct(struct sock *sk)
        if (nlk->cb_running) {
                if (nlk->cb.done)
                        nlk->cb.done(&nlk->cb);
-
                module_put(nlk->cb.module);
                kfree_skb(nlk->cb.skb);
        }
@@ -960,6 +959,14 @@ static void netlink_sock_destruct(struct sock *sk)
        WARN_ON(nlk_sk(sk)->groups);
 }
 
+static void netlink_sock_destruct_work(struct work_struct *work)
+{
+       struct netlink_sock *nlk = container_of(work, struct netlink_sock,
+                                               work);
+
+       sk_free(&nlk->sk);
+}
+
 /* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on
  * SMP. Look, when several writers sleep and reader wakes them up, all but one
  * immediately hit write lock and grab all the cpus. Exclusive sleep solves
@@ -1265,8 +1272,18 @@ out_module:
 static void deferred_put_nlk_sk(struct rcu_head *head)
 {
        struct netlink_sock *nlk = container_of(head, struct netlink_sock, rcu);
+       struct sock *sk = &nlk->sk;
+
+       if (!atomic_dec_and_test(&sk->sk_refcnt))
+               return;
+
+       if (nlk->cb_running && nlk->cb.done) {
+               INIT_WORK(&nlk->work, netlink_sock_destruct_work);
+               schedule_work(&nlk->work);
+               return;
+       }
 
-       sock_put(&nlk->sk);
+       sk_free(sk);
 }
 
 static int netlink_release(struct socket *sock)
index 14437d9b1965dcf3d3f085e4aba1f804bdc6f652..df32cb92d9fc6c182395bd408b300e0a3bbb386f 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/rhashtable.h>
 #include <linux/atomic.h>
+#include <linux/workqueue.h>
 #include <net/sock.h>
 
 #define NLGRPSZ(x)     (ALIGN(x, sizeof(unsigned long) * 8) / 8)
@@ -53,6 +54,7 @@ struct netlink_sock {
 
        struct rhash_head       node;
        struct rcu_head         rcu;
+       struct work_struct      work;
 };
 
 static inline struct netlink_sock *nlk_sk(struct sock *sk)
index 34e4fcfd240be1896029a059b564668aa8cba859..f223d1c80ccf7f9251dce0f8f31f58c766576946 100644 (file)
@@ -3572,19 +3572,25 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
 
                if (optlen != sizeof(val))
                        return -EINVAL;
-               if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)
-                       return -EBUSY;
                if (copy_from_user(&val, optval, sizeof(val)))
                        return -EFAULT;
                switch (val) {
                case TPACKET_V1:
                case TPACKET_V2:
                case TPACKET_V3:
-                       po->tp_version = val;
-                       return 0;
+                       break;
                default:
                        return -EINVAL;
                }
+               lock_sock(sk);
+               if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) {
+                       ret = -EBUSY;
+               } else {
+                       po->tp_version = val;
+                       ret = 0;
+               }
+               release_sock(sk);
+               return ret;
        }
        case PACKET_RESERVE:
        {
@@ -4067,6 +4073,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
        /* Added to avoid minimal code churn */
        struct tpacket_req *req = &req_u->req;
 
+       lock_sock(sk);
        /* Opening a Tx-ring is NOT supported in TPACKET_V3 */
        if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) {
                WARN(1, "Tx-ring is not supported.\n");
@@ -4148,7 +4155,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                        goto out;
        }
 
-       lock_sock(sk);
 
        /* Detach socket from network */
        spin_lock(&po->bind_lock);
@@ -4197,11 +4203,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                if (!tx_ring)
                        prb_shutdown_retire_blk_timer(po, rb_queue);
        }
-       release_sock(sk);
 
        if (pg_vec)
                free_pg_vec(pg_vec, order, req->tp_block_nr);
 out:
+       release_sock(sk);
        return err;
 }
 
index e38a7701f154c97db2070b1e0b8b54fabdb8b0f3..c3434e9024450e5cff700ae7b48d104360e535ce 100644 (file)
@@ -104,6 +104,17 @@ static void tcf_pedit_cleanup(struct tc_action *a, int bind)
        kfree(keys);
 }
 
+static bool offset_valid(struct sk_buff *skb, int offset)
+{
+       if (offset > 0 && offset > skb->len)
+               return false;
+
+       if  (offset < 0 && -offset > skb_headroom(skb))
+               return false;
+
+       return true;
+}
+
 static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
                     struct tcf_result *res)
 {
@@ -130,6 +141,11 @@ static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
                        if (tkey->offmask) {
                                char *d, _d;
 
+                               if (!offset_valid(skb, off + tkey->at)) {
+                                       pr_info("tc filter pedit 'at' offset %d out of bounds\n",
+                                               off + tkey->at);
+                                       goto bad;
+                               }
                                d = skb_header_pointer(skb, off + tkey->at, 1,
                                                       &_d);
                                if (!d)
@@ -142,10 +158,10 @@ static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
                                        " offset must be on 32 bit boundaries\n");
                                goto bad;
                        }
-                       if (offset > 0 && offset > skb->len) {
-                               pr_info("tc filter pedit"
-                                       " offset %d can't exceed pkt length %d\n",
-                                      offset, skb->len);
+
+                       if (!offset_valid(skb, off + offset)) {
+                               pr_info("tc filter pedit offset %d out of bounds\n",
+                                       offset);
                                goto bad;
                        }
 
index 0b8c3ace671f1fff47cf2a12f7e6428bb5704b9f..1bf1f4517db623126952646fba50633929b300c4 100644 (file)
@@ -62,9 +62,6 @@ static unsigned long basic_get(struct tcf_proto *tp, u32 handle)
        struct basic_head *head = rtnl_dereference(tp->root);
        struct basic_filter *f;
 
-       if (head == NULL)
-               return 0UL;
-
        list_for_each_entry(f, &head->flist, link) {
                if (f->handle == handle) {
                        l = (unsigned long) f;
@@ -109,7 +106,6 @@ static bool basic_destroy(struct tcf_proto *tp, bool force)
                tcf_unbind_filter(tp, &f->res);
                call_rcu(&f->rcu, basic_delete_filter);
        }
-       RCU_INIT_POINTER(tp->root, NULL);
        kfree_rcu(head, rcu);
        return true;
 }
index 5faaa5425f7b72293fdd80e1b27405fcf479e207..3eef0215e53f35764ff02f5f6052f71d5972dde8 100644 (file)
@@ -199,7 +199,6 @@ static bool cls_bpf_destroy(struct tcf_proto *tp, bool force)
                call_rcu(&prog->rcu, __cls_bpf_delete_prog);
        }
 
-       RCU_INIT_POINTER(tp->root, NULL);
        kfree_rcu(head, rcu);
        return true;
 }
@@ -210,9 +209,6 @@ static unsigned long cls_bpf_get(struct tcf_proto *tp, u32 handle)
        struct cls_bpf_prog *prog;
        unsigned long ret = 0UL;
 
-       if (head == NULL)
-               return 0UL;
-
        list_for_each_entry(prog, &head->plist, link) {
                if (prog->handle == handle) {
                        ret = (unsigned long) prog;
index 4c85bd3a750cbb02c743779f28cbde6ceacb5ecf..c104c2019feb6245154a9149d4f685b1ab23cd18 100644 (file)
@@ -130,11 +130,10 @@ static bool cls_cgroup_destroy(struct tcf_proto *tp, bool force)
 
        if (!force)
                return false;
-
-       if (head) {
-               RCU_INIT_POINTER(tp->root, NULL);
+       /* Head can still be NULL due to cls_cgroup_init(). */
+       if (head)
                call_rcu(&head->rcu, cls_cgroup_destroy_rcu);
-       }
+
        return true;
 }
 
index fbfec6a188390007fd30cf0a351e74f5b2d77057..d7ba2b4ff0f3ac1ef6011804c58e35a41d77ff4d 100644 (file)
@@ -583,7 +583,6 @@ static bool flow_destroy(struct tcf_proto *tp, bool force)
                list_del_rcu(&f->list);
                call_rcu(&f->rcu, flow_destroy_filter);
        }
-       RCU_INIT_POINTER(tp->root, NULL);
        kfree_rcu(head, rcu);
        return true;
 }
index 95b021243233bd46a9ef836b07b7c4671faa9e15..e5a58c82728a485b9fb5abb307915a8f026d13c9 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/rhashtable.h>
+#include <linux/workqueue.h>
 
 #include <linux/if_ether.h>
 #include <linux/in6.h>
@@ -55,7 +56,10 @@ struct cls_fl_head {
        bool mask_assigned;
        struct list_head filters;
        struct rhashtable_params ht_params;
-       struct rcu_head rcu;
+       union {
+               struct work_struct work;
+               struct rcu_head rcu;
+       };
 };
 
 struct cls_fl_filter {
@@ -165,6 +169,24 @@ static void fl_destroy_filter(struct rcu_head *head)
        kfree(f);
 }
 
+static void fl_destroy_sleepable(struct work_struct *work)
+{
+       struct cls_fl_head *head = container_of(work, struct cls_fl_head,
+                                               work);
+       if (head->mask_assigned)
+               rhashtable_destroy(&head->ht);
+       kfree(head);
+       module_put(THIS_MODULE);
+}
+
+static void fl_destroy_rcu(struct rcu_head *rcu)
+{
+       struct cls_fl_head *head = container_of(rcu, struct cls_fl_head, rcu);
+
+       INIT_WORK(&head->work, fl_destroy_sleepable);
+       schedule_work(&head->work);
+}
+
 static bool fl_destroy(struct tcf_proto *tp, bool force)
 {
        struct cls_fl_head *head = rtnl_dereference(tp->root);
@@ -177,10 +199,9 @@ static bool fl_destroy(struct tcf_proto *tp, bool force)
                list_del_rcu(&f->list);
                call_rcu(&f->rcu, fl_destroy_filter);
        }
-       RCU_INIT_POINTER(tp->root, NULL);
-       if (head->mask_assigned)
-               rhashtable_destroy(&head->ht);
-       kfree_rcu(head, rcu);
+
+       __module_get(THIS_MODULE);
+       call_rcu(&head->rcu, fl_destroy_rcu);
        return true;
 }
 
index f9c9fc075fe65402c531ada58be9e4b916d282cd..9992dfac693886bf5502f3aac8a549d09fc2bdd3 100644 (file)
@@ -152,7 +152,8 @@ static int rsvp_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                return -1;
        nhptr = ip_hdr(skb);
 #endif
-
+       if (unlikely(!head))
+               return -1;
 restart:
 
 #if RSVP_DST_LEN == 4
index 944c8ff450558ca1d5475a5581410b2d5b69e3be..403746b202637f35ac1cfca5026e703ce194bcf2 100644 (file)
@@ -503,7 +503,6 @@ static bool tcindex_destroy(struct tcf_proto *tp, bool force)
        walker.fn = tcindex_destroy_element;
        tcindex_walk(tp, &walker);
 
-       RCU_INIT_POINTER(tp->root, NULL);
        call_rcu(&p->rcu, __tcindex_destroy);
        return true;
 }
index 0090225eeb1e973418bc391fde9eff971c784379..66d984ac29917200ac65258a220eee1b5201c3d3 100644 (file)
@@ -520,9 +520,23 @@ static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
        return used;
 }
 
+int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+       int err = simple_setattr(dentry, iattr);
+
+       if (!err) {
+               struct socket *sock = SOCKET_I(d_inode(dentry));
+
+               sock->sk->sk_uid = iattr->ia_uid;
+       }
+
+       return err;
+}
+
 static const struct inode_operations sockfs_inode_ops = {
        .getxattr = sockfs_getxattr,
        .listxattr = sockfs_listxattr,
+       .setattr = sockfs_setattr,
 };
 
 /**
index 824cc1e160bc1f79e54b1fcdb03a88b740abac27..73f75258ce4694be1235078ff062c3f0e73a1e3b 100644 (file)
@@ -2194,7 +2194,8 @@ out:
  *     Sleep until more data has arrived. But check for races..
  */
 static long unix_stream_data_wait(struct sock *sk, long timeo,
-                                 struct sk_buff *last, unsigned int last_len)
+                                 struct sk_buff *last, unsigned int last_len,
+                                 bool freezable)
 {
        struct sk_buff *tail;
        DEFINE_WAIT(wait);
@@ -2215,7 +2216,10 @@ static long unix_stream_data_wait(struct sock *sk, long timeo,
 
                sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
                unix_state_unlock(sk);
-               timeo = freezable_schedule_timeout(timeo);
+               if (freezable)
+                       timeo = freezable_schedule_timeout(timeo);
+               else
+                       timeo = schedule_timeout(timeo);
                unix_state_lock(sk);
 
                if (sock_flag(sk, SOCK_DEAD))
@@ -2245,7 +2249,8 @@ struct unix_stream_read_state {
        unsigned int splice_flags;
 };
 
-static int unix_stream_read_generic(struct unix_stream_read_state *state)
+static int unix_stream_read_generic(struct unix_stream_read_state *state,
+                                   bool freezable)
 {
        struct scm_cookie scm;
        struct socket *sock = state->socket;
@@ -2324,7 +2329,7 @@ again:
                        mutex_unlock(&u->iolock);
 
                        timeo = unix_stream_data_wait(sk, timeo, last,
-                                                     last_len);
+                                                     last_len, freezable);
 
                        if (signal_pending(current)) {
                                err = sock_intr_errno(timeo);
@@ -2466,7 +2471,7 @@ static int unix_stream_recvmsg(struct socket *sock, struct msghdr *msg,
                .flags = flags
        };
 
-       return unix_stream_read_generic(&state);
+       return unix_stream_read_generic(&state, true);
 }
 
 static ssize_t skb_unix_socket_splice(struct sock *sk,
@@ -2512,7 +2517,7 @@ static ssize_t unix_stream_splice_read(struct socket *sock,  loff_t *ppos,
            flags & SPLICE_F_NONBLOCK)
                state.flags = MSG_DONTWAIT;
 
-       return unix_stream_read_generic(&state);
+       return unix_stream_read_generic(&state, false);
 }
 
 static int unix_shutdown(struct socket *sock, int mode)
index 47a967fed8ffc18aff179715c21eb9d7d98eb8b1..47ea169aa0a3d372636d56c2dbd6eb6eb53a919f 100644 (file)
@@ -398,6 +398,7 @@ void cfg80211_sme_disassoc(struct wireless_dev *wdev);
 void cfg80211_sme_deauth(struct wireless_dev *wdev);
 void cfg80211_sme_auth_timeout(struct wireless_dev *wdev);
 void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev);
+void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev);
 
 /* internal helpers */
 bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher);
index fb44fa3bf4efa750298163a15534572c43229b2e..c0e02f72e931fccbdd1b3003dfd0e7fb6a45e197 100644 (file)
@@ -149,6 +149,18 @@ void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss)
 }
 EXPORT_SYMBOL(cfg80211_assoc_timeout);
 
+void cfg80211_abandon_assoc(struct net_device *dev, struct cfg80211_bss *bss)
+{
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
+       struct wiphy *wiphy = wdev->wiphy;
+
+       cfg80211_sme_abandon_assoc(wdev);
+
+       cfg80211_unhold_bss(bss_from_pub(bss));
+       cfg80211_put_bss(wiphy, bss);
+}
+EXPORT_SYMBOL(cfg80211_abandon_assoc);
+
 void cfg80211_tx_mlme_mgmt(struct net_device *dev, const u8 *buf, size_t len)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
index 8020b5b094d4c8fba0c0f2431f8af7d8ecc40dca..18b4a652cf41f2b7f40f0044bd386d72af823ae5 100644 (file)
@@ -39,6 +39,7 @@ struct cfg80211_conn {
                CFG80211_CONN_ASSOCIATING,
                CFG80211_CONN_ASSOC_FAILED,
                CFG80211_CONN_DEAUTH,
+               CFG80211_CONN_ABANDON,
                CFG80211_CONN_CONNECTED,
        } state;
        u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
@@ -204,6 +205,8 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
                cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
                                     NULL, 0,
                                     WLAN_REASON_DEAUTH_LEAVING, false);
+               /* fall through */
+       case CFG80211_CONN_ABANDON:
                /* free directly, disconnected event already sent */
                cfg80211_sme_free(wdev);
                return 0;
@@ -423,6 +426,17 @@ void cfg80211_sme_assoc_timeout(struct wireless_dev *wdev)
        schedule_work(&rdev->conn_work);
 }
 
+void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev)
+{
+       struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+
+       if (!wdev->conn)
+               return;
+
+       wdev->conn->state = CFG80211_CONN_ABANDON;
+       schedule_work(&rdev->conn_work);
+}
+
 static int cfg80211_sme_get_conn_ies(struct wireless_dev *wdev,
                                     const u8 *ies, size_t ies_len,
                                     const u8 **out_ies, size_t *out_ies_len)
index 8275f0e55106bc0055d0a1adfe2a169ad1b54193..4b2f44c20caf8941d150f261074b40d589a10376 100644 (file)
@@ -364,12 +364,14 @@ int dialog_inputbox(WINDOW *main_window,
        WINDOW *prompt_win;
        WINDOW *form_win;
        PANEL *panel;
-       int i, x, y;
+       int i, x, y, lines, columns, win_lines, win_cols;
        int res = -1;
        int cursor_position = strlen(init);
        int cursor_form_win;
        char *result = *resultp;
 
+       getmaxyx(stdscr, lines, columns);
+
        if (strlen(init)+1 > *result_len) {
                *result_len = strlen(init)+1;
                *resultp = result = realloc(result, *result_len);
@@ -386,14 +388,19 @@ int dialog_inputbox(WINDOW *main_window,
        if (title)
                prompt_width = max(prompt_width, strlen(title));
 
+       win_lines = min(prompt_lines+6, lines-2);
+       win_cols = min(prompt_width+7, columns-2);
+       prompt_lines = max(win_lines-6, 0);
+       prompt_width = max(win_cols-7, 0);
+
        /* place dialog in middle of screen */
-       y = (getmaxy(stdscr)-(prompt_lines+4))/2;
-       x = (getmaxx(stdscr)-(prompt_width+4))/2;
+       y = (lines-win_lines)/2;
+       x = (columns-win_cols)/2;
 
        strncpy(result, init, *result_len);
 
        /* create the windows */
-       win = newwin(prompt_lines+6, prompt_width+7, y, x);
+       win = newwin(win_lines, win_cols, y, x);
        prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2);
        form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
        keypad(form_win, TRUE);
index 3a9b66c6e09c38933b63a4af6ee20e34efa09118..0aca39762ed0ec981fb4f612741010a255a97587 100644 (file)
@@ -1886,8 +1886,8 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
                snd_timer_interrupt(substream->timer, 1);
 #endif
  _end:
-       snd_pcm_stream_unlock_irqrestore(substream, flags);
        kill_fasync(&runtime->fasync, SIGIO, POLL_IN);
+       snd_pcm_stream_unlock_irqrestore(substream, flags);
 }
 
 EXPORT_SYMBOL(snd_pcm_period_elapsed);
index 7f57a145a47e1fe8b5a949511fdfa99c9c55c221..a03cf68d0bcd6ce350b658e96de7dc9b9561dd1a 100644 (file)
@@ -884,6 +884,8 @@ void snd_hda_apply_fixup(struct hda_codec *codec, int action)
 }
 EXPORT_SYMBOL_GPL(snd_hda_apply_fixup);
 
+#define IGNORE_SEQ_ASSOC (~(AC_DEFCFG_SEQUENCE | AC_DEFCFG_DEF_ASSOC))
+
 static bool pin_config_match(struct hda_codec *codec,
                             const struct hda_pintbl *pins)
 {
@@ -901,7 +903,7 @@ static bool pin_config_match(struct hda_codec *codec,
                for (; t_pins->nid; t_pins++) {
                        if (t_pins->nid == nid) {
                                found = 1;
-                               if (t_pins->val == cfg)
+                               if ((t_pins->val & IGNORE_SEQ_ASSOC) == (cfg & IGNORE_SEQ_ASSOC))
                                        break;
                                else if ((cfg & 0xf0000000) == 0x40000000 && (t_pins->val & 0xf0000000) == 0x40000000)
                                        break;
index 9ceb2bc36e68026bd02dfca8bdca4f9ffab2e849..c146d0de53d825d8653ca900d6f5e559b351641f 100644 (file)
@@ -780,6 +780,7 @@ static const struct hda_pintbl alienware_pincfgs[] = {
 static const struct snd_pci_quirk ca0132_quirks[] = {
        SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE),
        SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE),
+       SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE),
        {}
 };
 
index 36cd715986bc53a40b61f4cd27bc927e114bec64..46f7b023f69ccf1ca469377ccbe5da330cebef1d 100644 (file)
@@ -262,6 +262,7 @@ enum {
        CXT_FIXUP_CAP_MIX_AMP_5047,
        CXT_FIXUP_MUTE_LED_EAPD,
        CXT_FIXUP_HP_SPECTRE,
+       CXT_FIXUP_HP_GATE_MIC,
 };
 
 /* for hda_fixup_thinkpad_acpi() */
@@ -633,6 +634,17 @@ static void cxt_fixup_cap_mix_amp_5047(struct hda_codec *codec,
                                  (1 << AC_AMPCAP_MUTE_SHIFT));
 }
 
+static void cxt_fixup_hp_gate_mic_jack(struct hda_codec *codec,
+                                      const struct hda_fixup *fix,
+                                      int action)
+{
+       /* the mic pin (0x19) doesn't give an unsolicited event;
+        * probe the mic pin together with the headphone pin (0x16)
+        */
+       if (action == HDA_FIXUP_ACT_PROBE)
+               snd_hda_jack_set_gating_jack(codec, 0x19, 0x16);
+}
+
 /* ThinkPad X200 & co with cxt5051 */
 static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
        { 0x16, 0x042140ff }, /* HP (seq# overridden) */
@@ -774,6 +786,10 @@ static const struct hda_fixup cxt_fixups[] = {
                        { }
                }
        },
+       [CXT_FIXUP_HP_GATE_MIC] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = cxt_fixup_hp_gate_mic_jack,
+       },
 };
 
 static const struct snd_pci_quirk cxt5045_fixups[] = {
@@ -824,6 +840,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC),
        SND_PCI_QUIRK(0x1025, 0x054f, "Acer Aspire 4830T", CXT_FIXUP_ASPIRE_DMIC),
        SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
+       SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC),
        SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
        SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
index f0986cac82f1a5fb464e786b992f312345c3b6f8..3b2687889cd5eec607e54118e6274b9786051b11 100644 (file)
@@ -5899,6 +5899,9 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x12, 0x90a60180},
                {0x14, 0x90170120},
                {0x21, 0x02211030}),
+       SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+               {0x1b, 0x01011020},
+               {0x21, 0x02211010}),
        SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
                {0x12, 0x90a60160},
                {0x14, 0x90170120},
index 0487cfaac5385a5c8201fbb80cf1b28040e18c74..2b96b11fbe71c10251207046e8ca02dc50dae4af 100644 (file)
@@ -762,6 +762,9 @@ static int sst_soc_prepare(struct device *dev)
        struct sst_data *drv = dev_get_drvdata(dev);
        int i;
 
+       if (!drv->soc_card)
+               return 0;
+
        /* suspend all pcms first */
        snd_soc_suspend(drv->soc_card->dev);
        snd_soc_poweroff(drv->soc_card->dev);
@@ -784,6 +787,9 @@ static void sst_soc_complete(struct device *dev)
        struct sst_data *drv = dev_get_drvdata(dev);
        int i;
 
+       if (!drv->soc_card)
+               return;
+
        /* restart SSPs */
        for (i = 0; i < drv->soc_card->num_rtd; i++) {
                struct snd_soc_dai *dai = drv->soc_card->rtd[i].cpu_dai;
index 2c44139b404188607fc47e863aa9b33419ae5fcc..33db205dd12b57d8b53436d5fd2eb9ff6cc2a22a 100644 (file)
@@ -445,6 +445,8 @@ static int hiface_pcm_prepare(struct snd_pcm_substream *alsa_sub)
 
        mutex_lock(&rt->stream_mutex);
 
+       hiface_pcm_stream_stop(rt);
+
        sub->dma_off = 0;
        sub->period_off = 0;
 
index 4f85757009b3e44e2246cc21f4387d0948056da3..499b03c8281de19ac925a0dd06cc6562c46e856b 100644 (file)
@@ -931,9 +931,10 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
        case USB_ID(0x046d, 0x0826): /* HD Webcam c525 */
        case USB_ID(0x046d, 0x08ca): /* Logitech Quickcam Fusion */
        case USB_ID(0x046d, 0x0991):
+       case USB_ID(0x046d, 0x09a2): /* QuickCam Communicate Deluxe/S7500 */
        /* Most audio usb devices lie about volume resolution.
         * Most Logitech webcams have res = 384.
-        * Proboly there is some logitech magic behind this number --fishor
+        * Probably there is some logitech magic behind this number --fishor
         */
                if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
                        usb_audio_info(chip,