layerscape: clean up kernel patches
[openwrt/staging/chunkeey.git] / target / linux / layerscape / patches-4.9 / 202-core-linux-support-layerscape.patch
diff --git a/target/linux/layerscape/patches-4.9/202-core-linux-support-layerscape.patch b/target/linux/layerscape/patches-4.9/202-core-linux-support-layerscape.patch
new file mode 100644 (file)
index 0000000..6eeb6ff
--- /dev/null
@@ -0,0 +1,538 @@
+From c37953457a7ebeb0d97ae8574b3d41274fcd9119 Mon Sep 17 00:00:00 2001
+From: Yangbo Lu <yangbo.lu@nxp.com>
+Date: Wed, 1 Nov 2017 16:22:33 +0800
+Subject: [PATCH] core-linux: support layerscape
+
+This is a integrated patch for layerscape core-linux support.
+
+Signed-off-by: Madalin Bucur <madalin.bucur@freescale.com>
+Signed-off-by: Zhao Qiang <qiang.zhao@nxp.com>
+Signed-off-by: Camelia Groza <camelia.groza@nxp.com>
+Signed-off-by: Madalin Bucur <madalin.bucur@nxp.com>
+Signed-off-by: Zhang Ying-22455 <ying.zhang22455@nxp.com>
+Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
+Signed-off-by: Jarod Wilson <jarod@redhat.com>
+Signed-off-by: Nikhil Badola <nikhil.badola@freescale.com>
+Signed-off-by: stephen hemminger <stephen@networkplumber.org>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+---
+ drivers/base/devres.c           | 66 ++++++++++++++++++++++++++++
+ drivers/base/soc.c              | 66 ++++++++++++++++++++++++++++
+ include/linux/device.h          | 19 ++++++++
+ include/linux/fsl/svr.h         | 97 +++++++++++++++++++++++++++++++++++++++++
+ include/linux/fsl_devices.h     |  3 ++
+ include/linux/netdev_features.h |  2 +
+ include/linux/netdevice.h       |  4 ++
+ include/linux/skbuff.h          |  2 +
+ include/linux/sys_soc.h         |  3 ++
+ include/uapi/linux/if_ether.h   |  1 +
+ net/core/dev.c                  | 13 +++++-
+ net/core/skbuff.c               | 29 +++++++++++-
+ net/sched/sch_generic.c         |  7 +++
+ 13 files changed, 309 insertions(+), 3 deletions(-)
+ create mode 100644 include/linux/fsl/svr.h
+
+diff --git a/drivers/base/devres.c b/drivers/base/devres.c
+index 8fc654f0..71d57702 100644
+--- a/drivers/base/devres.c
++++ b/drivers/base/devres.c
+@@ -10,6 +10,7 @@
+ #include <linux/device.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/percpu.h>
+ #include "base.h"
+@@ -985,3 +986,68 @@ void devm_free_pages(struct device *dev, unsigned long addr)
+                              &devres));
+ }
+ EXPORT_SYMBOL_GPL(devm_free_pages);
++
++static void devm_percpu_release(struct device *dev, void *pdata)
++{
++      void __percpu *p;
++
++      p = *(void __percpu **)pdata;
++      free_percpu(p);
++}
++
++static int devm_percpu_match(struct device *dev, void *data, void *p)
++{
++      struct devres *devr = container_of(data, struct devres, data);
++
++      return *(void **)devr->data == p;
++}
++
++/**
++ * __devm_alloc_percpu - Resource-managed alloc_percpu
++ * @dev: Device to allocate per-cpu memory for
++ * @size: Size of per-cpu memory to allocate
++ * @align: Alignment of per-cpu memory to allocate
++ *
++ * Managed alloc_percpu. Per-cpu memory allocated with this function is
++ * automatically freed on driver detach.
++ *
++ * RETURNS:
++ * Pointer to allocated memory on success, NULL on failure.
++ */
++void __percpu *__devm_alloc_percpu(struct device *dev, size_t size,
++              size_t align)
++{
++      void *p;
++      void __percpu *pcpu;
++
++      pcpu = __alloc_percpu(size, align);
++      if (!pcpu)
++              return NULL;
++
++      p = devres_alloc(devm_percpu_release, sizeof(void *), GFP_KERNEL);
++      if (!p) {
++              free_percpu(pcpu);
++              return NULL;
++      }
++
++      *(void __percpu **)p = pcpu;
++
++      devres_add(dev, p);
++
++      return pcpu;
++}
++EXPORT_SYMBOL_GPL(__devm_alloc_percpu);
++
++/**
++ * devm_free_percpu - Resource-managed free_percpu
++ * @dev: Device this memory belongs to
++ * @pdata: Per-cpu memory to free
++ *
++ * Free memory allocated with devm_alloc_percpu().
++ */
++void devm_free_percpu(struct device *dev, void __percpu *pdata)
++{
++      WARN_ON(devres_destroy(dev, devm_percpu_release, devm_percpu_match,
++                             (void *)pdata));
++}
++EXPORT_SYMBOL_GPL(devm_free_percpu);
+diff --git a/drivers/base/soc.c b/drivers/base/soc.c
+index b63f23e6..0c5cf872 100644
+--- a/drivers/base/soc.c
++++ b/drivers/base/soc.c
+@@ -13,6 +13,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/sys_soc.h>
+ #include <linux/err.h>
++#include <linux/glob.h>
+ static DEFINE_IDA(soc_ida);
+@@ -159,3 +160,68 @@ static int __init soc_bus_register(void)
+       return bus_register(&soc_bus_type);
+ }
+ core_initcall(soc_bus_register);
++
++static int soc_device_match_one(struct device *dev, void *arg)
++{
++      struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
++      const struct soc_device_attribute *match = arg;
++
++      if (match->machine &&
++          !glob_match(match->machine, soc_dev->attr->machine))
++              return 0;
++
++      if (match->family &&
++          !glob_match(match->family, soc_dev->attr->family))
++              return 0;
++
++      if (match->revision &&
++          !glob_match(match->revision, soc_dev->attr->revision))
++              return 0;
++
++      if (match->soc_id &&
++          !glob_match(match->soc_id, soc_dev->attr->soc_id))
++              return 0;
++
++      return 1;
++}
++
++/*
++ * soc_device_match - identify the SoC in the machine
++ * @matches: zero-terminated array of possible matches
++ *
++ * returns the first matching entry of the argument array, or NULL
++ * if none of them match.
++ *
++ * This function is meant as a helper in place of of_match_node()
++ * in cases where either no device tree is available or the information
++ * in a device node is insufficient to identify a particular variant
++ * by its compatible strings or other properties. For new devices,
++ * the DT binding should always provide unique compatible strings
++ * that allow the use of of_match_node() instead.
++ *
++ * The calling function can use the .data entry of the
++ * soc_device_attribute to pass a structure or function pointer for
++ * each entry.
++ */
++const struct soc_device_attribute *soc_device_match(
++      const struct soc_device_attribute *matches)
++{
++      int ret = 0;
++
++      if (!matches)
++              return NULL;
++
++      while (!ret) {
++              if (!(matches->machine || matches->family ||
++                    matches->revision || matches->soc_id))
++                      break;
++              ret = bus_for_each_dev(&soc_bus_type, NULL, (void *)matches,
++                                     soc_device_match_one);
++              if (!ret)
++                      matches++;
++              else
++                      return matches;
++      }
++      return NULL;
++}
++EXPORT_SYMBOL_GPL(soc_device_match);
+diff --git a/include/linux/device.h b/include/linux/device.h
+index 8d732965..6d206930 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -688,6 +688,25 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);
+ int devm_add_action(struct device *dev, void (*action)(void *), void *data);
+ void devm_remove_action(struct device *dev, void (*action)(void *), void *data);
++/**
++ * devm_alloc_percpu - Resource-managed alloc_percpu
++ * @dev: Device to allocate per-cpu memory for
++ * @type: Type to allocate per-cpu memory for
++ *
++ * Managed alloc_percpu. Per-cpu memory allocated with this function is
++ * automatically freed on driver detach.
++ *
++ * RETURNS:
++ * Pointer to allocated memory on success, NULL on failure.
++ */
++#define devm_alloc_percpu(dev, type)      \
++      ((typeof(type) __percpu *)__devm_alloc_percpu((dev), sizeof(type), \
++                                                    __alignof__(type)))
++
++void __percpu *__devm_alloc_percpu(struct device *dev, size_t size,
++                                 size_t align);
++void devm_free_percpu(struct device *dev, void __percpu *pdata);
++
+ static inline int devm_add_action_or_reset(struct device *dev,
+                                          void (*action)(void *), void *data)
+ {
+diff --git a/include/linux/fsl/svr.h b/include/linux/fsl/svr.h
+new file mode 100644
+index 00000000..e95c8f43
+--- /dev/null
++++ b/include/linux/fsl/svr.h
+@@ -0,0 +1,97 @@
++/*
++ * MPC85xx cpu type detection
++ *
++ * Copyright 2011-2012 Freescale Semiconductor, Inc.
++ *
++ * This is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++
++#ifndef FSL_SVR_H
++#define FSL_SVR_H
++
++#define SVR_REV(svr)  ((svr) & 0xFF)          /* SOC design resision */
++#define SVR_MAJ(svr)  (((svr) >>  4) & 0xF)   /* Major revision field*/
++#define SVR_MIN(svr)  (((svr) >>  0) & 0xF)   /* Minor revision field*/
++
++/* Some parts define SVR[0:23] as the SOC version */
++#define SVR_SOC_VER(svr) (((svr) >> 8) & 0xFFF7FF)    /* SOC Version fields */
++
++#define SVR_8533      0x803400
++#define SVR_8535      0x803701
++#define SVR_8536      0x803700
++#define SVR_8540      0x803000
++#define SVR_8541      0x807200
++#define SVR_8543      0x803200
++#define SVR_8544      0x803401
++#define SVR_8545      0x803102
++#define SVR_8547      0x803101
++#define SVR_8548      0x803100
++#define SVR_8555      0x807100
++#define SVR_8560      0x807000
++#define SVR_8567      0x807501
++#define SVR_8568      0x807500
++#define SVR_8569      0x808000
++#define SVR_8572      0x80E000
++#define SVR_P1010     0x80F100
++#define SVR_P1011     0x80E500
++#define SVR_P1012     0x80E501
++#define SVR_P1013     0x80E700
++#define SVR_P1014     0x80F101
++#define SVR_P1017     0x80F700
++#define SVR_P1020     0x80E400
++#define SVR_P1021     0x80E401
++#define SVR_P1022     0x80E600
++#define SVR_P1023     0x80F600
++#define SVR_P1024     0x80E402
++#define SVR_P1025     0x80E403
++#define SVR_P2010     0x80E300
++#define SVR_P2020     0x80E200
++#define SVR_P2040     0x821000
++#define SVR_P2041     0x821001
++#define SVR_P3041     0x821103
++#define SVR_P4040     0x820100
++#define SVR_P4080     0x820000
++#define SVR_P5010     0x822100
++#define SVR_P5020     0x822000
++#define SVR_P5021     0X820500
++#define SVR_P5040     0x820400
++#define SVR_T4240     0x824000
++#define SVR_T4120     0x824001
++#define SVR_T4160     0x824100
++#define SVR_T4080     0x824102
++#define SVR_C291      0x850000
++#define SVR_C292      0x850020
++#define SVR_C293      0x850030
++#define SVR_B4860     0X868000
++#define SVR_G4860     0x868001
++#define SVR_G4060     0x868003
++#define SVR_B4440     0x868100
++#define SVR_G4440     0x868101
++#define SVR_B4420     0x868102
++#define SVR_B4220     0x868103
++#define SVR_T1040     0x852000
++#define SVR_T1041     0x852001
++#define SVR_T1042     0x852002
++#define SVR_T1020     0x852100
++#define SVR_T1021     0x852101
++#define SVR_T1022     0x852102
++#define SVR_T1023     0x854100
++#define SVR_T1024     0x854000
++#define SVR_T2080     0x853000
++#define SVR_T2081     0x853100
++
++#define SVR_8610      0x80A000
++#define SVR_8641      0x809000
++#define SVR_8641D     0x809001
++
++#define SVR_9130      0x860001
++#define SVR_9131      0x860000
++#define SVR_9132      0x861000
++#define SVR_9232      0x861400
++
++#define SVR_Unknown   0xFFFFFF
++
++#endif
+diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
+index f2912914..22308465 100644
+--- a/include/linux/fsl_devices.h
++++ b/include/linux/fsl_devices.h
+@@ -99,7 +99,10 @@ struct fsl_usb2_platform_data {
+       unsigned        suspended:1;
+       unsigned        already_suspended:1;
+       unsigned        has_fsl_erratum_a007792:1;
++      unsigned        has_fsl_erratum_14:1;
+       unsigned        has_fsl_erratum_a005275:1;
++      unsigned        has_fsl_erratum_a006918:1;
++      unsigned        has_fsl_erratum_a005697:1;
+       unsigned        check_phy_clk_valid:1;
+       /* register save area for suspend/resume */
+diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
+index 9c6c8ef2..90b4107e 100644
+--- a/include/linux/netdev_features.h
++++ b/include/linux/netdev_features.h
+@@ -74,6 +74,7 @@ enum {
+       NETIF_F_BUSY_POLL_BIT,          /* Busy poll */
+       NETIF_F_HW_TC_BIT,              /* Offload TC infrastructure */
++      NETIF_F_HW_ACCEL_MQ_BIT,        /* Hardware-accelerated multiqueue */
+       /*
+        * Add your fresh new feature above and remember to update
+@@ -136,6 +137,7 @@ enum {
+ #define NETIF_F_HW_L2FW_DOFFLOAD      __NETIF_F(HW_L2FW_DOFFLOAD)
+ #define NETIF_F_BUSY_POLL     __NETIF_F(BUSY_POLL)
+ #define NETIF_F_HW_TC         __NETIF_F(HW_TC)
++#define NETIF_F_HW_ACCEL_MQ   __NETIF_F(HW_ACCEL_MQ)
+ #define for_each_netdev_feature(mask_addr, bit)       \
+       for_each_set_bit(bit, (unsigned long *)mask_addr, NETDEV_FEATURE_COUNT)
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index c3a1537c..9740875b 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -1509,6 +1509,8 @@ enum netdev_priv_flags {
+  *    @if_port:       Selectable AUI, TP, ...
+  *    @dma:           DMA channel
+  *    @mtu:           Interface MTU value
++ *    @min_mtu:       Interface Minimum MTU value
++ *    @max_mtu:       Interface Maximum MTU value
+  *    @type:          Interface hardware type
+  *    @hard_header_len: Maximum hardware header length.
+  *    @min_header_len:  Minimum hardware header length
+@@ -1735,6 +1737,8 @@ struct net_device {
+       unsigned char           dma;
+       unsigned int            mtu;
++      unsigned int            min_mtu;
++      unsigned int            max_mtu;
+       unsigned short          type;
+       unsigned short          hard_header_len;
+       unsigned short          min_header_len;
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index 9a0c945e..06f33c98 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -903,6 +903,7 @@ void kfree_skb(struct sk_buff *skb);
+ void kfree_skb_list(struct sk_buff *segs);
+ void skb_tx_error(struct sk_buff *skb);
+ void consume_skb(struct sk_buff *skb);
++void skb_recycle(struct sk_buff *skb);
+ void  __kfree_skb(struct sk_buff *skb);
+ extern struct kmem_cache *skbuff_head_cache;
+@@ -3057,6 +3058,7 @@ static inline void skb_free_datagram_locked(struct sock *sk,
+ }
+ int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags);
+ int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len);
++void copy_skb_header(struct sk_buff *new, const struct sk_buff *old);
+ int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len);
+ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to,
+                             int len, __wsum csum);
+diff --git a/include/linux/sys_soc.h b/include/linux/sys_soc.h
+index 2739ccb6..9f5eb06f 100644
+--- a/include/linux/sys_soc.h
++++ b/include/linux/sys_soc.h
+@@ -13,6 +13,7 @@ struct soc_device_attribute {
+       const char *family;
+       const char *revision;
+       const char *soc_id;
++      const void *data;
+ };
+ /**
+@@ -34,4 +35,6 @@ void soc_device_unregister(struct soc_device *soc_dev);
+  */
+ struct device *soc_device_to_device(struct soc_device *soc);
++const struct soc_device_attribute *soc_device_match(
++      const struct soc_device_attribute *matches);
+ #endif /* __SOC_BUS_H */
+diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h
+index 51f38442..5c01afbf 100644
+--- a/include/uapi/linux/if_ether.h
++++ b/include/uapi/linux/if_ether.h
+@@ -35,6 +35,7 @@
+ #define ETH_DATA_LEN  1500            /* Max. octets in payload        */
+ #define ETH_FRAME_LEN 1514            /* Max. octets in frame sans FCS */
+ #define ETH_FCS_LEN   4               /* Octets in the FCS             */
++#define ETH_MIN_MTU   68              /* Min IPv4 MTU per RFC791      */
+ /*
+  *    These are the defined Ethernet Protocol ID's.
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 512086f2..6e3bb7bc 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -6603,9 +6603,18 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
+       if (new_mtu == dev->mtu)
+               return 0;
+-      /*      MTU must be positive.    */
+-      if (new_mtu < 0)
++      /* MTU must be positive, and in range */
++      if (new_mtu < 0 || new_mtu < dev->min_mtu) {
++              net_err_ratelimited("%s: Invalid MTU %d requested, hw min %d\n",
++                                  dev->name, new_mtu, dev->min_mtu);
+               return -EINVAL;
++      }
++
++      if (dev->max_mtu > 0 && new_mtu > dev->max_mtu) {
++              net_err_ratelimited("%s: Invalid MTU %d requested, hw max %d\n",
++                                  dev->name, new_mtu, dev->min_mtu);
++              return -EINVAL;
++      }
+       if (!netif_device_present(dev))
+               return -ENODEV;
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 7e7b7ce0..0f9c014a 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -842,6 +842,32 @@ void napi_consume_skb(struct sk_buff *skb, int budget)
+ }
+ EXPORT_SYMBOL(napi_consume_skb);
++/**
++ *    skb_recycle - clean up an skb for reuse
++ *    @skb: buffer
++ *
++ *    Recycles the skb to be reused as a receive buffer. This
++ *    function does any necessary reference count dropping, and
++ *    cleans up the skbuff as if it just came from __alloc_skb().
++ */
++void skb_recycle(struct sk_buff *skb)
++{
++      struct skb_shared_info *shinfo;
++      u8 head_frag = skb->head_frag;
++
++      skb_release_head_state(skb);
++
++      shinfo = skb_shinfo(skb);
++      memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));
++      atomic_set(&shinfo->dataref, 1);
++
++      memset(skb, 0, offsetof(struct sk_buff, tail));
++      skb->data = skb->head + NET_SKB_PAD;
++      skb->head_frag = head_frag;
++      skb_reset_tail_pointer(skb);
++}
++EXPORT_SYMBOL(skb_recycle);
++
+ /* Make sure a field is enclosed inside headers_start/headers_end section */
+ #define CHECK_SKB_FIELD(field) \
+       BUILD_BUG_ON(offsetof(struct sk_buff, field) <          \
+@@ -1073,7 +1099,7 @@ static void skb_headers_offset_update(struct sk_buff *skb, int off)
+       skb->inner_mac_header += off;
+ }
+-static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
++void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
+ {
+       __copy_skb_header(new, old);
+@@ -1081,6 +1107,7 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
+       skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
+       skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type;
+ }
++EXPORT_SYMBOL(copy_skb_header);
+ static inline int skb_alloc_rx_flag(const struct sk_buff *skb)
+ {
+diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
+index 8018dd3a..ea760b83 100644
+--- a/net/sched/sch_generic.c
++++ b/net/sched/sch_generic.c
+@@ -309,6 +309,13 @@ static void dev_watchdog(unsigned long arg)
+                                       txq->trans_timeout++;
+                                       break;
+                               }
++
++                              /* Devices with HW_ACCEL_MQ have multiple txqs
++                               * but update only the first one's transmission
++                               * timestamp so avoid checking the rest.
++                               */
++                              if (dev->features & NETIF_F_HW_ACCEL_MQ)
++                                      break;
+                       }
+                       if (some_queue_timedout) {
+-- 
+2.14.1
+