Merge remote-tracking branch 'lts/linux-4.4.y' into linux-linaro-lsk-v4.4
authorAlex Shi <alex.shi@linaro.org>
Mon, 12 Dec 2016 14:16:26 +0000 (22:16 +0800)
committerAlex Shi <alex.shi@linaro.org>
Mon, 12 Dec 2016 14:16:26 +0000 (22:16 +0800)
Conflicts:
also change cpu_enable_uao in arch/arm64/include/asm/processor.h
comment unmatch fixed in arch/arm64/kernel/suspend.c

52 files changed:
Makefile
arch/arc/include/asm/delay.h
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/sparc/kernel/signal_32.c
arch/sparc/mm/init_64.c
arch/x86/kernel/head_32.S
block/blk-map.c
drivers/block/zram/zram_drv.c
drivers/net/dsa/bcm_sf2.c
drivers/net/ethernet/broadcom/genet/bcmgenet.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/mwifiex/cfg80211.c
drivers/pci/pcie/aer/aer_inject.c
drivers/pci/probe.c
drivers/pwm/sysfs.c
include/linux/compiler-gcc.h
include/linux/pci.h
include/linux/uio.h
kernel/rcu/tree_plugin.h
mm/kasan/kasan.h
net/core/net_namespace.c
net/core/rtnetlink.c
net/core/sock.c
net/dccp/ipv4.c
net/ipv4/esp4.c
net/ipv4/ip_output.c
net/ipv4/ping.c
net/ipv6/esp6.c
net/ipv6/ip6_tunnel.c
net/ipv6/output_core.c
net/l2tp/l2tp_ip.c
net/l2tp/l2tp_ip6.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/unix/af_unix.c
sound/core/pcm_lib.c

index 705eb9e38fce599582feb708513662db551d450c..6876efe0d735676b6394a002e1767a9dda0fcc4a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 4
-SUBLEVEL = 36
+SUBLEVEL = 38
 EXTRAVERSION =
 NAME = Blurry Fish Butt
 
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 308d96eaeeaeb0e8fc2f3e54c6a11fb3882a15a6..1695f77d8bf2fa73f3ed464c4cb3f6d9f75da382 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 24ecbeb733ed354f24be2d11fcfb9eba3ddd939c..eda7d5915fbb209bf4057cd1f621beadd8c02606 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>
@@ -823,7 +825,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 6c16e4963b39092a30ad444f1862d39d270538ae..18e5a2c3d5546ff0bf7c1e809d2817ad53ac348a 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>
@@ -641,9 +643,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 */
 
@@ -654,7 +664,7 @@ 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));
 }
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 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 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 370c2f76016d685820689f543ea96c1006230131..1770c455dfdd3125e639524e0b242027c33a68a8 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;
        }
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 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 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 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 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 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 e89c7ee7e8036b55abd63a687fbd91e858006554..5f37614f2451faa1fdcfdf91031963746cea2c83 100644 (file)
@@ -1802,6 +1802,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 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 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 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 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..f4c0917e66b5f8cad1cec9a7b93e84b67cfe1006 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:
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 f2ad5216c438006e5f62a862913895bd04f2126a..2b7283303650ae9a833582e38908c3a1dca9dae0 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 aa67e0e64b69dad791056706e986b4d0f15bbb88..23160d2b3f711348678a8b161eae12cf9715d8ff 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.
         */
index 060a60b2f8a6db074167e389b56893337c887fe9..111ba55fd512fb9f2b6f6af6c7084b71cc9bbf22 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);
        }
 
index e8878886eba425fe39c4b95ae399d0bf551f30cd..2994d1f1a6616070acb17598ebdf7e129634b216 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);
 
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 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..3c4f867d3633144f38c2ddc5783dd0fac23832f8 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;
 
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 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 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);