commit:     29844256de5e753a88a18e250b81b1d20b16c783
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Mon Apr 13 11:13:48 2020 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Mon Apr 13 11:13:48 2020 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=29844256

Linux patch 4.4.219

Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>

 0000_README              |    4 +
 1218_linux-4.4.219.patch | 1261 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1265 insertions(+)

diff --git a/0000_README b/0000_README
index 48c827e..3d36ad7 100644
--- a/0000_README
+++ b/0000_README
@@ -915,6 +915,10 @@ Patch:  1217_linux-4.4.218.patch
 From:   http://www.kernel.org
 Desc:   Linux 4.4.218
 
+Patch:  1218_linux-4.4.219.patch
+From:   http://www.kernel.org
+Desc:   Linux 4.4.219
+
 Patch:  1500_XATTR_USER_PREFIX.patch
 From:   https://bugs.gentoo.org/show_bug.cgi?id=470644
 Desc:   Support for namespace user.pax.* on tmpfs.

diff --git a/1218_linux-4.4.219.patch b/1218_linux-4.4.219.patch
new file mode 100644
index 0000000..426540a
--- /dev/null
+++ b/1218_linux-4.4.219.patch
@@ -0,0 +1,1261 @@
+diff --git a/Documentation/accounting/getdelays.c 
b/Documentation/accounting/getdelays.c
+index f40578026a04..8b14a6b08862 100644
+--- a/Documentation/accounting/getdelays.c
++++ b/Documentation/accounting/getdelays.c
+@@ -135,7 +135,7 @@ static int send_cmd(int sd, __u16 nlmsg_type, __u32 
nlmsg_pid,
+       msg.g.version = 0x1;
+       na = (struct nlattr *) GENLMSG_DATA(&msg);
+       na->nla_type = nla_type;
+-      na->nla_len = nla_len + 1 + NLA_HDRLEN;
++      na->nla_len = nla_len + NLA_HDRLEN;
+       memcpy(NLA_DATA(na), nla_data, nla_len);
+       msg.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
+ 
+diff --git a/Makefile b/Makefile
+index 2a06e5e4cc8d..738ef5d8ec0f 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 4
+ PATCHLEVEL = 4
+-SUBLEVEL = 218
++SUBLEVEL = 219
+ EXTRAVERSION =
+ NAME = Blurry Fish Butt
+ 
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 2916d08ee30e..661ed5ec546e 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -1824,9 +1824,6 @@ unsigned int get_random_int(void)
+       __u32 *hash;
+       unsigned int ret;
+ 
+-      if (arch_get_random_int(&ret))
+-              return ret;
+-
+       hash = get_cpu_var(get_random_int_hash);
+ 
+       hash[0] += current->pid + jiffies + random_get_entropy();
+@@ -1846,9 +1843,6 @@ unsigned long get_random_long(void)
+       __u32 *hash;
+       unsigned long ret;
+ 
+-      if (arch_get_random_long(&ret))
+-              return ret;
+-
+       hash = get_cpu_var(get_random_int_hash);
+ 
+       hash[0] += current->pid + jiffies + random_get_entropy();
+diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
+index 8b549ece9f13..d5f3fcc30002 100644
+--- a/drivers/clk/qcom/clk-rcg2.c
++++ b/drivers/clk/qcom/clk-rcg2.c
+@@ -107,7 +107,7 @@ static int update_config(struct clk_rcg2 *rcg)
+       }
+ 
+       WARN(1, "%s: rcg didn't update its configuration.", name);
+-      return 0;
++      return -EBUSY;
+ }
+ 
+ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
+diff --git a/drivers/gpu/drm/bochs/bochs_hw.c 
b/drivers/gpu/drm/bochs/bochs_hw.c
+index a39b0343c197..401c218567af 100644
+--- a/drivers/gpu/drm/bochs/bochs_hw.c
++++ b/drivers/gpu/drm/bochs/bochs_hw.c
+@@ -97,10 +97,8 @@ int bochs_hw_init(struct drm_device *dev, uint32_t flags)
+               size = min(size, mem);
+       }
+ 
+-      if (pci_request_region(pdev, 0, "bochs-drm") != 0) {
+-              DRM_ERROR("Cannot request framebuffer\n");
+-              return -EBUSY;
+-      }
++      if (pci_request_region(pdev, 0, "bochs-drm") != 0)
++              DRM_WARN("Cannot request framebuffer, boot fb still active?\n");
+ 
+       bochs->fb_map = ioremap(addr, size);
+       if (bochs->fb_map == NULL) {
+diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
+index 2cb924ffd5a3..f5229b083f8e 100644
+--- a/drivers/gpu/drm/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/drm_dp_mst_topology.c
+@@ -431,6 +431,7 @@ static bool drm_dp_sideband_parse_remote_dpcd_read(struct 
drm_dp_sideband_msg_rx
+       if (idx > raw->curlen)
+               goto fail_len;
+       repmsg->u.remote_dpcd_read_ack.num_bytes = raw->msg[idx];
++      idx++;
+       if (idx > raw->curlen)
+               goto fail_len;
+ 
+diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
+index 5ed9b5f8a037..b59a4a819aaa 100644
+--- a/drivers/infiniband/core/cma.c
++++ b/drivers/infiniband/core/cma.c
+@@ -2378,6 +2378,7 @@ static int cma_resolve_iboe_route(struct rdma_id_private 
*id_priv)
+ err2:
+       kfree(route->path_rec);
+       route->path_rec = NULL;
++      route->num_paths = 0;
+ err1:
+       kfree(work);
+       return ret;
+diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
+index 27f42763eaf5..5bacb019ec1f 100644
+--- a/drivers/net/can/slcan.c
++++ b/drivers/net/can/slcan.c
+@@ -147,7 +147,7 @@ static void slc_bump(struct slcan *sl)
+       u32 tmpid;
+       char *cmd = sl->rbuff;
+ 
+-      cf.can_id = 0;
++      memset(&cf, 0, sizeof(cf));
+ 
+       switch (*cmd) {
+       case 'r':
+@@ -186,8 +186,6 @@ static void slc_bump(struct slcan *sl)
+       else
+               return;
+ 
+-      *(u64 *) (&cf.data) = 0; /* clear payload */
+-
+       /* RTR frames may have a dlc > 0 but they never have any data bytes */
+       if (!(cf.can_id & CAN_RTR_FLAG)) {
+               for (i = 0; i < cf.can_dlc; i++) {
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c 
b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+index 1df84c8de9d7..b535f6c37838 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+@@ -188,7 +188,7 @@ static void dwmac1000_set_filter(struct mac_device_info 
*hw,
+                       reg++;
+               }
+ 
+-              while (reg <= perfect_addr_number) {
++              while (reg < perfect_addr_number) {
+                       writel(0, ioaddr + GMAC_ADDR_HIGH(reg));
+                       writel(0, ioaddr + GMAC_ADDR_LOW(reg));
+                       reg++;
+diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
+index 89eec6fead75..e99a07d5fda7 100644
+--- a/drivers/net/xen-netfront.c
++++ b/drivers/net/xen-netfront.c
+@@ -1835,7 +1835,7 @@ static int talk_to_netback(struct xenbus_device *dev,
+       err = xen_net_read_mac(dev, info->netdev->dev_addr);
+       if (err) {
+               xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
+-              goto out;
++              goto out_unlocked;
+       }
+ 
+       rtnl_lock();
+@@ -1950,6 +1950,7 @@ abort_transaction_no_dev_fatal:
+       xennet_destroy_queues(info);
+  out:
+       rtnl_unlock();
++out_unlocked:
+       device_unregister(&dev->dev);
+       return err;
+ }
+@@ -1981,10 +1982,6 @@ static int xennet_connect(struct net_device *dev)
+       /* talk_to_netback() sets the correct number of queues */
+       num_queues = dev->real_num_tx_queues;
+ 
+-      rtnl_lock();
+-      netdev_update_features(dev);
+-      rtnl_unlock();
+-
+       if (dev->reg_state == NETREG_UNINITIALIZED) {
+               err = register_netdev(dev);
+               if (err) {
+@@ -1994,6 +1991,10 @@ static int xennet_connect(struct net_device *dev)
+               }
+       }
+ 
++      rtnl_lock();
++      netdev_update_features(dev);
++      rtnl_unlock();
++
+       /*
+        * All public and private state should now be sane.  Get
+        * ready to start sending and receiving packets and give the driver
+diff --git a/drivers/power/axp288_charger.c b/drivers/power/axp288_charger.c
+index e4d569f57acc..0c6fed79c363 100644
+--- a/drivers/power/axp288_charger.c
++++ b/drivers/power/axp288_charger.c
+@@ -883,6 +883,10 @@ static int axp288_charger_probe(struct platform_device 
*pdev)
+       /* Register charger interrupts */
+       for (i = 0; i < CHRG_INTR_END; i++) {
+               pirq = platform_get_irq(info->pdev, i);
++              if (pirq < 0) {
++                      dev_err(&pdev->dev, "Failed to get IRQ: %d\n", pirq);
++                      return pirq;
++              }
+               info->irq[i] = regmap_irq_get_virq(info->regmap_irqc, pirq);
+               if (info->irq[i] < 0) {
+                       dev_warn(&info->pdev->dev,
+diff --git a/drivers/staging/rdma/hfi1/sysfs.c 
b/drivers/staging/rdma/hfi1/sysfs.c
+index 1dd6727dd5ef..a86828f44c4d 100644
+--- a/drivers/staging/rdma/hfi1/sysfs.c
++++ b/drivers/staging/rdma/hfi1/sysfs.c
+@@ -620,7 +620,11 @@ int hfi1_create_port_files(struct ib_device *ibdev, u8 
port_num,
+               dd_dev_err(dd,
+                          "Skipping sc2vl sysfs info, (err %d) port %u\n",
+                          ret, port_num);
+-              goto bail;
++              /*
++               * Based on the documentation for kobject_init_and_add(), the
++               * caller should call kobject_put even if this call fails.
++               */
++              goto bail_sc2vl;
+       }
+       kobject_uevent(&ppd->sc2vl_kobj, KOBJ_ADD);
+ 
+@@ -630,7 +634,7 @@ int hfi1_create_port_files(struct ib_device *ibdev, u8 
port_num,
+               dd_dev_err(dd,
+                          "Skipping sl2sc sysfs info, (err %d) port %u\n",
+                          ret, port_num);
+-              goto bail_sc2vl;
++              goto bail_sl2sc;
+       }
+       kobject_uevent(&ppd->sl2sc_kobj, KOBJ_ADD);
+ 
+@@ -640,7 +644,7 @@ int hfi1_create_port_files(struct ib_device *ibdev, u8 
port_num,
+               dd_dev_err(dd,
+                          "Skipping vl2mtu sysfs info, (err %d) port %u\n",
+                          ret, port_num);
+-              goto bail_sl2sc;
++              goto bail_vl2mtu;
+       }
+       kobject_uevent(&ppd->vl2mtu_kobj, KOBJ_ADD);
+ 
+@@ -651,7 +655,7 @@ int hfi1_create_port_files(struct ib_device *ibdev, u8 
port_num,
+               dd_dev_err(dd,
+                "Skipping Congestion Control sysfs info, (err %d) port %u\n",
+                ret, port_num);
+-              goto bail_vl2mtu;
++              goto bail_cc;
+       }
+ 
+       kobject_uevent(&ppd->pport_cc_kobj, KOBJ_ADD);
+@@ -691,7 +695,6 @@ bail_sl2sc:
+       kobject_put(&ppd->sl2sc_kobj);
+ bail_sc2vl:
+       kobject_put(&ppd->sc2vl_kobj);
+-bail:
+       return ret;
+ }
+ 
+diff --git a/drivers/usb/gadget/function/f_printer.c 
b/drivers/usb/gadget/function/f_printer.c
+index 0fbfb2b2aa08..69afc17fca38 100644
+--- a/drivers/usb/gadget/function/f_printer.c
++++ b/drivers/usb/gadget/function/f_printer.c
+@@ -161,14 +161,6 @@ static struct usb_endpoint_descriptor hs_ep_out_desc = {
+       .wMaxPacketSize =       cpu_to_le16(512)
+ };
+ 
+-static struct usb_qualifier_descriptor dev_qualifier = {
+-      .bLength =              sizeof(dev_qualifier),
+-      .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
+-      .bcdUSB =               cpu_to_le16(0x0200),
+-      .bDeviceClass =         USB_CLASS_PRINTER,
+-      .bNumConfigurations =   1
+-};
+-
+ static struct usb_descriptor_header *hs_printer_function[] = {
+       (struct usb_descriptor_header *) &intf_desc,
+       (struct usb_descriptor_header *) &hs_ep_in_desc,
+diff --git a/drivers/usb/gadget/function/f_uac2.c 
b/drivers/usb/gadget/function/f_uac2.c
+index e931c3cb0840..ac190650314a 100644
+--- a/drivers/usb/gadget/function/f_uac2.c
++++ b/drivers/usb/gadget/function/f_uac2.c
+@@ -598,18 +598,6 @@ static struct usb_gadget_strings *fn_strings[] = {
+       NULL,
+ };
+ 
+-static struct usb_qualifier_descriptor devqual_desc = {
+-      .bLength = sizeof devqual_desc,
+-      .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
+-
+-      .bcdUSB = cpu_to_le16(0x200),
+-      .bDeviceClass = USB_CLASS_MISC,
+-      .bDeviceSubClass = 0x02,
+-      .bDeviceProtocol = 0x01,
+-      .bNumConfigurations = 1,
+-      .bRESERVED = 0,
+-};
+-
+ static struct usb_interface_assoc_descriptor iad_desc = {
+       .bLength = sizeof iad_desc,
+       .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+diff --git a/kernel/padata.c b/kernel/padata.c
+index 0d7ec5fd520b..ae036af3f012 100644
+--- a/kernel/padata.c
++++ b/kernel/padata.c
+@@ -640,8 +640,8 @@ int padata_set_cpumask(struct padata_instance *pinst, int 
cpumask_type,
+       struct cpumask *serial_mask, *parallel_mask;
+       int err = -EINVAL;
+ 
+-      mutex_lock(&pinst->lock);
+       get_online_cpus();
++      mutex_lock(&pinst->lock);
+ 
+       switch (cpumask_type) {
+       case PADATA_CPU_PARALLEL:
+@@ -659,8 +659,8 @@ int padata_set_cpumask(struct padata_instance *pinst, int 
cpumask_type,
+       err =  __padata_set_cpumasks(pinst, parallel_mask, serial_mask);
+ 
+ out:
+-      put_online_cpus();
+       mutex_unlock(&pinst->lock);
++      put_online_cpus();
+ 
+       return err;
+ }
+diff --git a/mm/mempolicy.c b/mm/mempolicy.c
+index 41c678199b80..e101cac3d4a6 100644
+--- a/mm/mempolicy.c
++++ b/mm/mempolicy.c
+@@ -2725,7 +2725,9 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
+       switch (mode) {
+       case MPOL_PREFERRED:
+               /*
+-               * Insist on a nodelist of one node only
++               * Insist on a nodelist of one node only, although later
++               * we use first_node(nodes) to grab a single node, so here
++               * nodelist (or nodes) cannot be empty.
+                */
+               if (nodelist) {
+                       char *rest = nodelist;
+@@ -2733,6 +2735,8 @@ int mpol_parse_str(char *str, struct mempolicy **mpol)
+                               rest++;
+                       if (*rest)
+                               goto out;
++                      if (nodes_empty(nodes))
++                              goto out;
+               }
+               break;
+       case MPOL_INTERLEAVE:
+diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
+index 8e385a0ae60e..939fbf7b352d 100644
+--- a/net/bluetooth/rfcomm/tty.c
++++ b/net/bluetooth/rfcomm/tty.c
+@@ -413,10 +413,8 @@ static int __rfcomm_create_dev(struct sock *sk, void 
__user *arg)
+               dlc = rfcomm_dlc_exists(&req.src, &req.dst, req.channel);
+               if (IS_ERR(dlc))
+                       return PTR_ERR(dlc);
+-              else if (dlc) {
+-                      rfcomm_dlc_put(dlc);
++              if (dlc)
+                       return -EBUSY;
+-              }
+               dlc = rfcomm_dlc_alloc(GFP_KERNEL);
+               if (!dlc)
+                       return -ENOMEM;
+diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
+index fdaa905dccdd..0d87639deb27 100644
+--- a/net/ipv4/fib_trie.c
++++ b/net/ipv4/fib_trie.c
+@@ -2230,6 +2230,7 @@ static int fib_triestat_seq_show(struct seq_file *seq, 
void *v)
+                  " %Zd bytes, size of tnode: %Zd bytes.\n",
+                  LEAF_SIZE, TNODE_SIZE(0));
+ 
++      rcu_read_lock();
+       for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
+               struct hlist_head *head = &net->ipv4.fib_table_hash[h];
+               struct fib_table *tb;
+@@ -2249,7 +2250,9 @@ static int fib_triestat_seq_show(struct seq_file *seq, 
void *v)
+                       trie_show_usage(seq, t->stats);
+ #endif
+               }
++              cond_resched_rcu();
+       }
++      rcu_read_unlock();
+ 
+       return 0;
+ }
+diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
+index e598aa14f167..20b21f8578e1 100644
+--- a/net/ipv4/ip_tunnel.c
++++ b/net/ipv4/ip_tunnel.c
+@@ -155,11 +155,8 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net 
*itn,
+                       cand = t;
+       }
+ 
+-      if (flags & TUNNEL_NO_KEY)
+-              goto skip_key_lookup;
+-
+       hlist_for_each_entry_rcu(t, head, hash_node) {
+-              if (t->parms.i_key != key ||
++              if ((!(flags & TUNNEL_NO_KEY) && t->parms.i_key != key) ||
+                   t->parms.iph.saddr != 0 ||
+                   t->parms.iph.daddr != 0 ||
+                   !(t->dev->flags & IFF_UP))
+@@ -171,7 +168,6 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net 
*itn,
+                       cand = t;
+       }
+ 
+-skip_key_lookup:
+       if (cand)
+               return cand;
+ 
+diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
+index 429dbb064240..2b8b5c57c7f0 100644
+--- a/net/l2tp/l2tp_core.c
++++ b/net/l2tp/l2tp_core.c
+@@ -277,6 +277,55 @@ struct l2tp_session *l2tp_session_find(struct net *net, 
struct l2tp_tunnel *tunn
+ }
+ EXPORT_SYMBOL_GPL(l2tp_session_find);
+ 
++/* Like l2tp_session_find() but takes a reference on the returned session.
++ * Optionally calls session->ref() too if do_ref is true.
++ */
++struct l2tp_session *l2tp_session_get(struct net *net,
++                                    struct l2tp_tunnel *tunnel,
++                                    u32 session_id, bool do_ref)
++{
++      struct hlist_head *session_list;
++      struct l2tp_session *session;
++
++      if (!tunnel) {
++              struct l2tp_net *pn = l2tp_pernet(net);
++
++              session_list = l2tp_session_id_hash_2(pn, session_id);
++
++              rcu_read_lock_bh();
++              hlist_for_each_entry_rcu(session, session_list, global_hlist) {
++                      if (session->session_id == session_id) {
++                              l2tp_session_inc_refcount(session);
++                              if (do_ref && session->ref)
++                                      session->ref(session);
++                              rcu_read_unlock_bh();
++
++                              return session;
++                      }
++              }
++              rcu_read_unlock_bh();
++
++              return NULL;
++      }
++
++      session_list = l2tp_session_id_hash(tunnel, session_id);
++      read_lock_bh(&tunnel->hlist_lock);
++      hlist_for_each_entry(session, session_list, hlist) {
++              if (session->session_id == session_id) {
++                      l2tp_session_inc_refcount(session);
++                      if (do_ref && session->ref)
++                              session->ref(session);
++                      read_unlock_bh(&tunnel->hlist_lock);
++
++                      return session;
++              }
++      }
++      read_unlock_bh(&tunnel->hlist_lock);
++
++      return NULL;
++}
++EXPORT_SYMBOL_GPL(l2tp_session_get);
++
+ struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
+                                         bool do_ref)
+ {
+@@ -328,6 +377,48 @@ struct l2tp_session *l2tp_session_find_by_ifname(struct 
net *net, char *ifname)
+ }
+ EXPORT_SYMBOL_GPL(l2tp_session_find_by_ifname);
+ 
++static int l2tp_session_add_to_tunnel(struct l2tp_tunnel *tunnel,
++                                    struct l2tp_session *session)
++{
++      struct l2tp_session *session_walk;
++      struct hlist_head *g_head;
++      struct hlist_head *head;
++      struct l2tp_net *pn;
++
++      head = l2tp_session_id_hash(tunnel, session->session_id);
++
++      write_lock_bh(&tunnel->hlist_lock);
++      hlist_for_each_entry(session_walk, head, hlist)
++              if (session_walk->session_id == session->session_id)
++                      goto exist;
++
++      if (tunnel->version == L2TP_HDR_VER_3) {
++              pn = l2tp_pernet(tunnel->l2tp_net);
++              g_head = l2tp_session_id_hash_2(l2tp_pernet(tunnel->l2tp_net),
++                                              session->session_id);
++
++              spin_lock_bh(&pn->l2tp_session_hlist_lock);
++              hlist_for_each_entry(session_walk, g_head, global_hlist)
++                      if (session_walk->session_id == session->session_id)
++                              goto exist_glob;
++
++              hlist_add_head_rcu(&session->global_hlist, g_head);
++              spin_unlock_bh(&pn->l2tp_session_hlist_lock);
++      }
++
++      hlist_add_head(&session->hlist, head);
++      write_unlock_bh(&tunnel->hlist_lock);
++
++      return 0;
++
++exist_glob:
++      spin_unlock_bh(&pn->l2tp_session_hlist_lock);
++exist:
++      write_unlock_bh(&tunnel->hlist_lock);
++
++      return -EEXIST;
++}
++
+ /* Lookup a tunnel by id
+  */
+ struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id)
+@@ -636,6 +727,9 @@ discard:
+  * a data (not control) frame before coming here. Fields up to the
+  * session-id have already been parsed and ptr points to the data
+  * after the session-id.
++ *
++ * session->ref() must have been called prior to l2tp_recv_common().
++ * session->deref() will be called automatically after skb is processed.
+  */
+ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
+                     unsigned char *ptr, unsigned char *optr, u16 hdrflags,
+@@ -645,14 +739,6 @@ void l2tp_recv_common(struct l2tp_session *session, 
struct sk_buff *skb,
+       int offset;
+       u32 ns, nr;
+ 
+-      /* The ref count is increased since we now hold a pointer to
+-       * the session. Take care to decrement the refcnt when exiting
+-       * this function from now on...
+-       */
+-      l2tp_session_inc_refcount(session);
+-      if (session->ref)
+-              (*session->ref)(session);
+-
+       /* Parse and check optional cookie */
+       if (session->peer_cookie_len > 0) {
+               if (memcmp(ptr, &session->peer_cookie[0], 
session->peer_cookie_len)) {
+@@ -803,8 +889,6 @@ void l2tp_recv_common(struct l2tp_session *session, struct 
sk_buff *skb,
+       /* Try to dequeue as many skbs from reorder_q as we can. */
+       l2tp_recv_dequeue(session);
+ 
+-      l2tp_session_dec_refcount(session);
+-
+       return;
+ 
+ discard:
+@@ -813,8 +897,6 @@ discard:
+ 
+       if (session->deref)
+               (*session->deref)(session);
+-
+-      l2tp_session_dec_refcount(session);
+ }
+ EXPORT_SYMBOL(l2tp_recv_common);
+ 
+@@ -921,8 +1003,14 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel 
*tunnel, struct sk_buff *skb,
+       }
+ 
+       /* Find the session context */
+-      session = l2tp_session_find(tunnel->l2tp_net, tunnel, session_id);
++      session = l2tp_session_get(tunnel->l2tp_net, tunnel, session_id, true);
+       if (!session || !session->recv_skb) {
++              if (session) {
++                      if (session->deref)
++                              session->deref(session);
++                      l2tp_session_dec_refcount(session);
++              }
++
+               /* Not found? Pass to userspace to deal with */
+               l2tp_info(tunnel, L2TP_MSG_DATA,
+                         "%s: no session found (%u/%u). Passing up.\n",
+@@ -935,6 +1023,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, 
struct sk_buff *skb,
+               goto error;
+ 
+       l2tp_recv_common(session, skb, ptr, optr, hdrflags, length, 
payload_hook);
++      l2tp_session_dec_refcount(session);
+ 
+       return 0;
+ 
+@@ -1262,6 +1351,9 @@ again:
+ 
+                       hlist_del_init(&session->hlist);
+ 
++                      if (test_and_set_bit(0, &session->dead))
++                              goto again;
++
+                       if (session->ref != NULL)
+                               (*session->ref)(session);
+ 
+@@ -1710,6 +1802,9 @@ EXPORT_SYMBOL_GPL(__l2tp_session_unhash);
+  */
+ int l2tp_session_delete(struct l2tp_session *session)
+ {
++      if (test_and_set_bit(0, &session->dead))
++              return 0;
++
+       if (session->ref)
+               (*session->ref)(session);
+       __l2tp_session_unhash(session);
+@@ -1745,6 +1840,7 @@ EXPORT_SYMBOL_GPL(l2tp_session_set_header_len);
+ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel 
*tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg)
+ {
+       struct l2tp_session *session;
++      int err;
+ 
+       session = kzalloc(sizeof(struct l2tp_session) + priv_size, GFP_KERNEL);
+       if (session != NULL) {
+@@ -1800,6 +1896,13 @@ struct l2tp_session *l2tp_session_create(int priv_size, 
struct l2tp_tunnel *tunn
+ 
+               l2tp_session_set_header_len(session, tunnel->version);
+ 
++              err = l2tp_session_add_to_tunnel(tunnel, session);
++              if (err) {
++                      kfree(session);
++
++                      return ERR_PTR(err);
++              }
++
+               /* Bump the reference count. The session context is deleted
+                * only when this drops to zero.
+                */
+@@ -1809,28 +1912,14 @@ struct l2tp_session *l2tp_session_create(int 
priv_size, struct l2tp_tunnel *tunn
+               /* Ensure tunnel socket isn't deleted */
+               sock_hold(tunnel->sock);
+ 
+-              /* Add session to the tunnel's hash list */
+-              write_lock_bh(&tunnel->hlist_lock);
+-              hlist_add_head(&session->hlist,
+-                             l2tp_session_id_hash(tunnel, session_id));
+-              write_unlock_bh(&tunnel->hlist_lock);
+-
+-              /* And to the global session list if L2TPv3 */
+-              if (tunnel->version != L2TP_HDR_VER_2) {
+-                      struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net);
+-
+-                      spin_lock_bh(&pn->l2tp_session_hlist_lock);
+-                      hlist_add_head_rcu(&session->global_hlist,
+-                                         l2tp_session_id_hash_2(pn, 
session_id));
+-                      spin_unlock_bh(&pn->l2tp_session_hlist_lock);
+-              }
+-
+               /* Ignore management session in session count value */
+               if (session->session_id != 0)
+                       atomic_inc(&l2tp_session_count);
++
++              return session;
+       }
+ 
+-      return session;
++      return ERR_PTR(-ENOMEM);
+ }
+ EXPORT_SYMBOL_GPL(l2tp_session_create);
+ 
+diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
+index fad47e9d74bc..06323a12d62c 100644
+--- a/net/l2tp/l2tp_core.h
++++ b/net/l2tp/l2tp_core.h
+@@ -85,6 +85,7 @@ struct l2tp_session_cfg {
+ struct l2tp_session {
+       int                     magic;          /* should be
+                                                * L2TP_SESSION_MAGIC */
++      long                    dead;
+ 
+       struct l2tp_tunnel      *tunnel;        /* back pointer to tunnel
+                                                * context */
+@@ -243,6 +244,9 @@ out:
+       return tunnel;
+ }
+ 
++struct l2tp_session *l2tp_session_get(struct net *net,
++                                    struct l2tp_tunnel *tunnel,
++                                    u32 session_id, bool do_ref);
+ struct l2tp_session *l2tp_session_find(struct net *net,
+                                      struct l2tp_tunnel *tunnel,
+                                      u32 session_id);
+diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
+index e253c26f31ac..c94160df71af 100644
+--- a/net/l2tp/l2tp_eth.c
++++ b/net/l2tp/l2tp_eth.c
+@@ -223,12 +223,6 @@ static int l2tp_eth_create(struct net *net, u32 
tunnel_id, u32 session_id, u32 p
+               goto out;
+       }
+ 
+-      session = l2tp_session_find(net, tunnel, session_id);
+-      if (session) {
+-              rc = -EEXIST;
+-              goto out;
+-      }
+-
+       if (cfg->ifname) {
+               dev = dev_get_by_name(net, cfg->ifname);
+               if (dev) {
+@@ -242,8 +236,8 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, 
u32 session_id, u32 p
+ 
+       session = l2tp_session_create(sizeof(*spriv), tunnel, session_id,
+                                     peer_session_id, cfg);
+-      if (!session) {
+-              rc = -ENOMEM;
++      if (IS_ERR(session)) {
++              rc = PTR_ERR(session);
+               goto out;
+       }
+ 
+diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
+index 7efb3cadc152..58f87bdd12c7 100644
+--- a/net/l2tp/l2tp_ip.c
++++ b/net/l2tp/l2tp_ip.c
+@@ -142,19 +142,19 @@ static int l2tp_ip_recv(struct sk_buff *skb)
+       }
+ 
+       /* Ok, this is a data packet. Lookup the session. */
+-      session = l2tp_session_find(net, NULL, session_id);
+-      if (session == NULL)
++      session = l2tp_session_get(net, NULL, session_id, true);
++      if (!session)
+               goto discard;
+ 
+       tunnel = session->tunnel;
+-      if (tunnel == NULL)
+-              goto discard;
++      if (!tunnel)
++              goto discard_sess;
+ 
+       /* Trace packet contents, if enabled */
+       if (tunnel->debug & L2TP_MSG_DATA) {
+               length = min(32u, skb->len);
+               if (!pskb_may_pull(skb, length))
+-                      goto discard;
++                      goto discard_sess;
+ 
+               /* Point to L2TP header */
+               optr = ptr = skb->data;
+@@ -167,6 +167,7 @@ static int l2tp_ip_recv(struct sk_buff *skb)
+               goto discard;
+ 
+       l2tp_recv_common(session, skb, ptr, optr, 0, skb->len, 
tunnel->recv_payload_hook);
++      l2tp_session_dec_refcount(session);
+ 
+       return 0;
+ 
+@@ -204,6 +205,12 @@ pass_up:
+ 
+       return sk_receive_skb(sk, skb, 1);
+ 
++discard_sess:
++      if (session->deref)
++              session->deref(session);
++      l2tp_session_dec_refcount(session);
++      goto discard;
++
+ discard_put:
+       sock_put(sk);
+ 
+diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
+index a88649c5d26c..af04a8a68269 100644
+--- a/net/l2tp/l2tp_ip6.c
++++ b/net/l2tp/l2tp_ip6.c
+@@ -127,6 +127,7 @@ static inline struct sock *l2tp_ip6_bind_lookup(struct net 
*net,
+  */
+ static int l2tp_ip6_recv(struct sk_buff *skb)
+ {
++      struct net *net = dev_net(skb->dev);
+       struct sock *sk;
+       u32 session_id;
+       u32 tunnel_id;
+@@ -153,19 +154,19 @@ static int l2tp_ip6_recv(struct sk_buff *skb)
+       }
+ 
+       /* Ok, this is a data packet. Lookup the session. */
+-      session = l2tp_session_find(&init_net, NULL, session_id);
+-      if (session == NULL)
++      session = l2tp_session_get(net, NULL, session_id, true);
++      if (!session)
+               goto discard;
+ 
+       tunnel = session->tunnel;
+-      if (tunnel == NULL)
+-              goto discard;
++      if (!tunnel)
++              goto discard_sess;
+ 
+       /* Trace packet contents, if enabled */
+       if (tunnel->debug & L2TP_MSG_DATA) {
+               length = min(32u, skb->len);
+               if (!pskb_may_pull(skb, length))
+-                      goto discard;
++                      goto discard_sess;
+ 
+               /* Point to L2TP header */
+               optr = ptr = skb->data;
+@@ -179,6 +180,8 @@ static int l2tp_ip6_recv(struct sk_buff *skb)
+ 
+       l2tp_recv_common(session, skb, ptr, optr, 0, skb->len,
+                        tunnel->recv_payload_hook);
++      l2tp_session_dec_refcount(session);
++
+       return 0;
+ 
+ pass_up:
+@@ -190,7 +193,7 @@ pass_up:
+               goto discard;
+ 
+       tunnel_id = ntohl(*(__be32 *) &skb->data[4]);
+-      tunnel = l2tp_tunnel_find(&init_net, tunnel_id);
++      tunnel = l2tp_tunnel_find(net, tunnel_id);
+       if (tunnel) {
+               sk = tunnel->sock;
+               sock_hold(sk);
+@@ -198,7 +201,7 @@ pass_up:
+               struct ipv6hdr *iph = ipv6_hdr(skb);
+ 
+               read_lock_bh(&l2tp_ip6_lock);
+-              sk = __l2tp_ip6_bind_lookup(&init_net, &iph->daddr,
++              sk = __l2tp_ip6_bind_lookup(net, &iph->daddr,
+                                           0, tunnel_id);
+               if (!sk) {
+                       read_unlock_bh(&l2tp_ip6_lock);
+@@ -216,6 +219,12 @@ pass_up:
+ 
+       return sk_receive_skb(sk, skb, 1);
+ 
++discard_sess:
++      if (session->deref)
++              session->deref(session);
++      l2tp_session_dec_refcount(session);
++      goto discard;
++
+ discard_put:
+       sock_put(sk);
+ 
+@@ -267,6 +276,7 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr 
*uaddr, int addr_len)
+       struct inet_sock *inet = inet_sk(sk);
+       struct ipv6_pinfo *np = inet6_sk(sk);
+       struct sockaddr_l2tpip6 *addr = (struct sockaddr_l2tpip6 *) uaddr;
++      struct net *net = sock_net(sk);
+       __be32 v4addr = 0;
+       int addr_type;
+       int err;
+@@ -288,7 +298,7 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr 
*uaddr, int addr_len)
+ 
+       err = -EADDRINUSE;
+       read_lock_bh(&l2tp_ip6_lock);
+-      if (__l2tp_ip6_bind_lookup(&init_net, &addr->l2tp_addr,
++      if (__l2tp_ip6_bind_lookup(net, &addr->l2tp_addr,
+                                  sk->sk_bound_dev_if, addr->l2tp_conn_id))
+               goto out_in_use;
+       read_unlock_bh(&l2tp_ip6_lock);
+@@ -461,7 +471,7 @@ static int l2tp_ip6_backlog_recv(struct sock *sk, struct 
sk_buff *skb)
+       return 0;
+ 
+ drop:
+-      IP_INC_STATS(&init_net, IPSTATS_MIB_INDISCARDS);
++      IP_INC_STATS(sock_net(sk), IPSTATS_MIB_INDISCARDS);
+       kfree_skb(skb);
+       return -1;
+ }
+diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
+index d3f1222c1a8c..bc5d6b8f8ede 100644
+--- a/net/l2tp/l2tp_ppp.c
++++ b/net/l2tp/l2tp_ppp.c
+@@ -177,7 +177,7 @@ static int pppol2tp_recv_payload_hook(struct sk_buff *skb)
+       if (!pskb_may_pull(skb, 2))
+               return 1;
+ 
+-      if ((skb->data[0] == 0xff) && (skb->data[1] == 0x03))
++      if ((skb->data[0] == PPP_ALLSTATIONS) && (skb->data[1] == PPP_UI))
+               skb_pull(skb, 2);
+ 
+       return 0;
+@@ -297,7 +297,6 @@ static void pppol2tp_session_sock_put(struct l2tp_session 
*session)
+ static int pppol2tp_sendmsg(struct socket *sock, struct msghdr *m,
+                           size_t total_len)
+ {
+-      static const unsigned char ppph[2] = { 0xff, 0x03 };
+       struct sock *sk = sock->sk;
+       struct sk_buff *skb;
+       int error;
+@@ -327,7 +326,7 @@ static int pppol2tp_sendmsg(struct socket *sock, struct 
msghdr *m,
+       error = -ENOMEM;
+       skb = sock_wmalloc(sk, NET_SKB_PAD + sizeof(struct iphdr) +
+                          uhlen + session->hdr_len +
+-                         sizeof(ppph) + total_len,
++                         2 + total_len, /* 2 bytes for PPP_ALLSTATIONS & 
PPP_UI */
+                          0, GFP_KERNEL);
+       if (!skb)
+               goto error_put_sess_tun;
+@@ -340,8 +339,8 @@ static int pppol2tp_sendmsg(struct socket *sock, struct 
msghdr *m,
+       skb_reserve(skb, uhlen);
+ 
+       /* Add PPP header */
+-      skb->data[0] = ppph[0];
+-      skb->data[1] = ppph[1];
++      skb->data[0] = PPP_ALLSTATIONS;
++      skb->data[1] = PPP_UI;
+       skb_put(skb, 2);
+ 
+       /* Copy user data into skb */
+@@ -384,7 +383,6 @@ error:
+  */
+ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+ {
+-      static const u8 ppph[2] = { 0xff, 0x03 };
+       struct sock *sk = (struct sock *) chan->private;
+       struct sock *sk_tun;
+       struct l2tp_session *session;
+@@ -413,14 +411,14 @@ static int pppol2tp_xmit(struct ppp_channel *chan, 
struct sk_buff *skb)
+                  sizeof(struct iphdr) + /* IP header */
+                  uhlen +              /* UDP header (if L2TP_ENCAPTYPE_UDP) */
+                  session->hdr_len +   /* L2TP header */
+-                 sizeof(ppph);        /* PPP header */
++                 2;                   /* 2 bytes for PPP_ALLSTATIONS & PPP_UI 
*/
+       if (skb_cow_head(skb, headroom))
+               goto abort_put_sess_tun;
+ 
+       /* Setup PPP header */
+-      __skb_push(skb, sizeof(ppph));
+-      skb->data[0] = ppph[0];
+-      skb->data[1] = ppph[1];
++      __skb_push(skb, 2);
++      skb->data[0] = PPP_ALLSTATIONS;
++      skb->data[1] = PPP_UI;
+ 
+       local_bh_disable();
+       l2tp_xmit_skb(session, skb, session->hdr_len);
+@@ -454,11 +452,11 @@ static void pppol2tp_session_close(struct l2tp_session 
*session)
+ 
+       BUG_ON(session->magic != L2TP_SESSION_MAGIC);
+ 
+-      if (sock) {
+-              inet_shutdown(sock, 2);
+-              /* Don't let the session go away before our socket does */
+-              l2tp_session_inc_refcount(session);
+-      }
++      if (sock)
++              inet_shutdown(sock, SEND_SHUTDOWN);
++
++      /* Don't let the session go away before our socket does */
++      l2tp_session_inc_refcount(session);
+ }
+ 
+ /* Really kill the session socket. (Called from sock_put() if
+@@ -600,6 +598,7 @@ static int pppol2tp_connect(struct socket *sock, struct 
sockaddr *uservaddr,
+       int error = 0;
+       u32 tunnel_id, peer_tunnel_id;
+       u32 session_id, peer_session_id;
++      bool drop_refcnt = false;
+       int ver = 2;
+       int fd;
+ 
+@@ -708,36 +707,36 @@ static int pppol2tp_connect(struct socket *sock, struct 
sockaddr *uservaddr,
+       if (tunnel->peer_tunnel_id == 0)
+               tunnel->peer_tunnel_id = peer_tunnel_id;
+ 
+-      /* Create session if it doesn't already exist. We handle the
+-       * case where a session was previously created by the netlink
+-       * interface by checking that the session doesn't already have
+-       * a socket and its tunnel socket are what we expect. If any
+-       * of those checks fail, return EEXIST to the caller.
+-       */
+-      session = l2tp_session_find(sock_net(sk), tunnel, session_id);
+-      if (session == NULL) {
+-              /* Default MTU must allow space for UDP/L2TP/PPP
+-               * headers.
++      session = l2tp_session_get(sock_net(sk), tunnel, session_id, false);
++      if (session) {
++              drop_refcnt = true;
++              ps = l2tp_session_priv(session);
++
++              /* Using a pre-existing session is fine as long as it hasn't
++               * been connected yet.
+                */
+-              cfg.mtu = cfg.mru = 1500 - PPPOL2TP_HEADER_OVERHEAD;
++              if (ps->sock) {
++                      error = -EEXIST;
++                      goto end;
++              }
+ 
+-              /* Allocate and initialize a new session context. */
+-              session = l2tp_session_create(sizeof(struct pppol2tp_session),
+-                                            tunnel, session_id,
+-                                            peer_session_id, &cfg);
+-              if (session == NULL) {
+-                      error = -ENOMEM;
++              /* consistency checks */
++              if (ps->tunnel_sock != tunnel->sock) {
++                      error = -EEXIST;
+                       goto end;
+               }
+       } else {
+-              ps = l2tp_session_priv(session);
+-              error = -EEXIST;
+-              if (ps->sock != NULL)
+-                      goto end;
++              /* Default MTU must allow space for UDP/L2TP/PPP headers */
++              cfg.mtu = 1500 - PPPOL2TP_HEADER_OVERHEAD;
++              cfg.mru = cfg.mtu;
+ 
+-              /* consistency checks */
+-              if (ps->tunnel_sock != tunnel->sock)
++              session = l2tp_session_create(sizeof(struct pppol2tp_session),
++                                            tunnel, session_id,
++                                            peer_session_id, &cfg);
++              if (IS_ERR(session)) {
++                      error = PTR_ERR(session);
+                       goto end;
++              }
+       }
+ 
+       /* Associate session with its PPPoL2TP socket */
+@@ -802,6 +801,8 @@ out_no_ppp:
+                 session->name);
+ 
+ end:
++      if (drop_refcnt)
++              l2tp_session_dec_refcount(session);
+       release_sock(sk);
+ 
+       return error;
+@@ -829,12 +830,6 @@ static int pppol2tp_session_create(struct net *net, u32 
tunnel_id, u32 session_i
+       if (tunnel->sock == NULL)
+               goto out;
+ 
+-      /* Check that this session doesn't already exist */
+-      error = -EEXIST;
+-      session = l2tp_session_find(net, tunnel, session_id);
+-      if (session != NULL)
+-              goto out;
+-
+       /* Default MTU values. */
+       if (cfg->mtu == 0)
+               cfg->mtu = 1500 - PPPOL2TP_HEADER_OVERHEAD;
+@@ -842,12 +837,13 @@ static int pppol2tp_session_create(struct net *net, u32 
tunnel_id, u32 session_i
+               cfg->mru = cfg->mtu;
+ 
+       /* Allocate and initialize a new session context. */
+-      error = -ENOMEM;
+       session = l2tp_session_create(sizeof(struct pppol2tp_session),
+                                     tunnel, session_id,
+                                     peer_session_id, cfg);
+-      if (session == NULL)
++      if (IS_ERR(session)) {
++              error = PTR_ERR(session);
+               goto out;
++      }
+ 
+       ps = l2tp_session_priv(session);
+       ps->tunnel_sock = tunnel->sock;
+@@ -889,10 +885,8 @@ static int pppol2tp_getname(struct socket *sock, struct 
sockaddr *uaddr,
+ 
+       pls = l2tp_session_priv(session);
+       tunnel = l2tp_sock_to_tunnel(pls->tunnel_sock);
+-      if (tunnel == NULL) {
+-              error = -EBADF;
++      if (tunnel == NULL)
+               goto end_put_sess;
+-      }
+ 
+       inet = inet_sk(tunnel->sock);
+       if ((tunnel->version == 2) && (tunnel->sock->sk_family == AF_INET)) {
+@@ -970,12 +964,11 @@ static int pppol2tp_getname(struct socket *sock, struct 
sockaddr *uaddr,
+       }
+ 
+       *usockaddr_len = len;
++      error = 0;
+ 
+       sock_put(pls->tunnel_sock);
+ end_put_sess:
+       sock_put(sk);
+-      error = 0;
+-
+ end:
+       return error;
+ }
+@@ -1171,11 +1164,18 @@ static int pppol2tp_tunnel_ioctl(struct l2tp_tunnel 
*tunnel,
+               if (stats.session_id != 0) {
+                       /* resend to session ioctl handler */
+                       struct l2tp_session *session =
+-                              l2tp_session_find(sock_net(sk), tunnel, 
stats.session_id);
+-                      if (session != NULL)
+-                              err = pppol2tp_session_ioctl(session, cmd, arg);
+-                      else
++                              l2tp_session_get(sock_net(sk), tunnel,
++                                               stats.session_id, true);
++
++                      if (session) {
++                              err = pppol2tp_session_ioctl(session, cmd,
++                                                           arg);
++                              if (session->deref)
++                                      session->deref(session);
++                              l2tp_session_dec_refcount(session);
++                      } else {
+                               err = -EBADR;
++                      }
+                       break;
+               }
+ #ifdef CONFIG_XFRM
+diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
+index ae619cffc3a9..dd097e065f39 100644
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -234,7 +234,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, 
union sctp_addr *saddr,
+ {
+       struct sctp_association *asoc = t->asoc;
+       struct dst_entry *dst = NULL;
+-      struct flowi6 *fl6 = &fl->u.ip6;
++      struct flowi _fl;
++      struct flowi6 *fl6 = &_fl.u.ip6;
+       struct sctp_bind_addr *bp;
+       struct ipv6_pinfo *np = inet6_sk(sk);
+       struct sctp_sockaddr_entry *laddr;
+@@ -244,7 +245,7 @@ static void sctp_v6_get_dst(struct sctp_transport *t, 
union sctp_addr *saddr,
+       __u8 matchlen = 0;
+       sctp_scope_t scope;
+ 
+-      memset(fl6, 0, sizeof(struct flowi6));
++      memset(&_fl, 0, sizeof(_fl));
+       fl6->daddr = daddr->v6.sin6_addr;
+       fl6->fl6_dport = daddr->v6.sin6_port;
+       fl6->flowi6_proto = IPPROTO_SCTP;
+@@ -268,8 +269,11 @@ static void sctp_v6_get_dst(struct sctp_transport *t, 
union sctp_addr *saddr,
+       rcu_read_unlock();
+ 
+       dst = ip6_dst_lookup_flow(sk, fl6, final_p);
+-      if (!asoc || saddr)
++      if (!asoc || saddr) {
++              t->dst = dst;
++              memcpy(fl, &_fl, sizeof(_fl));
+               goto out;
++      }
+ 
+       bp = &asoc->base.bind_addr;
+       scope = sctp_scope(daddr);
+@@ -292,6 +296,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, 
union sctp_addr *saddr,
+                       if ((laddr->a.sa.sa_family == AF_INET6) &&
+                           (sctp_v6_cmp_addr(&dst_saddr, &laddr->a))) {
+                               rcu_read_unlock();
++                              t->dst = dst;
++                              memcpy(fl, &_fl, sizeof(_fl));
+                               goto out;
+                       }
+               }
+@@ -330,6 +336,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, 
union sctp_addr *saddr,
+                       if (!IS_ERR_OR_NULL(dst))
+                               dst_release(dst);
+                       dst = bdst;
++                      t->dst = dst;
++                      memcpy(fl, &_fl, sizeof(_fl));
+                       break;
+               }
+ 
+@@ -343,6 +351,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, 
union sctp_addr *saddr,
+                       dst_release(dst);
+               dst = bdst;
+               matchlen = bmatchlen;
++              t->dst = dst;
++              memcpy(fl, &_fl, sizeof(_fl));
+       }
+       rcu_read_unlock();
+ 
+@@ -351,14 +361,12 @@ out:
+               struct rt6_info *rt;
+ 
+               rt = (struct rt6_info *)dst;
+-              t->dst = dst;
+               t->dst_cookie = rt6_get_cookie(rt);
+               pr_debug("rt6_dst:%pI6/%d rt6_src:%pI6\n",
+                        &rt->rt6i_dst.addr, rt->rt6i_dst.plen,
+-                       &fl6->saddr);
++                       &fl->u.ip6.saddr);
+       } else {
+               t->dst = NULL;
+-
+               pr_debug("no route\n");
+       }
+ }
+diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
+index 7e550265df87..9c6c42fd9f8a 100644
+--- a/net/sctp/protocol.c
++++ b/net/sctp/protocol.c
+@@ -428,14 +428,15 @@ static void sctp_v4_get_dst(struct sctp_transport *t, 
union sctp_addr *saddr,
+ {
+       struct sctp_association *asoc = t->asoc;
+       struct rtable *rt;
+-      struct flowi4 *fl4 = &fl->u.ip4;
++      struct flowi _fl;
++      struct flowi4 *fl4 = &_fl.u.ip4;
+       struct sctp_bind_addr *bp;
+       struct sctp_sockaddr_entry *laddr;
+       struct dst_entry *dst = NULL;
+       union sctp_addr *daddr = &t->ipaddr;
+       union sctp_addr dst_saddr;
+ 
+-      memset(fl4, 0x0, sizeof(struct flowi4));
++      memset(&_fl, 0x0, sizeof(_fl));
+       fl4->daddr  = daddr->v4.sin_addr.s_addr;
+       fl4->fl4_dport = daddr->v4.sin_port;
+       fl4->flowi4_proto = IPPROTO_SCTP;
+@@ -453,8 +454,11 @@ static void sctp_v4_get_dst(struct sctp_transport *t, 
union sctp_addr *saddr,
+                &fl4->saddr);
+ 
+       rt = ip_route_output_key(sock_net(sk), fl4);
+-      if (!IS_ERR(rt))
++      if (!IS_ERR(rt)) {
+               dst = &rt->dst;
++              t->dst = dst;
++              memcpy(fl, &_fl, sizeof(_fl));
++      }
+ 
+       /* If there is no association or if a source address is passed, no
+        * more validation is required.
+@@ -517,27 +521,33 @@ static void sctp_v4_get_dst(struct sctp_transport *t, 
union sctp_addr *saddr,
+               odev = __ip_dev_find(sock_net(sk), laddr->a.v4.sin_addr.s_addr,
+                                    false);
+               if (!odev || odev->ifindex != fl4->flowi4_oif) {
+-                      if (!dst)
++                      if (!dst) {
+                               dst = &rt->dst;
+-                      else
++                              t->dst = dst;
++                              memcpy(fl, &_fl, sizeof(_fl));
++                      } else {
+                               dst_release(&rt->dst);
++                      }
+                       continue;
+               }
+ 
+               dst_release(dst);
+               dst = &rt->dst;
++              t->dst = dst;
++              memcpy(fl, &_fl, sizeof(_fl));
+               break;
+       }
+ 
+ out_unlock:
+       rcu_read_unlock();
+ out:
+-      t->dst = dst;
+-      if (dst)
++      if (dst) {
+               pr_debug("rt_dst:%pI4, rt_src:%pI4\n",
+-                       &fl4->daddr, &fl4->saddr);
+-      else
++                       &fl->u.ip4.daddr, &fl->u.ip4.saddr);
++      } else {
++              t->dst = NULL;
+               pr_debug("no route\n");
++      }
+ }
+ 
+ /* For v4, the source address is cached in the route entry(dst). So no need
+diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
+index 794a3499e567..0dc1ab48fceb 100644
+--- a/sound/soc/jz4740/jz4740-i2s.c
++++ b/sound/soc/jz4740/jz4740-i2s.c
+@@ -92,7 +92,7 @@
+ #define JZ_AIC_I2S_STATUS_BUSY BIT(2)
+ 
+ #define JZ_AIC_CLK_DIV_MASK 0xf
+-#define I2SDIV_DV_SHIFT 8
++#define I2SDIV_DV_SHIFT 0
+ #define I2SDIV_DV_MASK (0xf << I2SDIV_DV_SHIFT)
+ #define I2SDIV_IDV_SHIFT 8
+ #define I2SDIV_IDV_MASK (0xf << I2SDIV_IDV_SHIFT)

Reply via email to