OpenWrt – Rev 4

Subversion Repositories:
Rev:
From 67a2eceebe9dcd92a1a5f3e912340c8975c84434 Mon Sep 17 00:00:00 2001
From: Yangbo Lu <yangbo.lu@nxp.com>
Date: Wed, 17 Jan 2018 14:50:41 +0800
Subject: [PATCH 02/30] core-linux: support layerscape

This is an 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              | 70 +++++++++++++++++++++++++++++
 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, 313 insertions(+), 3 deletions(-)
 create mode 100644 include/linux/fsl/svr.h

--- 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,
                               &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);
--- 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,72 @@ 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 &&
+           (!soc_dev->attr->machine ||
+            !glob_match(match->machine, soc_dev->attr->machine)))
+               return 0;
+
+       if (match->family &&
+           (!soc_dev->attr->family ||
+            !glob_match(match->family, soc_dev->attr->family)))
+               return 0;
+
+       if (match->revision &&
+           (!soc_dev->attr->revision ||
+            !glob_match(match->revision, soc_dev->attr->revision)))
+               return 0;
+
+       if (match->soc_id &&
+           (!soc_dev->attr->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);
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -688,6 +688,25 @@ void __iomem *devm_ioremap_resource(stru
 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)
 {
--- /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
--- 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 */
--- 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)
--- 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;
--- 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;
 
@@ -3059,6 +3060,7 @@ static inline void skb_free_datagram_loc
 }
 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);
--- 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_de
  */
 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 */
--- a/include/uapi/linux/if_ether.h
+++ b/include/uapi/linux/if_ether.h
@@ -36,6 +36,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.
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6630,9 +6630,18 @@ int dev_set_mtu(struct net_device *dev,
        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;
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -842,6 +842,32 @@ void napi_consume_skb(struct sk_buff *sk
 }
 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) <          \
@@ -1075,7 +1101,7 @@ static void skb_headers_offset_update(st
        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);
 
@@ -1083,6 +1109,7 @@ static void copy_skb_header(struct sk_bu
        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)
 {
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -309,6 +309,13 @@ static void dev_watchdog(unsigned long a
                                        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) {