]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 18 Feb 2019 12:48:45 +0000 (13:48 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 18 Feb 2019 12:48:45 +0000 (13:48 +0100)
added patches:
ch9200-use-skb_cow_head-to-deal-with-cloned-skbs.patch
kaweth-use-skb_cow_head-to-deal-with-cloned-skbs.patch
netfilter-nf_tables-fix-mismatch-in-big-endian-system.patch
smsc95xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch
usb-dwc2-remove-unnecessary-kfree.patch

queue-4.9/ch9200-use-skb_cow_head-to-deal-with-cloned-skbs.patch [new file with mode: 0644]
queue-4.9/kaweth-use-skb_cow_head-to-deal-with-cloned-skbs.patch [new file with mode: 0644]
queue-4.9/netfilter-nf_tables-fix-mismatch-in-big-endian-system.patch [new file with mode: 0644]
queue-4.9/series
queue-4.9/smsc95xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch [new file with mode: 0644]
queue-4.9/usb-dwc2-remove-unnecessary-kfree.patch [new file with mode: 0644]

diff --git a/queue-4.9/ch9200-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/queue-4.9/ch9200-use-skb_cow_head-to-deal-with-cloned-skbs.patch
new file mode 100644 (file)
index 0000000..45543c3
--- /dev/null
@@ -0,0 +1,45 @@
+From 6bc6895bdd6744e0136eaa4a11fbdb20a7db4e40 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Wed, 19 Apr 2017 09:59:25 -0700
+Subject: ch9200: use skb_cow_head() to deal with cloned skbs
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit 6bc6895bdd6744e0136eaa4a11fbdb20a7db4e40 upstream.
+
+We need to ensure there is enough headroom to push extra header,
+but we also need to check if we are allowed to change headers.
+
+skb_cow_head() is the proper helper to deal with this.
+
+Fixes: 4a476bd6d1d9 ("usbnet: New driver for QinHeng CH9200 devices")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: James Hughes <james.hughes@raspberrypi.org>
+Cc: Matthew Garrett <mjg59@srcf.ucam.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/usb/ch9200.c |    9 ++-------
+ 1 file changed, 2 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/usb/ch9200.c
++++ b/drivers/net/usb/ch9200.c
+@@ -254,14 +254,9 @@ static struct sk_buff *ch9200_tx_fixup(s
+       tx_overhead = 0x40;
+       len = skb->len;
+-      if (skb_headroom(skb) < tx_overhead) {
+-              struct sk_buff *skb2;
+-
+-              skb2 = skb_copy_expand(skb, tx_overhead, 0, flags);
++      if (skb_cow_head(skb, tx_overhead)) {
+               dev_kfree_skb_any(skb);
+-              skb = skb2;
+-              if (!skb)
+-                      return NULL;
++              return NULL;
+       }
+       __skb_push(skb, tx_overhead);
diff --git a/queue-4.9/kaweth-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/queue-4.9/kaweth-use-skb_cow_head-to-deal-with-cloned-skbs.patch
new file mode 100644 (file)
index 0000000..e7b85c8
--- /dev/null
@@ -0,0 +1,50 @@
+From 39fba7835aacda65284a86e611774cbba71dac20 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Wed, 19 Apr 2017 09:59:26 -0700
+Subject: kaweth: use skb_cow_head() to deal with cloned skbs
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit 39fba7835aacda65284a86e611774cbba71dac20 upstream.
+
+We can use skb_cow_head() to properly deal with clones,
+especially the ones coming from TCP stack that allow their head being
+modified. This avoids a copy.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: James Hughes <james.hughes@raspberrypi.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/usb/kaweth.c |   18 ++++++------------
+ 1 file changed, 6 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/usb/kaweth.c
++++ b/drivers/net/usb/kaweth.c
+@@ -803,18 +803,12 @@ static netdev_tx_t kaweth_start_xmit(str
+       }
+       /* We now decide whether we can put our special header into the sk_buff */
+-      if (skb_cloned(skb) || skb_headroom(skb) < 2) {
+-              /* no such luck - we make our own */
+-              struct sk_buff *copied_skb;
+-              copied_skb = skb_copy_expand(skb, 2, 0, GFP_ATOMIC);
+-              dev_kfree_skb_irq(skb);
+-              skb = copied_skb;
+-              if (!copied_skb) {
+-                      kaweth->stats.tx_errors++;
+-                      netif_start_queue(net);
+-                      spin_unlock_irq(&kaweth->device_lock);
+-                      return NETDEV_TX_OK;
+-              }
++      if (skb_cow_head(skb, 2)) {
++              kaweth->stats.tx_errors++;
++              netif_start_queue(net);
++              spin_unlock_irq(&kaweth->device_lock);
++              dev_kfree_skb_any(skb);
++              return NETDEV_TX_OK;
+       }
+       private_header = (__le16 *)__skb_push(skb, 2);
diff --git a/queue-4.9/netfilter-nf_tables-fix-mismatch-in-big-endian-system.patch b/queue-4.9/netfilter-nf_tables-fix-mismatch-in-big-endian-system.patch
new file mode 100644 (file)
index 0000000..412d770
--- /dev/null
@@ -0,0 +1,330 @@
+From 10596608c4d62cb8c1c2b806debcbd32fe657e71 Mon Sep 17 00:00:00 2001
+From: Liping Zhang <zlpnobody@gmail.com>
+Date: Wed, 8 Mar 2017 22:54:18 +0800
+Subject: netfilter: nf_tables: fix mismatch in big-endian system
+
+From: Liping Zhang <zlpnobody@gmail.com>
+
+commit 10596608c4d62cb8c1c2b806debcbd32fe657e71 upstream.
+
+Currently, there are two different methods to store an u16 integer to
+the u32 data register. For example:
+  u32 *dest = &regs->data[priv->dreg];
+  1. *dest = 0; *(u16 *) dest = val_u16;
+  2. *dest = val_u16;
+
+For method 1, the u16 value will be stored like this, either in
+big-endian or little-endian system:
+  0          15           31
+  +-+-+-+-+-+-+-+-+-+-+-+-+
+  |   Value   |     0     |
+  +-+-+-+-+-+-+-+-+-+-+-+-+
+
+For method 2, in little-endian system, the u16 value will be the same
+as listed above. But in big-endian system, the u16 value will be stored
+like this:
+  0          15           31
+  +-+-+-+-+-+-+-+-+-+-+-+-+
+  |     0     |   Value   |
+  +-+-+-+-+-+-+-+-+-+-+-+-+
+
+So later we use "memcmp(&regs->data[priv->sreg], data, 2);" to do
+compare in nft_cmp, nft_lookup expr ..., method 2 will get the wrong
+result in big-endian system, as 0~15 bits will always be zero.
+
+For the similar reason, when loading an u16 value from the u32 data
+register, we should use "*(u16 *) sreg;" instead of "(u16)*sreg;",
+the 2nd method will get the wrong value in the big-endian system.
+
+So introduce some wrapper functions to store/load an u8 or u16
+integer to/from the u32 data register, and use them in the right
+place.
+
+Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/net/netfilter/nf_tables.h   |   29 ++++++++++++++++++++++++
+ net/ipv4/netfilter/nft_masq_ipv4.c  |    8 +++---
+ net/ipv4/netfilter/nft_redir_ipv4.c |    8 +++---
+ net/ipv6/netfilter/nft_masq_ipv6.c  |    8 +++---
+ net/ipv6/netfilter/nft_redir_ipv6.c |    8 +++---
+ net/netfilter/nft_ct.c              |   10 ++++----
+ net/netfilter/nft_meta.c            |   42 ++++++++++++++++++------------------
+ net/netfilter/nft_nat.c             |    8 +++---
+ 8 files changed, 76 insertions(+), 45 deletions(-)
+
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -87,6 +87,35 @@ struct nft_regs {
+       };
+ };
++/* Store/load an u16 or u8 integer to/from the u32 data register.
++ *
++ * Note, when using concatenations, register allocation happens at 32-bit
++ * level. So for store instruction, pad the rest part with zero to avoid
++ * garbage values.
++ */
++
++static inline void nft_reg_store16(u32 *dreg, u16 val)
++{
++      *dreg = 0;
++      *(u16 *)dreg = val;
++}
++
++static inline void nft_reg_store8(u32 *dreg, u8 val)
++{
++      *dreg = 0;
++      *(u8 *)dreg = val;
++}
++
++static inline u16 nft_reg_load16(u32 *sreg)
++{
++      return *(u16 *)sreg;
++}
++
++static inline u8 nft_reg_load8(u32 *sreg)
++{
++      return *(u8 *)sreg;
++}
++
+ static inline void nft_data_copy(u32 *dst, const struct nft_data *src,
+                                unsigned int len)
+ {
+--- a/net/ipv4/netfilter/nft_masq_ipv4.c
++++ b/net/ipv4/netfilter/nft_masq_ipv4.c
+@@ -26,10 +26,10 @@ static void nft_masq_ipv4_eval(const str
+       memset(&range, 0, sizeof(range));
+       range.flags = priv->flags;
+       if (priv->sreg_proto_min) {
+-              range.min_proto.all =
+-                      *(__be16 *)&regs->data[priv->sreg_proto_min];
+-              range.max_proto.all =
+-                      *(__be16 *)&regs->data[priv->sreg_proto_max];
++              range.min_proto.all = (__force __be16)nft_reg_load16(
++                      &regs->data[priv->sreg_proto_min]);
++              range.max_proto.all = (__force __be16)nft_reg_load16(
++                      &regs->data[priv->sreg_proto_max]);
+       }
+       regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, pkt->hook,
+                                                   &range, pkt->out);
+--- a/net/ipv4/netfilter/nft_redir_ipv4.c
++++ b/net/ipv4/netfilter/nft_redir_ipv4.c
+@@ -26,10 +26,10 @@ static void nft_redir_ipv4_eval(const st
+       memset(&mr, 0, sizeof(mr));
+       if (priv->sreg_proto_min) {
+-              mr.range[0].min.all =
+-                      *(__be16 *)&regs->data[priv->sreg_proto_min];
+-              mr.range[0].max.all =
+-                      *(__be16 *)&regs->data[priv->sreg_proto_max];
++              mr.range[0].min.all = (__force __be16)nft_reg_load16(
++                      &regs->data[priv->sreg_proto_min]);
++              mr.range[0].max.all = (__force __be16)nft_reg_load16(
++                      &regs->data[priv->sreg_proto_max]);
+               mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+       }
+--- a/net/ipv6/netfilter/nft_masq_ipv6.c
++++ b/net/ipv6/netfilter/nft_masq_ipv6.c
+@@ -27,10 +27,10 @@ static void nft_masq_ipv6_eval(const str
+       memset(&range, 0, sizeof(range));
+       range.flags = priv->flags;
+       if (priv->sreg_proto_min) {
+-              range.min_proto.all =
+-                      *(__be16 *)&regs->data[priv->sreg_proto_min];
+-              range.max_proto.all =
+-                      *(__be16 *)&regs->data[priv->sreg_proto_max];
++              range.min_proto.all = (__force __be16)nft_reg_load16(
++                      &regs->data[priv->sreg_proto_min]);
++              range.max_proto.all = (__force __be16)nft_reg_load16(
++                      &regs->data[priv->sreg_proto_max]);
+       }
+       regs->verdict.code = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out);
+ }
+--- a/net/ipv6/netfilter/nft_redir_ipv6.c
++++ b/net/ipv6/netfilter/nft_redir_ipv6.c
+@@ -26,10 +26,10 @@ static void nft_redir_ipv6_eval(const st
+       memset(&range, 0, sizeof(range));
+       if (priv->sreg_proto_min) {
+-              range.min_proto.all =
+-                      *(__be16 *)&regs->data[priv->sreg_proto_min],
+-              range.max_proto.all =
+-                      *(__be16 *)&regs->data[priv->sreg_proto_max],
++              range.min_proto.all = (__force __be16)nft_reg_load16(
++                      &regs->data[priv->sreg_proto_min]);
++              range.max_proto.all = (__force __be16)nft_reg_load16(
++                      &regs->data[priv->sreg_proto_max]);
+               range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+       }
+--- a/net/netfilter/nft_ct.c
++++ b/net/netfilter/nft_ct.c
+@@ -77,7 +77,7 @@ static void nft_ct_get_eval(const struct
+       switch (priv->key) {
+       case NFT_CT_DIRECTION:
+-              *dest = CTINFO2DIR(ctinfo);
++              nft_reg_store8(dest, CTINFO2DIR(ctinfo));
+               return;
+       case NFT_CT_STATUS:
+               *dest = ct->status;
+@@ -129,10 +129,10 @@ static void nft_ct_get_eval(const struct
+               return;
+       }
+       case NFT_CT_L3PROTOCOL:
+-              *dest = nf_ct_l3num(ct);
++              nft_reg_store8(dest, nf_ct_l3num(ct));
+               return;
+       case NFT_CT_PROTOCOL:
+-              *dest = nf_ct_protonum(ct);
++              nft_reg_store8(dest, nf_ct_protonum(ct));
+               return;
+       default:
+               break;
+@@ -149,10 +149,10 @@ static void nft_ct_get_eval(const struct
+                      nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
+               return;
+       case NFT_CT_PROTO_SRC:
+-              *dest = (__force __u16)tuple->src.u.all;
++              nft_reg_store16(dest, (__force u16)tuple->src.u.all);
+               return;
+       case NFT_CT_PROTO_DST:
+-              *dest = (__force __u16)tuple->dst.u.all;
++              nft_reg_store16(dest, (__force u16)tuple->dst.u.all);
+               return;
+       default:
+               break;
+--- a/net/netfilter/nft_meta.c
++++ b/net/netfilter/nft_meta.c
+@@ -45,16 +45,15 @@ void nft_meta_get_eval(const struct nft_
+               *dest = skb->len;
+               break;
+       case NFT_META_PROTOCOL:
+-              *dest = 0;
+-              *(__be16 *)dest = skb->protocol;
++              nft_reg_store16(dest, (__force u16)skb->protocol);
+               break;
+       case NFT_META_NFPROTO:
+-              *dest = pkt->pf;
++              nft_reg_store8(dest, pkt->pf);
+               break;
+       case NFT_META_L4PROTO:
+               if (!pkt->tprot_set)
+                       goto err;
+-              *dest = pkt->tprot;
++              nft_reg_store8(dest, pkt->tprot);
+               break;
+       case NFT_META_PRIORITY:
+               *dest = skb->priority;
+@@ -85,14 +84,12 @@ void nft_meta_get_eval(const struct nft_
+       case NFT_META_IIFTYPE:
+               if (in == NULL)
+                       goto err;
+-              *dest = 0;
+-              *(u16 *)dest = in->type;
++              nft_reg_store16(dest, in->type);
+               break;
+       case NFT_META_OIFTYPE:
+               if (out == NULL)
+                       goto err;
+-              *dest = 0;
+-              *(u16 *)dest = out->type;
++              nft_reg_store16(dest, out->type);
+               break;
+       case NFT_META_SKUID:
+               sk = skb_to_full_sk(skb);
+@@ -142,22 +139,22 @@ void nft_meta_get_eval(const struct nft_
+ #endif
+       case NFT_META_PKTTYPE:
+               if (skb->pkt_type != PACKET_LOOPBACK) {
+-                      *dest = skb->pkt_type;
++                      nft_reg_store8(dest, skb->pkt_type);
+                       break;
+               }
+               switch (pkt->pf) {
+               case NFPROTO_IPV4:
+                       if (ipv4_is_multicast(ip_hdr(skb)->daddr))
+-                              *dest = PACKET_MULTICAST;
++                              nft_reg_store8(dest, PACKET_MULTICAST);
+                       else
+-                              *dest = PACKET_BROADCAST;
++                              nft_reg_store8(dest, PACKET_BROADCAST);
+                       break;
+               case NFPROTO_IPV6:
+                       if (ipv6_hdr(skb)->daddr.s6_addr[0] == 0xFF)
+-                              *dest = PACKET_MULTICAST;
++                              nft_reg_store8(dest, PACKET_MULTICAST);
+                       else
+-                              *dest = PACKET_BROADCAST;
++                              nft_reg_store8(dest, PACKET_BROADCAST);
+                       break;
+               case NFPROTO_NETDEV:
+                       switch (skb->protocol) {
+@@ -171,14 +168,14 @@ void nft_meta_get_eval(const struct nft_
+                                       goto err;
+                               if (ipv4_is_multicast(iph->daddr))
+-                                      *dest = PACKET_MULTICAST;
++                                      nft_reg_store8(dest, PACKET_MULTICAST);
+                               else
+-                                      *dest = PACKET_BROADCAST;
++                                      nft_reg_store8(dest, PACKET_BROADCAST);
+                               break;
+                       }
+                       case htons(ETH_P_IPV6):
+-                              *dest = PACKET_MULTICAST;
++                              nft_reg_store8(dest, PACKET_MULTICAST);
+                               break;
+                       default:
+                               WARN_ON_ONCE(1);
+@@ -233,7 +230,9 @@ void nft_meta_set_eval(const struct nft_
+ {
+       const struct nft_meta *meta = nft_expr_priv(expr);
+       struct sk_buff *skb = pkt->skb;
+-      u32 value = regs->data[meta->sreg];
++      u32 *sreg = &regs->data[meta->sreg];
++      u32 value = *sreg;
++      u8 pkt_type;
+       switch (meta->key) {
+       case NFT_META_MARK:
+@@ -243,9 +242,12 @@ void nft_meta_set_eval(const struct nft_
+               skb->priority = value;
+               break;
+       case NFT_META_PKTTYPE:
+-              if (skb->pkt_type != value &&
+-                  skb_pkt_type_ok(value) && skb_pkt_type_ok(skb->pkt_type))
+-                      skb->pkt_type = value;
++              pkt_type = nft_reg_load8(sreg);
++
++              if (skb->pkt_type != pkt_type &&
++                  skb_pkt_type_ok(pkt_type) &&
++                  skb_pkt_type_ok(skb->pkt_type))
++                      skb->pkt_type = pkt_type;
+               break;
+       case NFT_META_NFTRACE:
+               skb->nf_trace = !!value;
+--- a/net/netfilter/nft_nat.c
++++ b/net/netfilter/nft_nat.c
+@@ -65,10 +65,10 @@ static void nft_nat_eval(const struct nf
+       }
+       if (priv->sreg_proto_min) {
+-              range.min_proto.all =
+-                      *(__be16 *)&regs->data[priv->sreg_proto_min];
+-              range.max_proto.all =
+-                      *(__be16 *)&regs->data[priv->sreg_proto_max];
++              range.min_proto.all = (__force __be16)nft_reg_load16(
++                      &regs->data[priv->sreg_proto_min]);
++              range.max_proto.all = (__force __be16)nft_reg_load16(
++                      &regs->data[priv->sreg_proto_max]);
+               range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
+       }
index bb30904b44486d0cec11205305c762323d260ffc..b27cabbac9761d695dd9e20e2bb938b2451641e7 100644 (file)
@@ -49,3 +49,8 @@ signal-restore-the-stop-ptrace_event_exit.patch
 x86-a.out-clear-the-dump-structure-initially.patch
 dm-thin-fix-bug-where-bio-that-overwrites-thin-block-ignores-fua.patch
 drm-i915-prevent-a-race-during-i915_gem_mmap-ioctl-with-wc-set.patch
+smsc95xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch
+ch9200-use-skb_cow_head-to-deal-with-cloned-skbs.patch
+kaweth-use-skb_cow_head-to-deal-with-cloned-skbs.patch
+usb-dwc2-remove-unnecessary-kfree.patch
+netfilter-nf_tables-fix-mismatch-in-big-endian-system.patch
diff --git a/queue-4.9/smsc95xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch b/queue-4.9/smsc95xx-use-skb_cow_head-to-deal-with-cloned-skbs.patch
new file mode 100644 (file)
index 0000000..5ac1739
--- /dev/null
@@ -0,0 +1,47 @@
+From e9156cd26a495a18706e796f02a81fee41ec14f4 Mon Sep 17 00:00:00 2001
+From: James Hughes <james.hughes@raspberrypi.org>
+Date: Wed, 19 Apr 2017 11:13:40 +0100
+Subject: smsc95xx: Use skb_cow_head to deal with cloned skbs
+
+From: James Hughes <james.hughes@raspberrypi.org>
+
+commit e9156cd26a495a18706e796f02a81fee41ec14f4 upstream.
+
+The driver was failing to check that the SKB wasn't cloned
+before adding checksum data.
+Replace existing handling to extend/copy the header buffer
+with skb_cow_head.
+
+Signed-off-by: James Hughes <james.hughes@raspberrypi.org>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Acked-by: Woojung Huh <Woojung.Huh@microchip.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/usb/smsc95xx.c |   12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -2011,13 +2011,13 @@ static struct sk_buff *smsc95xx_tx_fixup
+       /* We do not advertise SG, so skbs should be already linearized */
+       BUG_ON(skb_shinfo(skb)->nr_frags);
+-      if (skb_headroom(skb) < overhead) {
+-              struct sk_buff *skb2 = skb_copy_expand(skb,
+-                      overhead, 0, flags);
++      /* Make writable and expand header space by overhead if required */
++      if (skb_cow_head(skb, overhead)) {
++              /* Must deallocate here as returning NULL to indicate error
++               * means the skb won't be deallocated in the caller.
++               */
+               dev_kfree_skb_any(skb);
+-              skb = skb2;
+-              if (!skb)
+-                      return NULL;
++              return NULL;
+       }
+       if (csum) {
diff --git a/queue-4.9/usb-dwc2-remove-unnecessary-kfree.patch b/queue-4.9/usb-dwc2-remove-unnecessary-kfree.patch
new file mode 100644 (file)
index 0000000..2018a2c
--- /dev/null
@@ -0,0 +1,31 @@
+From cd4b1e34655d46950c065d9284b596cd8d7b28cd Mon Sep 17 00:00:00 2001
+From: John Youn <johnyoun@synopsys.com>
+Date: Thu, 3 Nov 2016 17:55:45 -0700
+Subject: usb: dwc2: Remove unnecessary kfree
+
+From: John Youn <johnyoun@synopsys.com>
+
+commit cd4b1e34655d46950c065d9284b596cd8d7b28cd upstream.
+
+This shouldn't be freed by the HCD as it is owned by the core and
+allocated with devm_kzalloc.
+
+Signed-off-by: John Youn <johnyoun@synopsys.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc2/hcd.c |    1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/usb/dwc2/hcd.c
++++ b/drivers/usb/dwc2/hcd.c
+@@ -5202,7 +5202,6 @@ error3:
+ error2:
+       usb_put_hcd(hcd);
+ error1:
+-      kfree(hsotg->core_params);
+ #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
+       kfree(hsotg->last_frame_num_array);