kernel: bump 4.14 to 4.14.151
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.14 / 202-core-linux-support-layerscape.patch
index 14e8d73157b90b131675910c1e5fe5988316fe6c..512d323ac6e9c488bca27845d137d9f78679e68e 100644 (file)
-From 74243154052af635ee9ce9d07aab273ce219c855 Mon Sep 17 00:00:00 2001
-From: Biwen Li <biwen.li@nxp.com>
-Date: Thu, 13 Dec 2018 13:23:52 +0800
+From d2ef9f2f6d16d34d7eee74cb8efd269341fec5a1 Mon Sep 17 00:00:00 2001
+From: Yangbo Lu <yangbo.lu@nxp.com>
+Date: Mon, 6 May 2019 16:54:17 +0800
 Subject: [PATCH] core-linux: support layerscape
 
-This is an integrated patch of core-linux for layerscape.
+This is an integrated patch of core-linux for layerscape
 
+Signed-off-by: Aaron Lu <aaron.lu@intel.com>
 Signed-off-by: Abhijit Ayarekar <abhijit.ayarekar@caviumnetworks.com>
 Signed-off-by: Amrita Kumari <amrita.kumari@nxp.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
 Signed-off-by: Ashish Kumar <Ashish.Kumar@nxp.com>
+Signed-off-by: Biwen Li <biwen.li@nxp.com>
 Signed-off-by: Camelia Groza <camelia.groza@nxp.com>
 Signed-off-by: Christoph Hellwig <hch@lst.de>
 Signed-off-by: David Ahern <dsahern@gmail.com>
 Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 Signed-off-by: Guanhua Gao <guanhua.gao@nxp.com>
+Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
 Signed-off-by: Jiri Pirko <jiri@mellanox.com>
 Signed-off-by: Joel Fernandes <joelaf@google.com>
+Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
 Signed-off-by: Li Yang <leoyang.li@nxp.com>
-Signed-off-by: Madalin Bucur <madalin.bucur@freescale.com>
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
 Signed-off-by: Madalin Bucur <madalin.bucur@nxp.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
 Signed-off-by: Nikhil Badola <nikhil.badola@freescale.com>
 Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com>
+Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com>
+Signed-off-by: pascal paillet <p.paillet@st.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
 Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com>
 Signed-off-by: Robin Murphy <robin.murphy@arm.com>
 Signed-off-by: Suresh Gupta <suresh.gupta@freescale.com>
+Signed-off-by: Vivek Gautam <vivek.gautam@codeaurora.org>
 Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
-Signed-off-by: yinbo.zhu <yinbo.zhu@nxp.com>
-Signed-off-by: Biwen Li <biwen.li@nxp.com>
 ---
- drivers/base/dma-mapping.c                |  7 ++
- drivers/net/bonding/bond_main.c           |  5 +-
- drivers/net/bonding/bond_options.c        |  2 +-
- drivers/net/team/team.c                   |  3 +-
- drivers/net/vrf.c                         |  3 +-
- drivers/of/device.c                       | 13 +++-
- drivers/soc/fsl/guts.c                    |  3 +
- include/linux/fsl_devices.h               |  2 +
- include/linux/netdevice.h                 | 13 +++-
- include/linux/skbuff.h                    |  2 +
- include/net/bonding.h                     |  3 +-
- net/batman-adv/soft-interface.c           |  3 +-
- net/bridge/br_device.c                    |  3 +-
- net/core/dev.c                            | 81 ++++++++++++++---------
- net/core/rtnetlink.c                      | 10 +--
- net/core/skbuff.c                         | 29 +++++++-
- samples/bpf/Makefile                      | 12 +++-
- samples/bpf/map_perf_test_kern.c          |  2 +-
- samples/bpf/map_perf_test_user.c          |  2 +-
- tools/testing/selftests/bpf/bpf_helpers.h | 56 ++++++++++++++--
- 20 files changed, 193 insertions(+), 61 deletions(-)
+ drivers/base/core.c                       | 122 ++++++++++++++++++++++++++----
+ drivers/base/dma-mapping.c                |   7 ++
+ drivers/gpu/ipu-v3/ipu-pre.c              |   3 +-
+ drivers/gpu/ipu-v3/ipu-prg.c              |   3 +-
+ drivers/iommu/dma-iommu.c                 |   3 +
+ drivers/mux/Kconfig                       |  12 +--
+ drivers/mux/mmio.c                        |   6 +-
+ drivers/of/device.c                       |  14 +++-
+ drivers/soc/imx/gpc.c                     |   2 +-
+ include/linux/device.h                    |  20 +++--
+ include/linux/fsl_devices.h               |   2 +
+ include/linux/netdevice.h                 |  10 ++-
+ include/linux/skbuff.h                    |   2 +
+ lib/dma-noop.c                            |  19 +++++
+ mm/page_alloc.c                           |  10 ++-
+ net/core/dev.c                            |  81 ++++++++++++--------
+ net/core/skbuff.c                         |  29 ++++++-
+ samples/bpf/Makefile                      |  12 ++-
+ samples/bpf/map_perf_test_kern.c          |   2 +-
+ samples/bpf/map_perf_test_user.c          |   2 +-
+ tools/testing/selftests/bpf/bpf_helpers.h |  56 ++++++++++++--
+ 21 files changed, 337 insertions(+), 80 deletions(-)
 
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -162,10 +162,10 @@ static int device_reorder_to_tail(struct
+  * of the link.  If DL_FLAG_PM_RUNTIME is not set, DL_FLAG_RPM_ACTIVE will be
+  * ignored.
+  *
+- * If the DL_FLAG_AUTOREMOVE is set, the link will be removed automatically
+- * when the consumer device driver unbinds from it.  The combination of both
+- * DL_FLAG_AUTOREMOVE and DL_FLAG_STATELESS set is invalid and will cause NULL
+- * to be returned.
++ * If the DL_FLAG_AUTOREMOVE_CONSUMER is set, the link will be removed
++ * automatically when the consumer device driver unbinds from it.
++ * The combination of both DL_FLAG_AUTOREMOVE_CONSUMER and DL_FLAG_STATELESS
++ * set is invalid and will cause NULL to be returned.
+  *
+  * A side effect of the link creation is re-ordering of dpm_list and the
+  * devices_kset list by moving the consumer device and all devices depending
+@@ -182,7 +182,8 @@ struct device_link *device_link_add(stru
+       struct device_link *link;
+       if (!consumer || !supplier ||
+-          ((flags & DL_FLAG_STATELESS) && (flags & DL_FLAG_AUTOREMOVE)))
++          ((flags & DL_FLAG_STATELESS) &&
++           (flags & DL_FLAG_AUTOREMOVE_CONSUMER)))
+               return NULL;
+       device_links_write_lock();
+@@ -200,8 +201,10 @@ struct device_link *device_link_add(stru
+       }
+       list_for_each_entry(link, &supplier->links.consumers, s_node)
+-              if (link->consumer == consumer)
++              if (link->consumer == consumer) {
++                      kref_get(&link->kref);
+                       goto out;
++              }
+       link = kzalloc(sizeof(*link), GFP_KERNEL);
+       if (!link)
+@@ -233,6 +236,7 @@ struct device_link *device_link_add(stru
+       link->consumer = consumer;
+       INIT_LIST_HEAD(&link->c_node);
+       link->flags = flags;
++      kref_init(&link->kref);
+       /* Determine the initial link state. */
+       if (flags & DL_FLAG_STATELESS) {
+@@ -303,8 +307,10 @@ static void __device_link_free_srcu(stru
+       device_link_free(container_of(rhead, struct device_link, rcu_head));
+ }
+-static void __device_link_del(struct device_link *link)
++static void __device_link_del(struct kref *kref)
+ {
++      struct device_link *link = container_of(kref, struct device_link, kref);
++
+       dev_info(link->consumer, "Dropping the link to %s\n",
+                dev_name(link->supplier));
+@@ -316,8 +322,10 @@ static void __device_link_del(struct dev
+       call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu);
+ }
+ #else /* !CONFIG_SRCU */
+-static void __device_link_del(struct device_link *link)
++static void __device_link_del(struct kref *kref)
+ {
++      struct device_link *link = container_of(kref, struct device_link, kref);
++
+       dev_info(link->consumer, "Dropping the link to %s\n",
+                dev_name(link->supplier));
+@@ -335,18 +343,50 @@ static void __device_link_del(struct dev
+  * @link: Device link to delete.
+  *
+  * The caller must ensure proper synchronization of this function with runtime
+- * PM.
++ * PM.  If the link was added multiple times, it needs to be deleted as often.
++ * Care is required for hotplugged devices:  Their links are purged on removal
++ * and calling device_link_del() is then no longer allowed.
+  */
+ void device_link_del(struct device_link *link)
+ {
+       device_links_write_lock();
+       device_pm_lock();
+-      __device_link_del(link);
++      kref_put(&link->kref, __device_link_del);
+       device_pm_unlock();
+       device_links_write_unlock();
+ }
+ EXPORT_SYMBOL_GPL(device_link_del);
++/**
++ * device_link_remove - remove a link between two devices.
++ * @consumer: Consumer end of the link.
++ * @supplier: Supplier end of the link.
++ *
++ * The caller must ensure proper synchronization of this function with runtime
++ * PM.
++ */
++void device_link_remove(void *consumer, struct device *supplier)
++{
++      struct device_link *link;
++
++      if (WARN_ON(consumer == supplier))
++              return;
++
++      device_links_write_lock();
++      device_pm_lock();
++
++      list_for_each_entry(link, &supplier->links.consumers, s_node) {
++              if (link->consumer == consumer) {
++                      kref_put(&link->kref, __device_link_del);
++                      break;
++              }
++      }
++
++      device_pm_unlock();
++      device_links_write_unlock();
++}
++EXPORT_SYMBOL_GPL(device_link_remove);
++
+ static void device_links_missing_supplier(struct device *dev)
+ {
+       struct device_link *link;
+@@ -454,8 +494,8 @@ static void __device_links_no_driver(str
+               if (link->flags & DL_FLAG_STATELESS)
+                       continue;
+-              if (link->flags & DL_FLAG_AUTOREMOVE)
+-                      __device_link_del(link);
++              if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER)
++                      kref_put(&link->kref, __device_link_del);
+               else if (link->status != DL_STATE_SUPPLIER_UNBIND)
+                       WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
+       }
+@@ -490,8 +530,18 @@ void device_links_driver_cleanup(struct
+               if (link->flags & DL_FLAG_STATELESS)
+                       continue;
+-              WARN_ON(link->flags & DL_FLAG_AUTOREMOVE);
++              WARN_ON(link->flags & DL_FLAG_AUTOREMOVE_CONSUMER);
+               WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND);
++
++              /*
++               * autoremove the links between this @dev and its consumer
++               * devices that are not active, i.e. where the link state
++               * has moved to DL_STATE_SUPPLIER_UNBIND.
++               */
++              if (link->status == DL_STATE_SUPPLIER_UNBIND &&
++                  link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
++                      kref_put(&link->kref, __device_link_del);
++
+               WRITE_ONCE(link->status, DL_STATE_DORMANT);
+       }
+@@ -608,13 +658,13 @@ static void device_links_purge(struct de
+       list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) {
+               WARN_ON(link->status == DL_STATE_ACTIVE);
+-              __device_link_del(link);
++              __device_link_del(&link->kref);
+       }
+       list_for_each_entry_safe_reverse(link, ln, &dev->links.consumers, s_node) {
+               WARN_ON(link->status != DL_STATE_DORMANT &&
+                       link->status != DL_STATE_NONE);
+-              __device_link_del(link);
++              __device_link_del(&link->kref);
+       }
+       device_links_write_unlock();
+@@ -1036,6 +1086,34 @@ static ssize_t online_store(struct devic
+ }
+ static DEVICE_ATTR_RW(online);
++static ssize_t suppliers_show(struct device *dev, struct device_attribute *attr,
++                            char *buf)
++{
++      struct device_link *link;
++      size_t count = 0;
++
++      list_for_each_entry(link, &dev->links.suppliers, c_node)
++              count += scnprintf(buf + count, PAGE_SIZE - count, "%s\n",
++                                 dev_name(link->supplier));
++
++      return count;
++}
++static DEVICE_ATTR_RO(suppliers);
++
++static ssize_t consumers_show(struct device *dev, struct device_attribute *attr,
++                            char *buf)
++{
++      struct device_link *link;
++      size_t count = 0;
++
++      list_for_each_entry(link, &dev->links.consumers, s_node)
++              count += scnprintf(buf + count, PAGE_SIZE - count, "%s\n",
++                                 dev_name(link->consumer));
++
++      return count;
++}
++static DEVICE_ATTR_RO(consumers);
++
+ int device_add_groups(struct device *dev, const struct attribute_group **groups)
+ {
+       return sysfs_create_groups(&dev->kobj, groups);
+@@ -1207,8 +1285,20 @@ static int device_add_attrs(struct devic
+                       goto err_remove_dev_groups;
+       }
++      error = device_create_file(dev, &dev_attr_suppliers);
++      if (error)
++              goto err_remove_online;
++
++      error = device_create_file(dev, &dev_attr_consumers);
++      if (error)
++              goto err_remove_suppliers;
++
+       return 0;
++ err_remove_suppliers:
++      device_remove_file(dev, &dev_attr_suppliers);
++ err_remove_online:
++      device_remove_file(dev, &dev_attr_online);
+  err_remove_dev_groups:
+       device_remove_groups(dev, dev->groups);
+  err_remove_type_groups:
+@@ -1226,6 +1316,8 @@ static void device_remove_attrs(struct d
+       struct class *class = dev->class;
+       const struct device_type *type = dev->type;
++      device_remove_file(dev, &dev_attr_consumers);
++      device_remove_file(dev, &dev_attr_suppliers);
+       device_remove_file(dev, &dev_attr_online);
+       device_remove_groups(dev, dev->groups);
 --- a/drivers/base/dma-mapping.c
 +++ b/drivers/base/dma-mapping.c
 @@ -335,6 +335,7 @@ void dma_common_free_remap(void *cpu_add
@@ -72,62 +319,87 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        if (dma_dev->of_node) {
                ret = of_dma_configure(dev, dma_dev->of_node);
        } else if (has_acpi_companion(dma_dev)) {
---- a/drivers/net/bonding/bond_main.c
-+++ b/drivers/net/bonding/bond_main.c
-@@ -1337,7 +1337,8 @@ void bond_lower_state_changed(struct sla
- }
- /* enslave device <slave> to bond device <master> */
--int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
-+int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
-+               struct netlink_ext_ack *extack)
- {
-       struct bonding *bond = netdev_priv(bond_dev);
-       const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
-@@ -3506,7 +3507,7 @@ static int bond_do_ioctl(struct net_devi
-       switch (cmd) {
-       case BOND_ENSLAVE_OLD:
-       case SIOCBONDENSLAVE:
--              res = bond_enslave(bond_dev, slave_dev);
-+              res = bond_enslave(bond_dev, slave_dev, NULL);
-               break;
-       case BOND_RELEASE_OLD:
-       case SIOCBONDRELEASE:
---- a/drivers/net/bonding/bond_options.c
-+++ b/drivers/net/bonding/bond_options.c
-@@ -1389,7 +1389,7 @@ static int bond_option_slaves_set(struct
-       switch (command[0]) {
-       case '+':
-               netdev_dbg(bond->dev, "Adding slave %s\n", dev->name);
--              ret = bond_enslave(bond->dev, dev);
-+              ret = bond_enslave(bond->dev, dev, NULL);
-               break;
-       case '-':
---- a/drivers/net/team/team.c
-+++ b/drivers/net/team/team.c
-@@ -1932,7 +1932,8 @@ static int team_netpoll_setup(struct net
- }
- #endif
--static int team_add_slave(struct net_device *dev, struct net_device *port_dev)
-+static int team_add_slave(struct net_device *dev, struct net_device *port_dev,
-+                        struct netlink_ext_ack *extack)
- {
-       struct team *team = netdev_priv(dev);
-       int err;
---- a/drivers/net/vrf.c
-+++ b/drivers/net/vrf.c
-@@ -791,7 +791,8 @@ err:
-       return ret;
- }
--static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
-+static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev,
-+                       struct netlink_ext_ack *extack)
- {
-       if (netif_is_l3_master(port_dev) || netif_is_l3_slave(port_dev))
-               return -EINVAL;
+--- a/drivers/gpu/ipu-v3/ipu-pre.c
++++ b/drivers/gpu/ipu-v3/ipu-pre.c
+@@ -124,7 +124,8 @@ ipu_pre_lookup_by_phandle(struct device
+       list_for_each_entry(pre, &ipu_pre_list, list) {
+               if (pre_node == pre->dev->of_node) {
+                       mutex_unlock(&ipu_pre_list_mutex);
+-                      device_link_add(dev, pre->dev, DL_FLAG_AUTOREMOVE);
++                      device_link_add(dev, pre->dev,
++                                      DL_FLAG_AUTOREMOVE_CONSUMER);
+                       of_node_put(pre_node);
+                       return pre;
+               }
+--- a/drivers/gpu/ipu-v3/ipu-prg.c
++++ b/drivers/gpu/ipu-v3/ipu-prg.c
+@@ -99,7 +99,8 @@ ipu_prg_lookup_by_phandle(struct device
+       list_for_each_entry(prg, &ipu_prg_list, list) {
+               if (prg_node == prg->dev->of_node) {
+                       mutex_unlock(&ipu_prg_list_mutex);
+-                      device_link_add(dev, prg->dev, DL_FLAG_AUTOREMOVE);
++                      device_link_add(dev, prg->dev,
++                                      DL_FLAG_AUTOREMOVE_CONSUMER);
+                       prg->id = ipu_id;
+                       of_node_put(prg_node);
+                       return prg;
+--- a/drivers/iommu/dma-iommu.c
++++ b/drivers/iommu/dma-iommu.c
+@@ -381,6 +381,9 @@ static dma_addr_t iommu_dma_alloc_iova(s
+       if (iova_len < (1 << (IOVA_RANGE_CACHE_MAX_SIZE - 1)))
+               iova_len = roundup_pow_of_two(iova_len);
++      if (dev->bus_dma_mask)
++              dma_limit &= dev->bus_dma_mask;
++
+       if (domain->geometry.force_aperture)
+               dma_limit = min(dma_limit, domain->geometry.aperture_end);
+--- a/drivers/mux/Kconfig
++++ b/drivers/mux/Kconfig
+@@ -35,14 +35,14 @@ config MUX_GPIO
+         be called mux-gpio.
+ config MUX_MMIO
+-      tristate "MMIO register bitfield-controlled Multiplexer"
+-      depends on (OF && MFD_SYSCON) || COMPILE_TEST
++      tristate "MMIO/Regmap register bitfield-controlled Multiplexer"
++      depends on OF || COMPILE_TEST
+       help
+-        MMIO register bitfield-controlled Multiplexer controller.
++        MMIO/Regmap register bitfield-controlled Multiplexer controller.
+-        The driver builds multiplexer controllers for bitfields in a syscon
+-        register. For N bit wide bitfields, there will be 2^N possible
+-        multiplexer states.
++        The driver builds multiplexer controllers for bitfields in either
++        a syscon register or a driver regmap register. For N bit wide
++        bitfields, there will be 2^N possible multiplexer states.
+         To compile the driver as a module, choose M here: the module will
+         be called mux-mmio.
+--- a/drivers/mux/mmio.c
++++ b/drivers/mux/mmio.c
+@@ -31,6 +31,7 @@ static const struct mux_control_ops mux_
+ static const struct of_device_id mux_mmio_dt_ids[] = {
+       { .compatible = "mmio-mux", },
++      { .compatible = "reg-mux", },
+       { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, mux_mmio_dt_ids);
+@@ -46,7 +47,10 @@ static int mux_mmio_probe(struct platfor
+       int ret;
+       int i;
+-      regmap = syscon_node_to_regmap(np->parent);
++      if (of_device_is_compatible(np, "mmio-mux"))
++              regmap = syscon_node_to_regmap(np->parent);
++      else
++              regmap = dev_get_regmap(dev->parent, NULL) ?: ERR_PTR(-ENODEV);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               dev_err(dev, "failed to get regmap: %d\n", ret);
 --- a/drivers/of/device.c
 +++ b/drivers/of/device.c
 @@ -15,6 +15,9 @@
@@ -150,7 +422,11 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                    dev->bus != &platform_bus_type)
                        return ret == -ENODEV ? 0 : ret;
  
-@@ -155,7 +161,12 @@ int of_dma_configure(struct device *dev,
+@@ -152,10 +158,16 @@ int of_dma_configure(struct device *dev,
+        * set by the driver.
+        */
+       mask = DMA_BIT_MASK(ilog2(dma_addr + size - 1) + 1);
++      dev->bus_dma_mask = mask;
        dev->coherent_dma_mask &= mask;
        *dev->dma_mask &= mask;
  
@@ -164,18 +440,91 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        dev_dbg(dev, "device is%sdma coherent\n",
                coherent ? " " : " not ");
  
---- a/drivers/soc/fsl/guts.c
-+++ b/drivers/soc/fsl/guts.c
-@@ -213,6 +213,9 @@ static const struct of_device_id fsl_gut
-       { .compatible = "fsl,ls1021a-dcfg", },
-       { .compatible = "fsl,ls1043a-dcfg", },
-       { .compatible = "fsl,ls2080a-dcfg", },
-+      { .compatible = "fsl,ls1088a-dcfg", },
-+      { .compatible = "fsl,ls1012a-dcfg", },
-+      { .compatible = "fsl,ls1046a-dcfg", },
-       {}
- };
- MODULE_DEVICE_TABLE(of, fsl_guts_of_match);
+--- a/drivers/soc/imx/gpc.c
++++ b/drivers/soc/imx/gpc.c
+@@ -209,7 +209,7 @@ static int imx_pgc_power_domain_probe(st
+                       goto genpd_err;
+       }
+-      device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE);
++      device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE_CONSUMER);
+       return 0;
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -55,6 +55,8 @@ struct bus_attribute {
+       struct bus_attribute bus_attr_##_name = __ATTR_RW(_name)
+ #define BUS_ATTR_RO(_name) \
+       struct bus_attribute bus_attr_##_name = __ATTR_RO(_name)
++#define BUS_ATTR_WO(_name) \
++      struct bus_attribute bus_attr_##_name = __ATTR_WO(_name)
+ extern int __must_check bus_create_file(struct bus_type *,
+                                       struct bus_attribute *);
+@@ -750,14 +752,16 @@ enum device_link_state {
+  * Device link flags.
+  *
+  * STATELESS: The core won't track the presence of supplier/consumer drivers.
+- * AUTOREMOVE: Remove this link automatically on consumer driver unbind.
++ * AUTOREMOVE_CONSUMER: Remove the link automatically on consumer driver unbind.
+  * PM_RUNTIME: If set, the runtime PM framework will use this link.
+  * RPM_ACTIVE: Run pm_runtime_get_sync() on the supplier during link creation.
++ * AUTOREMOVE_SUPPLIER: Remove the link automatically on supplier driver unbind.
+  */
+-#define DL_FLAG_STATELESS     BIT(0)
+-#define DL_FLAG_AUTOREMOVE    BIT(1)
+-#define DL_FLAG_PM_RUNTIME    BIT(2)
+-#define DL_FLAG_RPM_ACTIVE    BIT(3)
++#define DL_FLAG_STATELESS             BIT(0)
++#define DL_FLAG_AUTOREMOVE_CONSUMER   BIT(1)
++#define DL_FLAG_PM_RUNTIME            BIT(2)
++#define DL_FLAG_RPM_ACTIVE            BIT(3)
++#define DL_FLAG_AUTOREMOVE_SUPPLIER   BIT(4)
+ /**
+  * struct device_link - Device link representation.
+@@ -768,6 +772,7 @@ enum device_link_state {
+  * @status: The state of the link (with respect to the presence of drivers).
+  * @flags: Link flags.
+  * @rpm_active: Whether or not the consumer device is runtime-PM-active.
++ * @kref: Count repeated addition of the same link.
+  * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks.
+  */
+ struct device_link {
+@@ -778,6 +783,7 @@ struct device_link {
+       enum device_link_state status;
+       u32 flags;
+       bool rpm_active;
++      struct kref kref;
+ #ifdef CONFIG_SRCU
+       struct rcu_head rcu_head;
+ #endif
+@@ -850,6 +856,8 @@ struct dev_links_info {
+  * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all
+  *            hardware supports 64-bit addresses for consistent allocations
+  *            such descriptors.
++ * @bus_dma_mask: Mask of an upstream bridge or bus which imposes a smaller DMA
++ *            limit than the device itself supports.
+  * @dma_pfn_offset: offset of DMA memory range relatively of RAM
+  * @dma_parms:        A low level driver may set these to teach IOMMU code about
+  *            segment limitations.
+@@ -929,6 +937,7 @@ struct device {
+                                            not all hardware supports
+                                            64 bit addresses for consistent
+                                            allocations such descriptors. */
++      u64             bus_dma_mask;   /* upstream dma_mask constraint */
+       unsigned long   dma_pfn_offset;
+       struct device_dma_parameters *dma_parms;
+@@ -1267,6 +1276,7 @@ extern const char *dev_driver_string(con
+ struct device_link *device_link_add(struct device *consumer,
+                                   struct device *supplier, u32 flags);
+ void device_link_del(struct device_link *link);
++void device_link_remove(void *consumer, struct device *supplier);
+ #ifdef CONFIG_PRINTK
 --- a/include/linux/fsl_devices.h
 +++ b/include/linux/fsl_devices.h
 @@ -99,7 +99,9 @@ struct fsl_usb2_platform_data {
@@ -190,17 +539,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
 --- a/include/linux/netdevice.h
 +++ b/include/linux/netdevice.h
-@@ -1260,7 +1260,8 @@ struct net_device_ops {
-                                                    u32 flow_id);
- #endif
-       int                     (*ndo_add_slave)(struct net_device *dev,
--                                               struct net_device *slave_dev);
-+                                               struct net_device *slave_dev,
-+                                               struct netlink_ext_ack *extack);
-       int                     (*ndo_del_slave)(struct net_device *dev,
-                                                struct net_device *slave_dev);
-       netdev_features_t       (*ndo_fix_features)(struct net_device *dev,
-@@ -2341,7 +2342,8 @@ int register_netdevice_notifier(struct n
+@@ -2344,7 +2344,8 @@ int register_netdevice_notifier(struct n
  int unregister_netdevice_notifier(struct notifier_block *nb);
  
  struct netdev_notifier_info {
@@ -210,7 +549,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  };
  
  struct netdev_notifier_info_ext {
-@@ -2373,6 +2375,7 @@ static inline void netdev_notifier_info_
+@@ -2376,6 +2377,7 @@ static inline void netdev_notifier_info_
                                             struct net_device *dev)
  {
        info->dev = dev;
@@ -218,7 +557,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  }
  
  static inline struct net_device *
-@@ -2381,6 +2384,12 @@ netdev_notifier_info_to_dev(const struct
+@@ -2384,6 +2386,12 @@ netdev_notifier_info_to_dev(const struct
        return info->dev;
  }
  
@@ -241,7 +580,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  void  __kfree_skb(struct sk_buff *skb);
  extern struct kmem_cache *skbuff_head_cache;
  
-@@ -3293,6 +3294,7 @@ static inline void skb_free_datagram_loc
+@@ -3297,6 +3298,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);
@@ -249,42 +588,58 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  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/net/bonding.h
-+++ b/include/net/bonding.h
-@@ -592,7 +592,8 @@ void bond_destroy_sysfs(struct bond_net
- void bond_prepare_sysfs_group(struct bonding *bond);
- int bond_sysfs_slave_add(struct slave *slave);
- void bond_sysfs_slave_del(struct slave *slave);
--int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
-+int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
-+               struct netlink_ext_ack *extack);
- int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
- u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb);
- int bond_set_carrier(struct bonding *bond);
---- a/net/batman-adv/soft-interface.c
-+++ b/net/batman-adv/soft-interface.c
-@@ -872,7 +872,8 @@ free_bat_counters:
-  * Return: 0 if successful or error otherwise.
-  */
- static int batadv_softif_slave_add(struct net_device *dev,
--                                 struct net_device *slave_dev)
-+                                 struct net_device *slave_dev,
-+                                 struct netlink_ext_ack *extack)
- {
-       struct batadv_hard_iface *hard_iface;
-       struct net *net = dev_net(dev);
---- a/net/bridge/br_device.c
-+++ b/net/bridge/br_device.c
-@@ -324,7 +324,8 @@ void br_netpoll_disable(struct net_bridg
- #endif
+--- a/lib/dma-noop.c
++++ b/lib/dma-noop.c
+@@ -58,11 +58,30 @@ static int dma_noop_map_sg(struct device
+       return nents;
+ }
  
--static int br_add_slave(struct net_device *dev, struct net_device *slave_dev)
-+static int br_add_slave(struct net_device *dev, struct net_device *slave_dev,
-+                      struct netlink_ext_ack *extack)
++static int dma_noop_supported(struct device *dev, u64 mask)
++{
++#ifdef CONFIG_ZONE_DMA
++      if (mask < DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))
++      return 0;
++#else
++      /*
++       * Because 32-bit DMA masks are so common we expect every architecture
++       * to be able to satisfy them - either by not supporting more physical
++       * memory, or by providing a ZONE_DMA32.  If neither is the case, the
++       * architecture needs to use an IOMMU instead of the direct mapping.
++       */
++      if (dev->bus_dma_mask && mask > dev->bus_dma_mask)
++              return 0;
++#endif
++      return 1;
++}
++
+ const struct dma_map_ops dma_noop_ops = {
+       .alloc                  = dma_noop_alloc,
+       .free                   = dma_noop_free,
+       .map_page               = dma_noop_map_page,
+       .map_sg                 = dma_noop_map_sg,
++      dma_supported           = dma_noop_supported
+ };
  
+ EXPORT_SYMBOL(dma_noop_ops);
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -4366,8 +4366,14 @@ void page_frag_free(void *addr)
  {
-       struct net_bridge *br = netdev_priv(dev);
+       struct page *page = virt_to_head_page(addr);
+-      if (unlikely(put_page_testzero(page)))
+-              __free_pages_ok(page, compound_order(page));
++      if (unlikely(put_page_testzero(page))) {
++              unsigned int order = compound_order(page);
++
++              if (order == 0)         /* Via pcp? */
++                      free_hot_cold_page(page, false);
++              else
++                      __free_pages_ok(page, order);
++      }
+ }
+ EXPORT_SYMBOL(page_frag_free);
 --- a/net/core/dev.c
 +++ b/net/core/dev.c
 @@ -162,7 +162,6 @@ static struct list_head offload_base __r
@@ -358,7 +713,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  }
  
  #ifdef CONFIG_NET_INGRESS
-@@ -6338,7 +6339,15 @@ static int __netdev_upper_dev_link(struc
+@@ -6341,7 +6342,15 @@ static int __netdev_upper_dev_link(struc
                                   struct net_device *upper_dev, bool master,
                                   void *upper_priv, void *upper_info)
  {
@@ -375,7 +730,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        int ret = 0;
  
        ASSERT_RTNL();
-@@ -6356,12 +6365,7 @@ static int __netdev_upper_dev_link(struc
+@@ -6359,12 +6368,7 @@ static int __netdev_upper_dev_link(struc
        if (master && netdev_master_upper_dev_get(dev))
                return -EBUSY;
  
@@ -389,7 +744,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                                            &changeupper_info.info);
        ret = notifier_to_errno(ret);
        if (ret)
-@@ -6373,7 +6377,7 @@ static int __netdev_upper_dev_link(struc
+@@ -6376,7 +6380,7 @@ static int __netdev_upper_dev_link(struc
                return ret;
  
        netdev_update_addr_mask(dev);
@@ -398,7 +753,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                                            &changeupper_info.info);
        ret = notifier_to_errno(ret);
        if (ret)
-@@ -6437,21 +6441,25 @@ EXPORT_SYMBOL(netdev_master_upper_dev_li
+@@ -6440,21 +6444,25 @@ EXPORT_SYMBOL(netdev_master_upper_dev_li
  void netdev_upper_dev_unlink(struct net_device *dev,
                             struct net_device *upper_dev)
  {
@@ -429,7 +784,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                                      &changeupper_info.info);
  }
  EXPORT_SYMBOL(netdev_upper_dev_unlink);
-@@ -6467,11 +6475,13 @@ EXPORT_SYMBOL(netdev_upper_dev_unlink);
+@@ -6470,11 +6478,13 @@ EXPORT_SYMBOL(netdev_upper_dev_unlink);
  void netdev_bonding_info_change(struct net_device *dev,
                                struct netdev_bonding_info *bonding_info)
  {
@@ -445,7 +800,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                                      &info.info);
  }
  EXPORT_SYMBOL(netdev_bonding_info_change);
-@@ -6597,11 +6607,13 @@ EXPORT_SYMBOL(dev_get_nest_level);
+@@ -6600,11 +6610,13 @@ EXPORT_SYMBOL(dev_get_nest_level);
  void netdev_lower_state_changed(struct net_device *lower_dev,
                                void *lower_state_info)
  {
@@ -461,7 +816,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                                      &changelowerstate_info.info);
  }
  EXPORT_SYMBOL(netdev_lower_state_changed);
-@@ -6892,11 +6904,14 @@ void __dev_notify_flags(struct net_devic
+@@ -6895,11 +6907,14 @@ void __dev_notify_flags(struct net_devic
  
        if (dev->flags & IFF_UP &&
            (changes & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI | IFF_VOLATILE))) {
@@ -480,49 +835,9 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        }
  }
  
---- a/net/core/rtnetlink.c
-+++ b/net/core/rtnetlink.c
-@@ -1912,7 +1912,8 @@ static int do_setvfinfo(struct net_devic
-       return err;
- }
--static int do_set_master(struct net_device *dev, int ifindex)
-+static int do_set_master(struct net_device *dev, int ifindex,
-+                       struct netlink_ext_ack *extack)
- {
-       struct net_device *upper_dev = netdev_master_upper_dev_get(dev);
-       const struct net_device_ops *ops;
-@@ -1937,7 +1938,7 @@ static int do_set_master(struct net_devi
-                       return -EINVAL;
-               ops = upper_dev->netdev_ops;
-               if (ops->ndo_add_slave) {
--                      err = ops->ndo_add_slave(upper_dev, dev);
-+                      err = ops->ndo_add_slave(upper_dev, dev, extack);
-                       if (err)
-                               return err;
-               } else {
-@@ -2074,7 +2075,7 @@ static int do_setlink(const struct sk_bu
-       }
-       if (tb[IFLA_MASTER]) {
--              err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]));
-+              err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]), extack);
-               if (err)
-                       goto errout;
-               status |= DO_SETLINK_MODIFIED;
-@@ -2723,7 +2724,8 @@ replay:
-                               goto out_unregister;
-               }
-               if (tb[IFLA_MASTER]) {
--                      err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]));
-+                      err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]),
-+                                          extack);
-                       if (err)
-                               goto out_unregister;
-               }
 --- a/net/core/skbuff.c
 +++ b/net/core/skbuff.c
-@@ -799,6 +799,32 @@ void napi_consume_skb(struct sk_buff *sk
+@@ -803,6 +803,32 @@ void napi_consume_skb(struct sk_buff *sk
  }
  EXPORT_SYMBOL(napi_consume_skb);
  
@@ -555,7 +870,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  /* 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) <          \
-@@ -1318,7 +1344,7 @@ static void skb_headers_offset_update(st
+@@ -1322,7 +1348,7 @@ static void skb_headers_offset_update(st
        skb->inner_mac_header += off;
  }
  
@@ -564,7 +879,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  {
        __copy_skb_header(new, old);
  
-@@ -1326,6 +1352,7 @@ static void copy_skb_header(struct sk_bu
+@@ -1330,6 +1356,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;
  }