commit:     fde4b0ebfc100387b4c7f2ef74ad54742ad7fc41
Author:     Arisu Tachibana <alicef <AT> gentoo <DOT> org>
AuthorDate: Sat Aug 16 03:11:47 2025 +0000
Commit:     Arisu Tachibana <alicef <AT> gentoo <DOT> org>
CommitDate: Sat Aug 16 03:11:47 2025 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=fde4b0eb

Linux patch 5.4.272

Signed-off-by: Arisu Tachibana <alicef <AT> gentoo.org>

 0000_README              |    4 +
 1271_linux-5.4.272.patch | 3383 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 3387 insertions(+)

diff --git a/0000_README b/0000_README
index 0065494a..c03ca9d3 100644
--- a/0000_README
+++ b/0000_README
@@ -1127,6 +1127,10 @@ Patch:  1270_linux-5.4.271.patch
 From:   https://www.kernel.org
 Desc:   Linux 5.4.271
 
+Patch:  1271_linux-5.4.272.patch
+From:   https://www.kernel.org
+Desc:   Linux 5.4.272
+
 Patch:  1500_XATTR_USER_PREFIX.patch
 From:   https://bugs.gentoo.org/show_bug.cgi?id=470644
 Desc:   Support for namespace user.pax.* on tmpfs.

diff --git a/1271_linux-5.4.272.patch b/1271_linux-5.4.272.patch
new file mode 100644
index 00000000..0971107e
--- /dev/null
+++ b/1271_linux-5.4.272.patch
@@ -0,0 +1,3383 @@
+diff --git a/Makefile b/Makefile
+index 56e53f77c0378..184b31e84b99c 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 5
+ PATCHLEVEL = 4
+-SUBLEVEL = 271
++SUBLEVEL = 272
+ EXTRAVERSION =
+ NAME = Kleptomaniac Octopus
+ 
+diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
+index bf497b8b0ec60..bbe7a0da6264f 100644
+--- a/arch/alpha/kernel/osf_sys.c
++++ b/arch/alpha/kernel/osf_sys.c
+@@ -963,7 +963,7 @@ put_tv32(struct timeval32 __user *o, struct timespec64 *i)
+ }
+ 
+ static inline long
+-put_tv_to_tv32(struct timeval32 __user *o, struct timeval *i)
++put_tv_to_tv32(struct timeval32 __user *o, struct __kernel_old_timeval *i)
+ {
+       return copy_to_user(o, &(struct timeval32){
+                               .tv_sec = i->tv_sec,
+diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi 
b/arch/arm64/boot/dts/qcom/sdm845.dtsi
+index 845005f1be2de..b4a0234f66d16 100644
+--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
++++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
+@@ -2501,10 +2501,10 @@ usb_1: usb@a6f8800 {
+                                         <&gcc GCC_USB30_PRIM_MASTER_CLK>;
+                       assigned-clock-rates = <19200000>, <150000000>;
+ 
+-                      interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+-                                   <GIC_SPI 486 IRQ_TYPE_LEVEL_HIGH>,
+-                                   <GIC_SPI 488 IRQ_TYPE_EDGE_BOTH>,
+-                                   <GIC_SPI 489 IRQ_TYPE_EDGE_BOTH>;
++                      interrupts-extended = <&intc GIC_SPI 131 
IRQ_TYPE_LEVEL_HIGH>,
++                                            <&intc GIC_SPI 486 
IRQ_TYPE_LEVEL_HIGH>,
++                                            <&pdc_intc 8 IRQ_TYPE_EDGE_BOTH>,
++                                            <&pdc_intc 9 IRQ_TYPE_EDGE_BOTH>;
+                       interrupt-names = "hs_phy_irq", "ss_phy_irq",
+                                         "dm_hs_phy_irq", "dp_hs_phy_irq";
+ 
+@@ -2545,10 +2545,10 @@ usb_2: usb@a8f8800 {
+                                         <&gcc GCC_USB30_SEC_MASTER_CLK>;
+                       assigned-clock-rates = <19200000>, <150000000>;
+ 
+-                      interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
+-                                   <GIC_SPI 487 IRQ_TYPE_LEVEL_HIGH>,
+-                                   <GIC_SPI 490 IRQ_TYPE_EDGE_BOTH>,
+-                                   <GIC_SPI 491 IRQ_TYPE_EDGE_BOTH>;
++                      interrupts-extended = <&intc GIC_SPI 136 
IRQ_TYPE_LEVEL_HIGH>,
++                                            <&intc GIC_SPI 487 
IRQ_TYPE_LEVEL_HIGH>,
++                                            <&pdc_intc 10 IRQ_TYPE_EDGE_BOTH>,
++                                            <&pdc_intc 11 IRQ_TYPE_EDGE_BOTH>;
+                       interrupt-names = "hs_phy_irq", "ss_phy_irq",
+                                         "dm_hs_phy_irq", "dp_hs_phy_irq";
+ 
+@@ -2940,6 +2940,15 @@ dispcc: clock-controller@af00000 {
+                       #power-domain-cells = <1>;
+               };
+ 
++              pdc_intc: interrupt-controller@b220000 {
++                      compatible = "qcom,sdm845-pdc", "qcom,pdc";
++                      reg = <0 0x0b220000 0 0x30000>;
++                      qcom,pdc-ranges = <0 480 94>, <94 609 15>, <115 630 7>;
++                      #interrupt-cells = <2>;
++                      interrupt-parent = <&intc>;
++                      interrupt-controller;
++              };
++
+               pdc_reset: reset-controller@b2e0000 {
+                       compatible = "qcom,sdm845-pdc-global";
+                       reg = <0 0x0b2e0000 0 0x20000>;
+diff --git a/arch/um/Kconfig b/arch/um/Kconfig
+index 468a5d63ef269..107a0bc668e9f 100644
+--- a/arch/um/Kconfig
++++ b/arch/um/Kconfig
+@@ -85,6 +85,19 @@ config LD_SCRIPT_DYN
+       depends on !LD_SCRIPT_STATIC
+       select MODULE_REL_CRCS if MODVERSIONS
+ 
++config LD_SCRIPT_DYN_RPATH
++      bool "set rpath in the binary" if EXPERT
++      default y
++      depends on LD_SCRIPT_DYN
++      help
++        Add /lib (and /lib64 for 64-bit) to the linux binary's rpath
++        explicitly.
++
++        You may need to turn this off if compiling for nix systems
++        that have their libraries in random /nix directories and
++        might otherwise unexpected use libraries from /lib or /lib64
++        instead of the desired ones.
++
+ config HOSTFS
+       tristate "Host filesystem"
+       help
+diff --git a/arch/um/Makefile b/arch/um/Makefile
+index 773120be0f56f..94cea8d46b222 100644
+--- a/arch/um/Makefile
++++ b/arch/um/Makefile
+@@ -118,7 +118,8 @@ archprepare:
+       $(Q)$(MAKE) $(build)=$(HOST_DIR)/um include/generated/user_constants.h
+ 
+ LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
+-LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib $(call cc-option, -no-pie)
++LINK-$(CONFIG_LD_SCRIPT_DYN) += $(call cc-option, -no-pie)
++LINK-$(CONFIG_LD_SCRIPT_DYN_RPATH) += -Wl,-rpath,/lib
+ 
+ CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, 
-fno-pic,) \
+       $(call cc-option, -fno-stack-protector,) \
+diff --git a/arch/x86/Makefile.um b/arch/x86/Makefile.um
+index 1db7913795f51..b3c1ae084180d 100644
+--- a/arch/x86/Makefile.um
++++ b/arch/x86/Makefile.um
+@@ -44,7 +44,7 @@ ELF_FORMAT := elf64-x86-64
+ 
+ # Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example.
+ 
+-LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64
++LINK-$(CONFIG_LD_SCRIPT_DYN_RPATH) += -Wl,-rpath,/lib64
+ LINK-y += -m64
+ 
+ endif
+diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
+index d7c01b70e43db..af6ac068ca5d3 100644
+--- a/drivers/base/regmap/internal.h
++++ b/drivers/base/regmap/internal.h
+@@ -104,6 +104,10 @@ struct regmap {
+       int (*reg_write)(void *context, unsigned int reg, unsigned int val);
+       int (*reg_update_bits)(void *context, unsigned int reg,
+                              unsigned int mask, unsigned int val);
++      /* Bulk read/write */
++      int (*read)(void *context, const void *reg_buf, size_t reg_size,
++                  void *val_buf, size_t val_size);
++      int (*write)(void *context, const void *data, size_t count);
+ 
+       bool defer_caching;
+ 
+diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
+index 23574c328616f..6f580883c1973 100644
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -771,12 +771,15 @@ struct regmap *__regmap_init(struct device *dev,
+               map->reg_stride_order = ilog2(map->reg_stride);
+       else
+               map->reg_stride_order = -1;
+-      map->use_single_read = config->use_single_read || !bus || !bus->read;
+-      map->use_single_write = config->use_single_write || !bus || !bus->write;
+-      map->can_multi_write = config->can_multi_write && bus && bus->write;
++      map->use_single_read = config->use_single_read || !(config->read || 
(bus && bus->read));
++      map->use_single_write = config->use_single_write || !(config->write || 
(bus && bus->write));
++      map->can_multi_write = config->can_multi_write && (config->write || 
(bus && bus->write));
+       if (bus) {
+               map->max_raw_read = bus->max_raw_read;
+               map->max_raw_write = bus->max_raw_write;
++      } else if (config->max_raw_read && config->max_raw_write) {
++              map->max_raw_read = config->max_raw_read;
++              map->max_raw_write = config->max_raw_write;
+       }
+       map->dev = dev;
+       map->bus = bus;
+@@ -810,9 +813,19 @@ struct regmap *__regmap_init(struct device *dev,
+               map->read_flag_mask = bus->read_flag_mask;
+       }
+ 
+-      if (!bus) {
++      if (config && config->read && config->write) {
++              map->reg_read  = _regmap_bus_read;
++
++              /* Bulk read/write */
++              map->read = config->read;
++              map->write = config->write;
++
++              reg_endian = REGMAP_ENDIAN_NATIVE;
++              val_endian = REGMAP_ENDIAN_NATIVE;
++      } else if (!bus) {
+               map->reg_read  = config->reg_read;
+               map->reg_write = config->reg_write;
++              map->reg_update_bits = config->reg_update_bits;
+ 
+               map->defer_caching = false;
+               goto skip_format_initialization;
+@@ -825,10 +838,13 @@ struct regmap *__regmap_init(struct device *dev,
+       } else {
+               map->reg_read  = _regmap_bus_read;
+               map->reg_update_bits = bus->reg_update_bits;
+-      }
++              /* Bulk read/write */
++              map->read = bus->read;
++              map->write = bus->write;
+ 
+-      reg_endian = regmap_get_reg_endian(bus, config);
+-      val_endian = regmap_get_val_endian(dev, bus, config);
++              reg_endian = regmap_get_reg_endian(bus, config);
++              val_endian = regmap_get_val_endian(dev, bus, config);
++      }
+ 
+       switch (config->reg_bits + map->reg_shift) {
+       case 2:
+@@ -1479,8 +1495,6 @@ static int _regmap_raw_write_impl(struct regmap *map, 
unsigned int reg,
+       size_t len;
+       int i;
+ 
+-      WARN_ON(!map->bus);
+-
+       /* Check for unwritable or noinc registers in range
+        * before we start
+        */
+@@ -1562,7 +1576,7 @@ static int _regmap_raw_write_impl(struct regmap *map, 
unsigned int reg,
+               val = work_val;
+       }
+ 
+-      if (map->async && map->bus->async_write) {
++      if (map->async && map->bus && map->bus->async_write) {
+               struct regmap_async *async;
+ 
+               trace_regmap_async_write_start(map, reg, val_len);
+@@ -1630,10 +1644,10 @@ static int _regmap_raw_write_impl(struct regmap *map, 
unsigned int reg,
+        * write.
+        */
+       if (val == work_val)
+-              ret = map->bus->write(map->bus_context, map->work_buf,
+-                                    map->format.reg_bytes +
+-                                    map->format.pad_bytes +
+-                                    val_len);
++              ret = map->write(map->bus_context, map->work_buf,
++                               map->format.reg_bytes +
++                               map->format.pad_bytes +
++                               val_len);
+       else if (map->bus->gather_write)
+               ret = map->bus->gather_write(map->bus_context, map->work_buf,
+                                            map->format.reg_bytes +
+@@ -1652,7 +1666,7 @@ static int _regmap_raw_write_impl(struct regmap *map, 
unsigned int reg,
+               memcpy(buf, map->work_buf, map->format.reg_bytes);
+               memcpy(buf + map->format.reg_bytes + map->format.pad_bytes,
+                      val, val_len);
+-              ret = map->bus->write(map->bus_context, buf, len);
++              ret = map->write(map->bus_context, buf, len);
+ 
+               kfree(buf);
+       } else if (ret != 0 && !map->cache_bypass && map->format.parse_val) {
+@@ -1709,7 +1723,7 @@ static int _regmap_bus_formatted_write(void *context, 
unsigned int reg,
+       struct regmap_range_node *range;
+       struct regmap *map = context;
+ 
+-      WARN_ON(!map->bus || !map->format.format_write);
++      WARN_ON(!map->format.format_write);
+ 
+       range = _regmap_range_lookup(map, reg);
+       if (range) {
+@@ -1722,8 +1736,7 @@ static int _regmap_bus_formatted_write(void *context, 
unsigned int reg,
+ 
+       trace_regmap_hw_write_start(map, reg, 1);
+ 
+-      ret = map->bus->write(map->bus_context, map->work_buf,
+-                            map->format.buf_size);
++      ret = map->write(map->bus_context, map->work_buf, map->format.buf_size);
+ 
+       trace_regmap_hw_write_done(map, reg, 1);
+ 
+@@ -1743,7 +1756,7 @@ static int _regmap_bus_raw_write(void *context, unsigned 
int reg,
+ {
+       struct regmap *map = context;
+ 
+-      WARN_ON(!map->bus || !map->format.format_val);
++      WARN_ON(!map->format.format_val);
+ 
+       map->format.format_val(map->work_buf + map->format.reg_bytes
+                              + map->format.pad_bytes, val, 0);
+@@ -1757,7 +1770,7 @@ static int _regmap_bus_raw_write(void *context, unsigned 
int reg,
+ 
+ static inline void *_regmap_map_get_context(struct regmap *map)
+ {
+-      return (map->bus) ? map : map->bus_context;
++      return (map->bus || (!map->bus && map->read)) ? map : map->bus_context;
+ }
+ 
+ int _regmap_write(struct regmap *map, unsigned int reg,
+@@ -2166,7 +2179,7 @@ static int _regmap_raw_multi_reg_write(struct regmap 
*map,
+       u8 = buf;
+       *u8 |= map->write_flag_mask;
+ 
+-      ret = map->bus->write(map->bus_context, buf, len);
++      ret = map->write(map->bus_context, buf, len);
+ 
+       kfree(buf);
+ 
+@@ -2464,9 +2477,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned 
int reg, void *val,
+       struct regmap_range_node *range;
+       int ret;
+ 
+-      WARN_ON(!map->bus);
+-
+-      if (!map->bus || !map->bus->read)
++      if (!map->read)
+               return -EINVAL;
+ 
+       range = _regmap_range_lookup(map, reg);
+@@ -2482,9 +2493,9 @@ static int _regmap_raw_read(struct regmap *map, unsigned 
int reg, void *val,
+                                     map->read_flag_mask);
+       trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes);
+ 
+-      ret = map->bus->read(map->bus_context, map->work_buf,
+-                           map->format.reg_bytes + map->format.pad_bytes,
+-                           val, val_len);
++      ret = map->read(map->bus_context, map->work_buf,
++                      map->format.reg_bytes + map->format.pad_bytes,
++                      val, val_len);
+ 
+       trace_regmap_hw_read_done(map, reg, val_len / map->format.val_bytes);
+ 
+@@ -2595,8 +2606,6 @@ int regmap_raw_read(struct regmap *map, unsigned int 
reg, void *val,
+       unsigned int v;
+       int ret, i;
+ 
+-      if (!map->bus)
+-              return -EINVAL;
+       if (val_len % map->format.val_bytes)
+               return -EINVAL;
+       if (!IS_ALIGNED(reg, map->reg_stride))
+@@ -2611,7 +2620,7 @@ int regmap_raw_read(struct regmap *map, unsigned int 
reg, void *val,
+               size_t chunk_count, chunk_bytes;
+               size_t chunk_regs = val_count;
+ 
+-              if (!map->bus->read) {
++              if (!map->read) {
+                       ret = -ENOTSUPP;
+                       goto out;
+               }
+@@ -2671,7 +2680,7 @@ EXPORT_SYMBOL_GPL(regmap_raw_read);
+  * @val: Pointer to data buffer
+  * @val_len: Length of output buffer in bytes.
+  *
+- * The regmap API usually assumes that bulk bus read operations will read a
++ * The regmap API usually assumes that bulk read operations will read a
+  * range of registers. Some devices have certain registers for which a read
+  * operation read will read from an internal FIFO.
+  *
+@@ -2689,10 +2698,6 @@ int regmap_noinc_read(struct regmap *map, unsigned int 
reg,
+       size_t read_len;
+       int ret;
+ 
+-      if (!map->bus)
+-              return -EINVAL;
+-      if (!map->bus->read)
+-              return -ENOTSUPP;
+       if (val_len % map->format.val_bytes)
+               return -EINVAL;
+       if (!IS_ALIGNED(reg, map->reg_stride))
+@@ -2806,7 +2811,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int 
reg, void *val,
+       if (val_count == 0)
+               return -EINVAL;
+ 
+-      if (map->bus && map->format.parse_inplace && (vol || map->cache_type == 
REGCACHE_NONE)) {
++      if (map->format.parse_inplace && (vol || map->cache_type == 
REGCACHE_NONE)) {
+               ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
+               if (ret != 0)
+                       return ret;
+diff --git a/drivers/input/serio/i8042-x86ia64io.h 
b/drivers/input/serio/i8042-x86ia64io.h
+index 1ab7f27bc9062..4ae96bd56253c 100644
+--- a/drivers/input/serio/i8042-x86ia64io.h
++++ b/drivers/input/serio/i8042-x86ia64io.h
+@@ -1179,6 +1179,12 @@ static const struct dmi_system_id 
i8042_dmi_quirk_table[] __initconst = {
+                                       SERIO_QUIRK_RESET_ALWAYS | 
SERIO_QUIRK_NOLOOP |
+                                       SERIO_QUIRK_NOPNP)
+       },
++      {
++              .matches = {
++                      DMI_MATCH(DMI_BOARD_NAME, "NS5x_7xPU"),
++              },
++              .driver_data = (void *)(SERIO_QUIRK_NOAUX)
++      },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "NJ50_70CU"),
+diff --git a/drivers/net/ethernet/intel/ice/ice_main.c 
b/drivers/net/ethernet/intel/ice/ice_main.c
+index 209ae96875849..cf1baae963de2 100644
+--- a/drivers/net/ethernet/intel/ice/ice_main.c
++++ b/drivers/net/ethernet/intel/ice/ice_main.c
+@@ -4594,6 +4594,8 @@ ice_bridge_setlink(struct net_device *dev, struct 
nlmsghdr *nlh,
+       pf_sw = pf->first_sw;
+       /* find the attribute in the netlink message */
+       br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
++      if (!br_spec)
++              return -EINVAL;
+ 
+       nla_for_each_nested(attr, br_spec, rem) {
+               __u16 mode;
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c 
b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+index 805aa9f53fc1f..3a188576f4c88 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+@@ -2938,8 +2938,8 @@ static void ixgbe_check_lsc(struct ixgbe_adapter 
*adapter)
+ static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
+                                          u64 qmask)
+ {
+-      u32 mask;
+       struct ixgbe_hw *hw = &adapter->hw;
++      u32 mask;
+ 
+       switch (hw->mac.type) {
+       case ixgbe_mac_82598EB:
+@@ -10528,6 +10528,44 @@ static void ixgbe_reset_rxr_stats(struct ixgbe_ring 
*rx_ring)
+       memset(&rx_ring->rx_stats, 0, sizeof(rx_ring->rx_stats));
+ }
+ 
++/**
++ * ixgbe_irq_disable_single - Disable single IRQ vector
++ * @adapter: adapter structure
++ * @ring: ring index
++ **/
++static void ixgbe_irq_disable_single(struct ixgbe_adapter *adapter, u32 ring)
++{
++      struct ixgbe_hw *hw = &adapter->hw;
++      u64 qmask = BIT_ULL(ring);
++      u32 mask;
++
++      switch (adapter->hw.mac.type) {
++      case ixgbe_mac_82598EB:
++              mask = qmask & IXGBE_EIMC_RTX_QUEUE;
++              IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, mask);
++              break;
++      case ixgbe_mac_82599EB:
++      case ixgbe_mac_X540:
++      case ixgbe_mac_X550:
++      case ixgbe_mac_X550EM_x:
++      case ixgbe_mac_x550em_a:
++              mask = (qmask & 0xFFFFFFFF);
++              if (mask)
++                      IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
++              mask = (qmask >> 32);
++              if (mask)
++                      IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
++              break;
++      default:
++              break;
++      }
++      IXGBE_WRITE_FLUSH(&adapter->hw);
++      if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
++              synchronize_irq(adapter->msix_entries[ring].vector);
++      else
++              synchronize_irq(adapter->pdev->irq);
++}
++
+ /**
+  * ixgbe_txrx_ring_disable - Disable Rx/Tx/XDP Tx rings
+  * @adapter: adapter structure
+@@ -10544,6 +10582,11 @@ void ixgbe_txrx_ring_disable(struct ixgbe_adapter 
*adapter, int ring)
+       tx_ring = adapter->tx_ring[ring];
+       xdp_ring = adapter->xdp_ring[ring];
+ 
++      ixgbe_irq_disable_single(adapter, ring);
++
++      /* Rx/Tx/XDP Tx share the same napi context. */
++      napi_disable(&rx_ring->q_vector->napi);
++
+       ixgbe_disable_txr(adapter, tx_ring);
+       if (xdp_ring)
+               ixgbe_disable_txr(adapter, xdp_ring);
+@@ -10552,9 +10595,6 @@ void ixgbe_txrx_ring_disable(struct ixgbe_adapter 
*adapter, int ring)
+       if (xdp_ring)
+               synchronize_rcu();
+ 
+-      /* Rx/Tx/XDP Tx share the same napi context. */
+-      napi_disable(&rx_ring->q_vector->napi);
+-
+       ixgbe_clean_tx_ring(tx_ring);
+       if (xdp_ring)
+               ixgbe_clean_tx_ring(xdp_ring);
+@@ -10582,9 +10622,6 @@ void ixgbe_txrx_ring_enable(struct ixgbe_adapter 
*adapter, int ring)
+       tx_ring = adapter->tx_ring[ring];
+       xdp_ring = adapter->xdp_ring[ring];
+ 
+-      /* Rx/Tx/XDP Tx share the same napi context. */
+-      napi_enable(&rx_ring->q_vector->napi);
+-
+       ixgbe_configure_tx_ring(adapter, tx_ring);
+       if (xdp_ring)
+               ixgbe_configure_tx_ring(adapter, xdp_ring);
+@@ -10593,6 +10630,11 @@ void ixgbe_txrx_ring_enable(struct ixgbe_adapter 
*adapter, int ring)
+       clear_bit(__IXGBE_TX_DISABLED, &tx_ring->state);
+       if (xdp_ring)
+               clear_bit(__IXGBE_TX_DISABLED, &xdp_ring->state);
++
++      /* Rx/Tx/XDP Tx share the same napi context. */
++      napi_enable(&rx_ring->q_vector->napi);
++      ixgbe_irq_enable_queues(adapter, BIT_ULL(ring));
++      IXGBE_WRITE_FLUSH(&adapter->hw);
+ }
+ 
+ /**
+diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
+index 5636673b84e7d..f932e4120cb6c 100644
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -215,7 +215,7 @@ static void geneve_rx(struct geneve_dev *geneve, struct 
geneve_sock *gs,
+       struct metadata_dst *tun_dst = NULL;
+       struct pcpu_sw_netstats *stats;
+       unsigned int len;
+-      int err = 0;
++      int nh, err = 0;
+       void *oiph;
+ 
+       if (ip_tunnel_collect_metadata() || gs->collect_md) {
+@@ -259,9 +259,23 @@ static void geneve_rx(struct geneve_dev *geneve, struct 
geneve_sock *gs,
+               goto drop;
+       }
+ 
+-      oiph = skb_network_header(skb);
++      /* Save offset of outer header relative to skb->head,
++       * because we are going to reset the network header to the inner header
++       * and might change skb->head.
++       */
++      nh = skb_network_header(skb) - skb->head;
++
+       skb_reset_network_header(skb);
+ 
++      if (!pskb_inet_may_pull(skb)) {
++              DEV_STATS_INC(geneve->dev, rx_length_errors);
++              DEV_STATS_INC(geneve->dev, rx_errors);
++              goto drop;
++      }
++
++      /* Get the outer header. */
++      oiph = skb->head + nh;
++
+       if (geneve_get_sk_family(gs) == AF_INET)
+               err = IP_ECN_decapsulate(oiph, skb);
+ #if IS_ENABLED(CONFIG_IPV6)
+diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
+index 31301cd242076..e42102a1de41f 100644
+--- a/drivers/net/hyperv/netvsc_drv.c
++++ b/drivers/net/hyperv/netvsc_drv.c
+@@ -43,6 +43,10 @@
+ #define LINKCHANGE_INT (2 * HZ)
+ #define VF_TAKEOVER_INT (HZ / 10)
+ 
++/* Macros to define the context of vf registration */
++#define VF_REG_IN_PROBE               1
++#define VF_REG_IN_NOTIFIER    2
++
+ static unsigned int ring_size __ro_after_init = 128;
+ module_param(ring_size, uint, 0444);
+ MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
+@@ -2037,7 +2041,7 @@ static rx_handler_result_t netvsc_vf_handle_frame(struct 
sk_buff **pskb)
+ }
+ 
+ static int netvsc_vf_join(struct net_device *vf_netdev,
+-                        struct net_device *ndev)
++                        struct net_device *ndev, int context)
+ {
+       struct net_device_context *ndev_ctx = netdev_priv(ndev);
+       int ret;
+@@ -2060,7 +2064,11 @@ static int netvsc_vf_join(struct net_device *vf_netdev,
+               goto upper_link_failed;
+       }
+ 
+-      schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
++      /* If this registration is called from probe context vf_takeover
++       * is taken care of later in probe itself.
++       */
++      if (context == VF_REG_IN_NOTIFIER)
++              schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
+ 
+       call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
+ 
+@@ -2153,8 +2161,17 @@ static struct net_device *get_netvsc_byslot(const 
struct net_device *vf_netdev)
+               if (!ndev_ctx->vf_alloc)
+                       continue;
+ 
+-              if (ndev_ctx->vf_serial == serial)
+-                      return hv_get_drvdata(ndev_ctx->device_ctx);
++              if (ndev_ctx->vf_serial != serial)
++                      continue;
++
++              ndev = hv_get_drvdata(ndev_ctx->device_ctx);
++              if (ndev->addr_len != vf_netdev->addr_len ||
++                  memcmp(ndev->perm_addr, vf_netdev->perm_addr,
++                         ndev->addr_len) != 0)
++                      continue;
++
++              return ndev;
++
+       }
+ 
+       /* Fallback path to check synthetic vf with help of mac addr.
+@@ -2189,7 +2206,7 @@ static int netvsc_prepare_bonding(struct net_device 
*vf_netdev)
+       return NOTIFY_DONE;
+ }
+ 
+-static int netvsc_register_vf(struct net_device *vf_netdev)
++static int netvsc_register_vf(struct net_device *vf_netdev, int context)
+ {
+       struct net_device_context *net_device_ctx;
+       struct netvsc_device *netvsc_dev;
+@@ -2228,7 +2245,7 @@ static int netvsc_register_vf(struct net_device 
*vf_netdev)
+ 
+       netdev_info(ndev, "VF registering: %s\n", vf_netdev->name);
+ 
+-      if (netvsc_vf_join(vf_netdev, ndev) != 0)
++      if (netvsc_vf_join(vf_netdev, ndev, context) != 0)
+               return NOTIFY_DONE;
+ 
+       dev_hold(vf_netdev);
+@@ -2292,10 +2309,31 @@ static int netvsc_unregister_vf(struct net_device 
*vf_netdev)
+       return NOTIFY_OK;
+ }
+ 
++static int check_dev_is_matching_vf(struct net_device *event_ndev)
++{
++      /* Skip NetVSC interfaces */
++      if (event_ndev->netdev_ops == &device_ops)
++              return -ENODEV;
++
++      /* Avoid non-Ethernet type devices */
++      if (event_ndev->type != ARPHRD_ETHER)
++              return -ENODEV;
++
++      /* Avoid Vlan dev with same MAC registering as VF */
++      if (is_vlan_dev(event_ndev))
++              return -ENODEV;
++
++      /* Avoid Bonding master dev with same MAC registering as VF */
++      if (netif_is_bond_master(event_ndev))
++              return -ENODEV;
++
++      return 0;
++}
++
+ static int netvsc_probe(struct hv_device *dev,
+                       const struct hv_vmbus_device_id *dev_id)
+ {
+-      struct net_device *net = NULL;
++      struct net_device *net = NULL, *vf_netdev;
+       struct net_device_context *net_device_ctx;
+       struct netvsc_device_info *device_info = NULL;
+       struct netvsc_device *nvdev;
+@@ -2396,6 +2434,30 @@ static int netvsc_probe(struct hv_device *dev,
+       }
+ 
+       list_add(&net_device_ctx->list, &netvsc_dev_list);
++
++      /* When the hv_netvsc driver is unloaded and reloaded, the
++       * NET_DEVICE_REGISTER for the vf device is replayed before probe
++       * is complete. This is because register_netdevice_notifier() gets
++       * registered before vmbus_driver_register() so that callback func
++       * is set before probe and we don't miss events like NETDEV_POST_INIT
++       * So, in this section we try to register the matching vf device that
++       * is present as a netdevice, knowing that its register call is not
++       * processed in the netvsc_netdev_notifier(as probing is progress and
++       * get_netvsc_byslot fails).
++       */
++      for_each_netdev(dev_net(net), vf_netdev) {
++              ret = check_dev_is_matching_vf(vf_netdev);
++              if (ret != 0)
++                      continue;
++
++              if (net != get_netvsc_byslot(vf_netdev))
++                      continue;
++
++              netvsc_prepare_bonding(vf_netdev);
++              netvsc_register_vf(vf_netdev, VF_REG_IN_PROBE);
++              __netvsc_vf_setup(net, vf_netdev);
++              break;
++      }
+       rtnl_unlock();
+ 
+       kfree(device_info);
+@@ -2488,29 +2550,17 @@ static int netvsc_netdev_event(struct notifier_block 
*this,
+                              unsigned long event, void *ptr)
+ {
+       struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
++      int ret = 0;
+ 
+-      /* Skip our own events */
+-      if (event_dev->netdev_ops == &device_ops)
+-              return NOTIFY_DONE;
+-
+-      /* Avoid non-Ethernet type devices */
+-      if (event_dev->type != ARPHRD_ETHER)
+-              return NOTIFY_DONE;
+-
+-      /* Avoid Vlan dev with same MAC registering as VF */
+-      if (is_vlan_dev(event_dev))
+-              return NOTIFY_DONE;
+-
+-      /* Avoid Bonding master dev with same MAC registering as VF */
+-      if ((event_dev->priv_flags & IFF_BONDING) &&
+-          (event_dev->flags & IFF_MASTER))
++      ret = check_dev_is_matching_vf(event_dev);
++      if (ret != 0)
+               return NOTIFY_DONE;
+ 
+       switch (event) {
+       case NETDEV_POST_INIT:
+               return netvsc_prepare_bonding(event_dev);
+       case NETDEV_REGISTER:
+-              return netvsc_register_vf(event_dev);
++              return netvsc_register_vf(event_dev, VF_REG_IN_NOTIFIER);
+       case NETDEV_UNREGISTER:
+               return netvsc_unregister_vf(event_dev);
+       case NETDEV_UP:
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index 454a03f0bc69f..b0efaf56d78f3 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -90,6 +90,12 @@
+ /* statistic update interval (mSec) */
+ #define STAT_UPDATE_TIMER             (1 * 1000)
+ 
++/* time to wait for MAC or FCT to stop (jiffies) */
++#define HW_DISABLE_TIMEOUT            (HZ / 10)
++
++/* time to wait between polling MAC or FCT state (ms) */
++#define HW_DISABLE_DELAY_MS           1
++
+ /* defines interrupts from interrupt EP */
+ #define MAX_INT_EP                    (32)
+ #define INT_EP_INTEP                  (31)
+@@ -384,8 +390,9 @@ struct lan78xx_net {
+       struct urb              *urb_intr;
+       struct usb_anchor       deferred;
+ 
++      struct mutex            dev_mutex; /* serialise open/stop wrt 
suspend/resume */
+       struct mutex            phy_mutex; /* for phy access */
+-      unsigned                pipe_in, pipe_out, pipe_intr;
++      unsigned int            pipe_in, pipe_out, pipe_intr;
+ 
+       u32                     hard_mtu;       /* count any extra framing */
+       size_t                  rx_urb_size;    /* size for rx urbs */
+@@ -395,7 +402,7 @@ struct lan78xx_net {
+       wait_queue_head_t       *wait;
+       unsigned char           suspend_count;
+ 
+-      unsigned                maxpacket;
++      unsigned int            maxpacket;
+       struct timer_list       delay;
+       struct timer_list       stat_monitor;
+ 
+@@ -479,6 +486,26 @@ static int lan78xx_write_reg(struct lan78xx_net *dev, u32 
index, u32 data)
+       return ret;
+ }
+ 
++static int lan78xx_update_reg(struct lan78xx_net *dev, u32 reg, u32 mask,
++                            u32 data)
++{
++      int ret;
++      u32 buf;
++
++      ret = lan78xx_read_reg(dev, reg, &buf);
++      if (ret < 0)
++              return ret;
++
++      buf &= ~mask;
++      buf |= (mask & data);
++
++      ret = lan78xx_write_reg(dev, reg, buf);
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
+ static int lan78xx_read_stats(struct lan78xx_net *dev,
+                             struct lan78xx_statstage *data)
+ {
+@@ -504,7 +531,7 @@ static int lan78xx_read_stats(struct lan78xx_net *dev,
+       if (likely(ret >= 0)) {
+               src = (u32 *)stats;
+               dst = (u32 *)data;
+-              for (i = 0; i < sizeof(*stats)/sizeof(u32); i++) {
++              for (i = 0; i < sizeof(*stats) / sizeof(u32); i++) {
+                       le32_to_cpus(&src[i]);
+                       dst[i] = src[i];
+               }
+@@ -518,10 +545,11 @@ static int lan78xx_read_stats(struct lan78xx_net *dev,
+       return ret;
+ }
+ 
+-#define check_counter_rollover(struct1, dev_stats, member) {  \
+-      if (struct1->member < dev_stats.saved.member)           \
+-              dev_stats.rollover_count.member++;              \
+-      }
++#define check_counter_rollover(struct1, dev_stats, member)            \
++      do {                                                            \
++              if ((struct1)->member < (dev_stats).saved.member)       \
++                      (dev_stats).rollover_count.member++;            \
++      } while (0)
+ 
+ static void lan78xx_check_stat_rollover(struct lan78xx_net *dev,
+                                       struct lan78xx_statstage *stats)
+@@ -847,9 +875,9 @@ static int lan78xx_read_raw_otp(struct lan78xx_net *dev, 
u32 offset,
+ 
+       for (i = 0; i < length; i++) {
+               lan78xx_write_reg(dev, OTP_ADDR1,
+-                                      ((offset + i) >> 8) & OTP_ADDR1_15_11);
++                                ((offset + i) >> 8) & OTP_ADDR1_15_11);
+               lan78xx_write_reg(dev, OTP_ADDR2,
+-                                      ((offset + i) & OTP_ADDR2_10_3));
++                                ((offset + i) & OTP_ADDR2_10_3));
+ 
+               lan78xx_write_reg(dev, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_);
+               lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
+@@ -903,9 +931,9 @@ static int lan78xx_write_raw_otp(struct lan78xx_net *dev, 
u32 offset,
+ 
+       for (i = 0; i < length; i++) {
+               lan78xx_write_reg(dev, OTP_ADDR1,
+-                                      ((offset + i) >> 8) & OTP_ADDR1_15_11);
++                                ((offset + i) >> 8) & OTP_ADDR1_15_11);
+               lan78xx_write_reg(dev, OTP_ADDR2,
+-                                      ((offset + i) & OTP_ADDR2_10_3));
++                                ((offset + i) & OTP_ADDR2_10_3));
+               lan78xx_write_reg(dev, OTP_PRGM_DATA, data[i]);
+               lan78xx_write_reg(dev, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_);
+               lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
+@@ -962,7 +990,7 @@ static int lan78xx_dataport_wait_not_busy(struct 
lan78xx_net *dev)
+               usleep_range(40, 100);
+       }
+ 
+-      netdev_warn(dev->net, "lan78xx_dataport_wait_not_busy timed out");
++      netdev_warn(dev->net, "%s timed out", __func__);
+ 
+       return -EIO;
+ }
+@@ -975,7 +1003,7 @@ static int lan78xx_dataport_write(struct lan78xx_net 
*dev, u32 ram_select,
+       int i, ret;
+ 
+       if (usb_autopm_get_interface(dev->intf) < 0)
+-                      return 0;
++              return 0;
+ 
+       mutex_lock(&pdata->dataport_mutex);
+ 
+@@ -1048,9 +1076,9 @@ static void lan78xx_deferred_multicast_write(struct 
work_struct *param)
+       for (i = 1; i < NUM_OF_MAF; i++) {
+               lan78xx_write_reg(dev, MAF_HI(i), 0);
+               lan78xx_write_reg(dev, MAF_LO(i),
+-                                      pdata->pfilter_table[i][1]);
++                                pdata->pfilter_table[i][1]);
+               lan78xx_write_reg(dev, MAF_HI(i),
+-                                      pdata->pfilter_table[i][0]);
++                                pdata->pfilter_table[i][0]);
+       }
+ 
+       lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
+@@ -1069,11 +1097,12 @@ static void lan78xx_set_multicast(struct net_device 
*netdev)
+                           RFE_CTL_DA_PERFECT_ | RFE_CTL_MCAST_HASH_);
+ 
+       for (i = 0; i < DP_SEL_VHF_HASH_LEN; i++)
+-                      pdata->mchash_table[i] = 0;
++              pdata->mchash_table[i] = 0;
++
+       /* pfilter_table[0] has own HW address */
+       for (i = 1; i < NUM_OF_MAF; i++) {
+-                      pdata->pfilter_table[i][0] =
+-                      pdata->pfilter_table[i][1] = 0;
++              pdata->pfilter_table[i][0] = 0;
++              pdata->pfilter_table[i][1] = 0;
+       }
+ 
+       pdata->rfe_ctl |= RFE_CTL_BCAST_EN_;
+@@ -1163,7 +1192,7 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
+       /* clear LAN78xx interrupt status */
+       ret = lan78xx_write_reg(dev, INT_STS, INT_STS_PHY_INT_);
+       if (unlikely(ret < 0))
+-              return -EIO;
++              return ret;
+ 
+       mutex_lock(&phydev->lock);
+       phy_read_status(phydev);
+@@ -1176,11 +1205,11 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
+               /* reset MAC */
+               ret = lan78xx_read_reg(dev, MAC_CR, &buf);
+               if (unlikely(ret < 0))
+-                      return -EIO;
++                      return ret;
+               buf |= MAC_CR_RST_;
+               ret = lan78xx_write_reg(dev, MAC_CR, buf);
+               if (unlikely(ret < 0))
+-                      return -EIO;
++                      return ret;
+ 
+               del_timer(&dev->stat_monitor);
+       } else if (link && !dev->link_on) {
+@@ -1192,18 +1221,30 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
+                       if (ecmd.base.speed == 1000) {
+                               /* disable U2 */
+                               ret = lan78xx_read_reg(dev, USB_CFG1, &buf);
++                              if (ret < 0)
++                                      return ret;
+                               buf &= ~USB_CFG1_DEV_U2_INIT_EN_;
+                               ret = lan78xx_write_reg(dev, USB_CFG1, buf);
++                              if (ret < 0)
++                                      return ret;
+                               /* enable U1 */
+                               ret = lan78xx_read_reg(dev, USB_CFG1, &buf);
++                              if (ret < 0)
++                                      return ret;
+                               buf |= USB_CFG1_DEV_U1_INIT_EN_;
+                               ret = lan78xx_write_reg(dev, USB_CFG1, buf);
++                              if (ret < 0)
++                                      return ret;
+                       } else {
+                               /* enable U1 & U2 */
+                               ret = lan78xx_read_reg(dev, USB_CFG1, &buf);
++                              if (ret < 0)
++                                      return ret;
+                               buf |= USB_CFG1_DEV_U2_INIT_EN_;
+                               buf |= USB_CFG1_DEV_U1_INIT_EN_;
+                               ret = lan78xx_write_reg(dev, USB_CFG1, buf);
++                              if (ret < 0)
++                                      return ret;
+                       }
+               }
+ 
+@@ -1221,6 +1262,8 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
+ 
+               ret = lan78xx_update_flowcontrol(dev, ecmd.base.duplex, ladv,
+                                                radv);
++              if (ret < 0)
++                      return ret;
+ 
+               if (!timer_pending(&dev->stat_monitor)) {
+                       dev->delta = 1;
+@@ -1231,7 +1274,7 @@ static int lan78xx_link_reset(struct lan78xx_net *dev)
+               tasklet_schedule(&dev->bh);
+       }
+ 
+-      return ret;
++      return 0;
+ }
+ 
+ /* some work can't be done in tasklets, so we use keventd
+@@ -1267,9 +1310,10 @@ static void lan78xx_status(struct lan78xx_net *dev, 
struct urb *urb)
+                       generic_handle_irq(dev->domain_data.phyirq);
+                       local_irq_enable();
+               }
+-      } else
++      } else {
+               netdev_warn(dev->net,
+                           "unexpected interrupt: 0x%08x\n", intdata);
++      }
+ }
+ 
+ static int lan78xx_ethtool_get_eeprom_len(struct net_device *netdev)
+@@ -1358,7 +1402,7 @@ static void lan78xx_get_wol(struct net_device *netdev,
+       struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
+ 
+       if (usb_autopm_get_interface(dev->intf) < 0)
+-                      return;
++              return;
+ 
+       ret = lan78xx_read_reg(dev, USB_CFG0, &buf);
+       if (unlikely(ret < 0)) {
+@@ -1988,7 +2032,7 @@ static int lan8835_fixup(struct phy_device *phydev)
+ 
+       /* RGMII MAC TXC Delay Enable */
+       lan78xx_write_reg(dev, MAC_RGMII_ID,
+-                              MAC_RGMII_ID_TXC_DELAY_EN_);
++                        MAC_RGMII_ID_TXC_DELAY_EN_);
+ 
+       /* RGMII TX DLL Tune Adjust */
+       lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00);
+@@ -2252,11 +2296,16 @@ static int lan78xx_change_mtu(struct net_device 
*netdev, int new_mtu)
+       int ll_mtu = new_mtu + netdev->hard_header_len;
+       int old_hard_mtu = dev->hard_mtu;
+       int old_rx_urb_size = dev->rx_urb_size;
++      int ret;
+ 
+       /* no second zero-length packet read wanted after mtu-sized packets */
+       if ((ll_mtu % dev->maxpacket) == 0)
+               return -EDOM;
+ 
++      ret = usb_autopm_get_interface(dev->intf);
++      if (ret < 0)
++              return ret;
++
+       lan78xx_set_rx_max_frame_length(dev, new_mtu + VLAN_ETH_HLEN);
+ 
+       netdev->mtu = new_mtu;
+@@ -2272,6 +2321,8 @@ static int lan78xx_change_mtu(struct net_device *netdev, 
int new_mtu)
+               }
+       }
+ 
++      usb_autopm_put_interface(dev->intf);
++
+       return 0;
+ }
+ 
+@@ -2428,26 +2479,186 @@ static void lan78xx_init_ltm(struct lan78xx_net *dev)
+       lan78xx_write_reg(dev, LTM_INACTIVE1, regs[5]);
+ }
+ 
++static int lan78xx_start_hw(struct lan78xx_net *dev, u32 reg, u32 hw_enable)
++{
++      return lan78xx_update_reg(dev, reg, hw_enable, hw_enable);
++}
++
++static int lan78xx_stop_hw(struct lan78xx_net *dev, u32 reg, u32 hw_enabled,
++                         u32 hw_disabled)
++{
++      unsigned long timeout;
++      bool stopped = true;
++      int ret;
++      u32 buf;
++
++      /* Stop the h/w block (if not already stopped) */
++
++      ret = lan78xx_read_reg(dev, reg, &buf);
++      if (ret < 0)
++              return ret;
++
++      if (buf & hw_enabled) {
++              buf &= ~hw_enabled;
++
++              ret = lan78xx_write_reg(dev, reg, buf);
++              if (ret < 0)
++                      return ret;
++
++              stopped = false;
++              timeout = jiffies + HW_DISABLE_TIMEOUT;
++              do  {
++                      ret = lan78xx_read_reg(dev, reg, &buf);
++                      if (ret < 0)
++                              return ret;
++
++                      if (buf & hw_disabled)
++                              stopped = true;
++                      else
++                              msleep(HW_DISABLE_DELAY_MS);
++              } while (!stopped && !time_after(jiffies, timeout));
++      }
++
++      ret = stopped ? 0 : -ETIME;
++
++      return ret;
++}
++
++static int lan78xx_flush_fifo(struct lan78xx_net *dev, u32 reg, u32 
fifo_flush)
++{
++      return lan78xx_update_reg(dev, reg, fifo_flush, fifo_flush);
++}
++
++static int lan78xx_start_tx_path(struct lan78xx_net *dev)
++{
++      int ret;
++
++      netif_dbg(dev, drv, dev->net, "start tx path");
++
++      /* Start the MAC transmitter */
++
++      ret = lan78xx_start_hw(dev, MAC_TX, MAC_TX_TXEN_);
++      if (ret < 0)
++              return ret;
++
++      /* Start the Tx FIFO */
++
++      ret = lan78xx_start_hw(dev, FCT_TX_CTL, FCT_TX_CTL_EN_);
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
++static int lan78xx_stop_tx_path(struct lan78xx_net *dev)
++{
++      int ret;
++
++      netif_dbg(dev, drv, dev->net, "stop tx path");
++
++      /* Stop the Tx FIFO */
++
++      ret = lan78xx_stop_hw(dev, FCT_TX_CTL, FCT_TX_CTL_EN_, FCT_TX_CTL_DIS_);
++      if (ret < 0)
++              return ret;
++
++      /* Stop the MAC transmitter */
++
++      ret = lan78xx_stop_hw(dev, MAC_TX, MAC_TX_TXEN_, MAC_TX_TXD_);
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
++/* The caller must ensure the Tx path is stopped before calling
++ * lan78xx_flush_tx_fifo().
++ */
++static int lan78xx_flush_tx_fifo(struct lan78xx_net *dev)
++{
++      return lan78xx_flush_fifo(dev, FCT_TX_CTL, FCT_TX_CTL_RST_);
++}
++
++static int lan78xx_start_rx_path(struct lan78xx_net *dev)
++{
++      int ret;
++
++      netif_dbg(dev, drv, dev->net, "start rx path");
++
++      /* Start the Rx FIFO */
++
++      ret = lan78xx_start_hw(dev, FCT_RX_CTL, FCT_RX_CTL_EN_);
++      if (ret < 0)
++              return ret;
++
++      /* Start the MAC receiver*/
++
++      ret = lan78xx_start_hw(dev, MAC_RX, MAC_RX_RXEN_);
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
++static int lan78xx_stop_rx_path(struct lan78xx_net *dev)
++{
++      int ret;
++
++      netif_dbg(dev, drv, dev->net, "stop rx path");
++
++      /* Stop the MAC receiver */
++
++      ret = lan78xx_stop_hw(dev, MAC_RX, MAC_RX_RXEN_, MAC_RX_RXD_);
++      if (ret < 0)
++              return ret;
++
++      /* Stop the Rx FIFO */
++
++      ret = lan78xx_stop_hw(dev, FCT_RX_CTL, FCT_RX_CTL_EN_, FCT_RX_CTL_DIS_);
++      if (ret < 0)
++              return ret;
++
++      return 0;
++}
++
++/* The caller must ensure the Rx path is stopped before calling
++ * lan78xx_flush_rx_fifo().
++ */
++static int lan78xx_flush_rx_fifo(struct lan78xx_net *dev)
++{
++      return lan78xx_flush_fifo(dev, FCT_RX_CTL, FCT_RX_CTL_RST_);
++}
++
+ static int lan78xx_reset(struct lan78xx_net *dev)
+ {
+       struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
+-      u32 buf;
+-      int ret = 0;
+       unsigned long timeout;
++      int ret;
++      u32 buf;
+       u8 sig;
+ 
+       ret = lan78xx_read_reg(dev, HW_CFG, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= HW_CFG_LRST_;
++
+       ret = lan78xx_write_reg(dev, HW_CFG, buf);
++      if (ret < 0)
++              return ret;
+ 
+       timeout = jiffies + HZ;
+       do {
+               mdelay(1);
+               ret = lan78xx_read_reg(dev, HW_CFG, &buf);
++              if (ret < 0)
++                      return ret;
++
+               if (time_after(jiffies, timeout)) {
+                       netdev_warn(dev->net,
+                                   "timeout on completion of LiteReset");
+-                      return -EIO;
++                      ret = -ETIMEDOUT;
++                      return ret;
+               }
+       } while (buf & HW_CFG_LRST_);
+ 
+@@ -2455,13 +2666,22 @@ static int lan78xx_reset(struct lan78xx_net *dev)
+ 
+       /* save DEVID for later usage */
+       ret = lan78xx_read_reg(dev, ID_REV, &buf);
++      if (ret < 0)
++              return ret;
++
+       dev->chipid = (buf & ID_REV_CHIP_ID_MASK_) >> 16;
+       dev->chiprev = buf & ID_REV_CHIP_REV_MASK_;
+ 
+       /* Respond to the IN token with a NAK */
+       ret = lan78xx_read_reg(dev, USB_CFG0, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= USB_CFG_BIR_;
++
+       ret = lan78xx_write_reg(dev, USB_CFG0, buf);
++      if (ret < 0)
++              return ret;
+ 
+       /* Init LTM */
+       lan78xx_init_ltm(dev);
+@@ -2484,53 +2704,105 @@ static int lan78xx_reset(struct lan78xx_net *dev)
+       }
+ 
+       ret = lan78xx_write_reg(dev, BURST_CAP, buf);
++      if (ret < 0)
++              return ret;
++
+       ret = lan78xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
++      if (ret < 0)
++              return ret;
+ 
+       ret = lan78xx_read_reg(dev, HW_CFG, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= HW_CFG_MEF_;
++
+       ret = lan78xx_write_reg(dev, HW_CFG, buf);
++      if (ret < 0)
++              return ret;
+ 
+       ret = lan78xx_read_reg(dev, USB_CFG0, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= USB_CFG_BCE_;
++
+       ret = lan78xx_write_reg(dev, USB_CFG0, buf);
++      if (ret < 0)
++              return ret;
+ 
+       /* set FIFO sizes */
+       buf = (MAX_RX_FIFO_SIZE - 512) / 512;
++
+       ret = lan78xx_write_reg(dev, FCT_RX_FIFO_END, buf);
++      if (ret < 0)
++              return ret;
+ 
+       buf = (MAX_TX_FIFO_SIZE - 512) / 512;
++
+       ret = lan78xx_write_reg(dev, FCT_TX_FIFO_END, buf);
++      if (ret < 0)
++              return ret;
+ 
+       ret = lan78xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
++      if (ret < 0)
++              return ret;
++
+       ret = lan78xx_write_reg(dev, FLOW, 0);
++      if (ret < 0)
++              return ret;
++
+       ret = lan78xx_write_reg(dev, FCT_FLOW, 0);
++      if (ret < 0)
++              return ret;
+ 
+       /* Don't need rfe_ctl_lock during initialisation */
+       ret = lan78xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl);
++      if (ret < 0)
++              return ret;
++
+       pdata->rfe_ctl |= RFE_CTL_BCAST_EN_ | RFE_CTL_DA_PERFECT_;
++
+       ret = lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
++      if (ret < 0)
++              return ret;
+ 
+       /* Enable or disable checksum offload engines */
+-      lan78xx_set_features(dev->net, dev->net->features);
++      ret = lan78xx_set_features(dev->net, dev->net->features);
++      if (ret < 0)
++              return ret;
+ 
+       lan78xx_set_multicast(dev->net);
+ 
+       /* reset PHY */
+       ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= PMT_CTL_PHY_RST_;
++
+       ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++      if (ret < 0)
++              return ret;
+ 
+       timeout = jiffies + HZ;
+       do {
+               mdelay(1);
+               ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++              if (ret < 0)
++                      return ret;
++
+               if (time_after(jiffies, timeout)) {
+                       netdev_warn(dev->net, "timeout waiting for PHY Reset");
+-                      return -EIO;
++                      ret = -ETIMEDOUT;
++                      return ret;
+               }
+       } while ((buf & PMT_CTL_PHY_RST_) || !(buf & PMT_CTL_READY_));
+ 
+       ret = lan78xx_read_reg(dev, MAC_CR, &buf);
++      if (ret < 0)
++              return ret;
++
+       /* LAN7801 only has RGMII mode */
+       if (dev->chipid == ID_REV_CHIP_ID_7801_)
+               buf &= ~MAC_CR_GMII_EN_;
+@@ -2545,27 +2817,13 @@ static int lan78xx_reset(struct lan78xx_net *dev)
+               }
+       }
+       ret = lan78xx_write_reg(dev, MAC_CR, buf);
+-
+-      ret = lan78xx_read_reg(dev, MAC_TX, &buf);
+-      buf |= MAC_TX_TXEN_;
+-      ret = lan78xx_write_reg(dev, MAC_TX, buf);
+-
+-      ret = lan78xx_read_reg(dev, FCT_TX_CTL, &buf);
+-      buf |= FCT_TX_CTL_EN_;
+-      ret = lan78xx_write_reg(dev, FCT_TX_CTL, buf);
++      if (ret < 0)
++              return ret;
+ 
+       ret = lan78xx_set_rx_max_frame_length(dev,
+                                             dev->net->mtu + VLAN_ETH_HLEN);
+ 
+-      ret = lan78xx_read_reg(dev, MAC_RX, &buf);
+-      buf |= MAC_RX_RXEN_;
+-      ret = lan78xx_write_reg(dev, MAC_RX, buf);
+-
+-      ret = lan78xx_read_reg(dev, FCT_RX_CTL, &buf);
+-      buf |= FCT_RX_CTL_EN_;
+-      ret = lan78xx_write_reg(dev, FCT_RX_CTL, buf);
+-
+-      return 0;
++      return ret;
+ }
+ 
+ static void lan78xx_init_stats(struct lan78xx_net *dev)
+@@ -2599,9 +2857,13 @@ static int lan78xx_open(struct net_device *net)
+       struct lan78xx_net *dev = netdev_priv(net);
+       int ret;
+ 
++      netif_dbg(dev, ifup, dev->net, "open device");
++
+       ret = usb_autopm_get_interface(dev->intf);
+       if (ret < 0)
+-              goto out;
++              return ret;
++
++      mutex_lock(&dev->dev_mutex);
+ 
+       phy_start(net->phydev);
+ 
+@@ -2617,6 +2879,20 @@ static int lan78xx_open(struct net_device *net)
+               }
+       }
+ 
++      ret = lan78xx_flush_rx_fifo(dev);
++      if (ret < 0)
++              goto done;
++      ret = lan78xx_flush_tx_fifo(dev);
++      if (ret < 0)
++              goto done;
++
++      ret = lan78xx_start_tx_path(dev);
++      if (ret < 0)
++              goto done;
++      ret = lan78xx_start_rx_path(dev);
++      if (ret < 0)
++              goto done;
++
+       lan78xx_init_stats(dev);
+ 
+       set_bit(EVENT_DEV_OPEN, &dev->flags);
+@@ -2627,9 +2903,11 @@ static int lan78xx_open(struct net_device *net)
+ 
+       lan78xx_defer_kevent(dev, EVENT_LINK_RESET);
+ done:
+-      usb_autopm_put_interface(dev->intf);
++      mutex_unlock(&dev->dev_mutex);
++
++      if (ret < 0)
++              usb_autopm_put_interface(dev->intf);
+ 
+-out:
+       return ret;
+ }
+ 
+@@ -2646,38 +2924,56 @@ static void lan78xx_terminate_urbs(struct lan78xx_net 
*dev)
+       temp = unlink_urbs(dev, &dev->txq) + unlink_urbs(dev, &dev->rxq);
+ 
+       /* maybe wait for deletions to finish. */
+-      while (!skb_queue_empty(&dev->rxq) &&
+-             !skb_queue_empty(&dev->txq) &&
+-             !skb_queue_empty(&dev->done)) {
++      while (!skb_queue_empty(&dev->rxq) ||
++             !skb_queue_empty(&dev->txq)) {
+               schedule_timeout(msecs_to_jiffies(UNLINK_TIMEOUT_MS));
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               netif_dbg(dev, ifdown, dev->net,
+-                        "waited for %d urb completions\n", temp);
++                        "waited for %d urb completions", temp);
+       }
+       set_current_state(TASK_RUNNING);
+       dev->wait = NULL;
+       remove_wait_queue(&unlink_wakeup, &wait);
++
++      while (!skb_queue_empty(&dev->done)) {
++              struct skb_data *entry;
++              struct sk_buff *skb;
++
++              skb = skb_dequeue(&dev->done);
++              entry = (struct skb_data *)(skb->cb);
++              usb_free_urb(entry->urb);
++              dev_kfree_skb(skb);
++      }
+ }
+ 
+ static int lan78xx_stop(struct net_device *net)
+ {
+       struct lan78xx_net *dev = netdev_priv(net);
+ 
++      netif_dbg(dev, ifup, dev->net, "stop device");
++
++      mutex_lock(&dev->dev_mutex);
++
+       if (timer_pending(&dev->stat_monitor))
+               del_timer_sync(&dev->stat_monitor);
+ 
+-      if (net->phydev)
+-              phy_stop(net->phydev);
+-
+       clear_bit(EVENT_DEV_OPEN, &dev->flags);
+       netif_stop_queue(net);
++      tasklet_kill(&dev->bh);
++
++      lan78xx_terminate_urbs(dev);
+ 
+       netif_info(dev, ifdown, dev->net,
+                  "stop stats: rx/tx %lu/%lu, errs %lu/%lu\n",
+                  net->stats.rx_packets, net->stats.tx_packets,
+                  net->stats.rx_errors, net->stats.tx_errors);
+ 
+-      lan78xx_terminate_urbs(dev);
++      /* ignore errors that occur stopping the Tx and Rx data paths */
++      lan78xx_stop_tx_path(dev);
++      lan78xx_stop_rx_path(dev);
++
++      if (net->phydev)
++              phy_stop(net->phydev);
+ 
+       usb_kill_urb(dev->urb_intr);
+ 
+@@ -2687,12 +2983,17 @@ static int lan78xx_stop(struct net_device *net)
+        * can't flush_scheduled_work() until we drop rtnl (later),
+        * else workers could deadlock; so make workers a NOP.
+        */
+-      dev->flags = 0;
++      clear_bit(EVENT_TX_HALT, &dev->flags);
++      clear_bit(EVENT_RX_HALT, &dev->flags);
++      clear_bit(EVENT_LINK_RESET, &dev->flags);
++      clear_bit(EVENT_STAT_UPDATE, &dev->flags);
++
+       cancel_delayed_work_sync(&dev->wq);
+-      tasklet_kill(&dev->bh);
+ 
+       usb_autopm_put_interface(dev->intf);
+ 
++      mutex_unlock(&dev->dev_mutex);
++
+       return 0;
+ }
+ 
+@@ -2815,6 +3116,9 @@ lan78xx_start_xmit(struct sk_buff *skb, struct 
net_device *net)
+       struct lan78xx_net *dev = netdev_priv(net);
+       struct sk_buff *skb2 = NULL;
+ 
++      if (test_bit(EVENT_DEV_ASLEEP, &dev->flags))
++              schedule_delayed_work(&dev->wq, 0);
++
+       if (skb) {
+               skb_tx_timestamp(skb);
+               skb2 = lan78xx_tx_prep(dev, skb, GFP_ATOMIC);
+@@ -3342,9 +3646,10 @@ static void lan78xx_tx_bh(struct lan78xx_net *dev)
+               if (skb)
+                       dev_kfree_skb_any(skb);
+               usb_free_urb(urb);
+-      } else
++      } else {
+               netif_dbg(dev, tx_queued, dev->net,
+                         "> tx, len %d, type 0x%x\n", length, skb->protocol);
++      }
+ }
+ 
+ static void lan78xx_rx_bh(struct lan78xx_net *dev)
+@@ -3420,18 +3725,17 @@ static void lan78xx_delayedwork(struct work_struct 
*work)
+ 
+       dev = container_of(work, struct lan78xx_net, wq.work);
+ 
++      if (usb_autopm_get_interface(dev->intf) < 0)
++              return;
++
+       if (test_bit(EVENT_TX_HALT, &dev->flags)) {
+               unlink_urbs(dev, &dev->txq);
+-              status = usb_autopm_get_interface(dev->intf);
+-              if (status < 0)
+-                      goto fail_pipe;
++
+               status = usb_clear_halt(dev->udev, dev->pipe_out);
+-              usb_autopm_put_interface(dev->intf);
+               if (status < 0 &&
+                   status != -EPIPE &&
+                   status != -ESHUTDOWN) {
+                       if (netif_msg_tx_err(dev))
+-fail_pipe:
+                               netdev_err(dev->net,
+                                          "can't clear tx halt, status %d\n",
+                                          status);
+@@ -3441,18 +3745,14 @@ static void lan78xx_delayedwork(struct work_struct 
*work)
+                               netif_wake_queue(dev->net);
+               }
+       }
++
+       if (test_bit(EVENT_RX_HALT, &dev->flags)) {
+               unlink_urbs(dev, &dev->rxq);
+-              status = usb_autopm_get_interface(dev->intf);
+-              if (status < 0)
+-                              goto fail_halt;
+               status = usb_clear_halt(dev->udev, dev->pipe_in);
+-              usb_autopm_put_interface(dev->intf);
+               if (status < 0 &&
+                   status != -EPIPE &&
+                   status != -ESHUTDOWN) {
+                       if (netif_msg_rx_err(dev))
+-fail_halt:
+                               netdev_err(dev->net,
+                                          "can't clear rx halt, status %d\n",
+                                          status);
+@@ -3466,16 +3766,9 @@ static void lan78xx_delayedwork(struct work_struct 
*work)
+               int ret = 0;
+ 
+               clear_bit(EVENT_LINK_RESET, &dev->flags);
+-              status = usb_autopm_get_interface(dev->intf);
+-              if (status < 0)
+-                      goto skip_reset;
+               if (lan78xx_link_reset(dev) < 0) {
+-                      usb_autopm_put_interface(dev->intf);
+-skip_reset:
+                       netdev_info(dev->net, "link reset failed (%d)\n",
+                                   ret);
+-              } else {
+-                      usb_autopm_put_interface(dev->intf);
+               }
+       }
+ 
+@@ -3489,6 +3782,8 @@ static void lan78xx_delayedwork(struct work_struct *work)
+ 
+               dev->delta = min((dev->delta * 2), 50);
+       }
++
++      usb_autopm_put_interface(dev->intf);
+ }
+ 
+ static void intr_complete(struct urb *urb)
+@@ -3618,8 +3913,8 @@ static int lan78xx_probe(struct usb_interface *intf,
+       struct net_device *netdev;
+       struct usb_device *udev;
+       int ret;
+-      unsigned maxp;
+-      unsigned period;
++      unsigned int maxp;
++      unsigned int period;
+       u8 *buf = NULL;
+ 
+       udev = interface_to_usbdev(intf);
+@@ -3648,6 +3943,7 @@ static int lan78xx_probe(struct usb_interface *intf,
+       skb_queue_head_init(&dev->rxq_pause);
+       skb_queue_head_init(&dev->txq_pend);
+       mutex_init(&dev->phy_mutex);
++      mutex_init(&dev->dev_mutex);
+ 
+       tasklet_init(&dev->bh, lan78xx_bh, (unsigned long)dev);
+       INIT_DELAYED_WORK(&dev->wq, lan78xx_delayedwork);
+@@ -3790,37 +4086,119 @@ static u16 lan78xx_wakeframe_crc16(const u8 *buf, int 
len)
+       return crc;
+ }
+ 
+-static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
++static int lan78xx_set_auto_suspend(struct lan78xx_net *dev)
+ {
+       u32 buf;
+-      int mask_index;
+-      u16 crc;
+-      u32 temp_wucsr;
+-      u32 temp_pmt_ctl;
++      int ret;
++
++      ret = lan78xx_stop_tx_path(dev);
++      if (ret < 0)
++              return ret;
++
++      ret = lan78xx_stop_rx_path(dev);
++      if (ret < 0)
++              return ret;
++
++      /* auto suspend (selective suspend) */
++
++      ret = lan78xx_write_reg(dev, WUCSR, 0);
++      if (ret < 0)
++              return ret;
++      ret = lan78xx_write_reg(dev, WUCSR2, 0);
++      if (ret < 0)
++              return ret;
++      ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
++      if (ret < 0)
++              return ret;
++
++      /* set goodframe wakeup */
++
++      ret = lan78xx_read_reg(dev, WUCSR, &buf);
++      if (ret < 0)
++              return ret;
++
++      buf |= WUCSR_RFE_WAKE_EN_;
++      buf |= WUCSR_STORE_WAKE_;
++
++      ret = lan78xx_write_reg(dev, WUCSR, buf);
++      if (ret < 0)
++              return ret;
++
++      ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++      if (ret < 0)
++              return ret;
++
++      buf &= ~PMT_CTL_RES_CLR_WKP_EN_;
++      buf |= PMT_CTL_RES_CLR_WKP_STS_;
++      buf |= PMT_CTL_PHY_WAKE_EN_;
++      buf |= PMT_CTL_WOL_EN_;
++      buf &= ~PMT_CTL_SUS_MODE_MASK_;
++      buf |= PMT_CTL_SUS_MODE_3_;
++
++      ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++      if (ret < 0)
++              return ret;
++
++      ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++      if (ret < 0)
++              return ret;
++
++      buf |= PMT_CTL_WUPS_MASK_;
++
++      ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++      if (ret < 0)
++              return ret;
++
++      ret = lan78xx_start_rx_path(dev);
++
++      return ret;
++}
++
++static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
++{
+       const u8 ipv4_multicast[3] = { 0x01, 0x00, 0x5E };
+       const u8 ipv6_multicast[3] = { 0x33, 0x33 };
+       const u8 arp_type[2] = { 0x08, 0x06 };
++      u32 temp_pmt_ctl;
++      int mask_index;
++      u32 temp_wucsr;
++      u32 buf;
++      u16 crc;
++      int ret;
+ 
+-      lan78xx_read_reg(dev, MAC_TX, &buf);
+-      buf &= ~MAC_TX_TXEN_;
+-      lan78xx_write_reg(dev, MAC_TX, buf);
+-      lan78xx_read_reg(dev, MAC_RX, &buf);
+-      buf &= ~MAC_RX_RXEN_;
+-      lan78xx_write_reg(dev, MAC_RX, buf);
++      ret = lan78xx_stop_tx_path(dev);
++      if (ret < 0)
++              return ret;
++      ret = lan78xx_stop_rx_path(dev);
++      if (ret < 0)
++              return ret;
+ 
+-      lan78xx_write_reg(dev, WUCSR, 0);
+-      lan78xx_write_reg(dev, WUCSR2, 0);
+-      lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
++      ret = lan78xx_write_reg(dev, WUCSR, 0);
++      if (ret < 0)
++              return ret;
++      ret = lan78xx_write_reg(dev, WUCSR2, 0);
++      if (ret < 0)
++              return ret;
++      ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
++      if (ret < 0)
++              return ret;
+ 
+       temp_wucsr = 0;
+ 
+       temp_pmt_ctl = 0;
+-      lan78xx_read_reg(dev, PMT_CTL, &temp_pmt_ctl);
++
++      ret = lan78xx_read_reg(dev, PMT_CTL, &temp_pmt_ctl);
++      if (ret < 0)
++              return ret;
++
+       temp_pmt_ctl &= ~PMT_CTL_RES_CLR_WKP_EN_;
+       temp_pmt_ctl |= PMT_CTL_RES_CLR_WKP_STS_;
+ 
+-      for (mask_index = 0; mask_index < NUM_OF_WUF_CFG; mask_index++)
+-              lan78xx_write_reg(dev, WUF_CFG(mask_index), 0);
++      for (mask_index = 0; mask_index < NUM_OF_WUF_CFG; mask_index++) {
++              ret = lan78xx_write_reg(dev, WUF_CFG(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++      }
+ 
+       mask_index = 0;
+       if (wol & WAKE_PHY) {
+@@ -3849,30 +4227,52 @@ static int lan78xx_set_suspend(struct lan78xx_net 
*dev, u32 wol)
+ 
+               /* set WUF_CFG & WUF_MASK for IPv4 Multicast */
+               crc = lan78xx_wakeframe_crc16(ipv4_multicast, 3);
+-              lan78xx_write_reg(dev, WUF_CFG(mask_index),
++              ret = lan78xx_write_reg(dev, WUF_CFG(mask_index),
+                                       WUF_CFGX_EN_ |
+                                       WUF_CFGX_TYPE_MCAST_ |
+                                       (0 << WUF_CFGX_OFFSET_SHIFT_) |
+                                       (crc & WUF_CFGX_CRC16_MASK_));
++              if (ret < 0)
++                      return ret;
++
++              ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 7);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
++              if (ret < 0)
++                      return ret;
+ 
+-              lan78xx_write_reg(dev, WUF_MASK0(mask_index), 7);
+-              lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+-              lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
+-              lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
+               mask_index++;
+ 
+               /* for IPv6 Multicast */
+               crc = lan78xx_wakeframe_crc16(ipv6_multicast, 2);
+-              lan78xx_write_reg(dev, WUF_CFG(mask_index),
++              ret = lan78xx_write_reg(dev, WUF_CFG(mask_index),
+                                       WUF_CFGX_EN_ |
+                                       WUF_CFGX_TYPE_MCAST_ |
+                                       (0 << WUF_CFGX_OFFSET_SHIFT_) |
+                                       (crc & WUF_CFGX_CRC16_MASK_));
++              if (ret < 0)
++                      return ret;
++
++              ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 3);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
++              if (ret < 0)
++                      return ret;
+ 
+-              lan78xx_write_reg(dev, WUF_MASK0(mask_index), 3);
+-              lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+-              lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
+-              lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
+               mask_index++;
+ 
+               temp_pmt_ctl |= PMT_CTL_WOL_EN_;
+@@ -3893,16 +4293,27 @@ static int lan78xx_set_suspend(struct lan78xx_net 
*dev, u32 wol)
+                * for packettype (offset 12,13) = ARP (0x0806)
+                */
+               crc = lan78xx_wakeframe_crc16(arp_type, 2);
+-              lan78xx_write_reg(dev, WUF_CFG(mask_index),
++              ret = lan78xx_write_reg(dev, WUF_CFG(mask_index),
+                                       WUF_CFGX_EN_ |
+                                       WUF_CFGX_TYPE_ALL_ |
+                                       (0 << WUF_CFGX_OFFSET_SHIFT_) |
+                                       (crc & WUF_CFGX_CRC16_MASK_));
++              if (ret < 0)
++                      return ret;
++
++              ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 0x3000);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
++              if (ret < 0)
++                      return ret;
++              ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
++              if (ret < 0)
++                      return ret;
+ 
+-              lan78xx_write_reg(dev, WUF_MASK0(mask_index), 0x3000);
+-              lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+-              lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
+-              lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
+               mask_index++;
+ 
+               temp_pmt_ctl |= PMT_CTL_WOL_EN_;
+@@ -3910,7 +4321,9 @@ static int lan78xx_set_suspend(struct lan78xx_net *dev, 
u32 wol)
+               temp_pmt_ctl |= PMT_CTL_SUS_MODE_0_;
+       }
+ 
+-      lan78xx_write_reg(dev, WUCSR, temp_wucsr);
++      ret = lan78xx_write_reg(dev, WUCSR, temp_wucsr);
++      if (ret < 0)
++              return ret;
+ 
+       /* when multiple WOL bits are set */
+       if (hweight_long((unsigned long)wol) > 1) {
+@@ -3918,36 +4331,48 @@ static int lan78xx_set_suspend(struct lan78xx_net 
*dev, u32 wol)
+               temp_pmt_ctl &= ~PMT_CTL_SUS_MODE_MASK_;
+               temp_pmt_ctl |= PMT_CTL_SUS_MODE_0_;
+       }
+-      lan78xx_write_reg(dev, PMT_CTL, temp_pmt_ctl);
++      ret = lan78xx_write_reg(dev, PMT_CTL, temp_pmt_ctl);
++      if (ret < 0)
++              return ret;
+ 
+       /* clear WUPS */
+-      lan78xx_read_reg(dev, PMT_CTL, &buf);
++      ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++      if (ret < 0)
++              return ret;
++
+       buf |= PMT_CTL_WUPS_MASK_;
+-      lan78xx_write_reg(dev, PMT_CTL, buf);
+ 
+-      lan78xx_read_reg(dev, MAC_RX, &buf);
+-      buf |= MAC_RX_RXEN_;
+-      lan78xx_write_reg(dev, MAC_RX, buf);
++      ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++      if (ret < 0)
++              return ret;
+ 
+-      return 0;
++      ret = lan78xx_start_rx_path(dev);
++
++      return ret;
+ }
+ 
+ static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
+ {
+       struct lan78xx_net *dev = usb_get_intfdata(intf);
+-      struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
+-      u32 buf;
++      bool dev_open;
+       int ret;
+       int event;
+ 
+       event = message.event;
+ 
+-      if (!dev->suspend_count++) {
++      mutex_lock(&dev->dev_mutex);
++
++      netif_dbg(dev, ifdown, dev->net,
++                "suspending: pm event %#x", message.event);
++
++      dev_open = test_bit(EVENT_DEV_OPEN, &dev->flags);
++
++      if (dev_open) {
+               spin_lock_irq(&dev->txq.lock);
+               /* don't autosuspend while transmitting */
+               if ((skb_queue_len(&dev->txq) ||
+                    skb_queue_len(&dev->txq_pend)) &&
+-                      PMSG_IS_AUTO(message)) {
++                  PMSG_IS_AUTO(message)) {
+                       spin_unlock_irq(&dev->txq.lock);
+                       ret = -EBUSY;
+                       goto out;
+@@ -3956,129 +4381,207 @@ static int lan78xx_suspend(struct usb_interface 
*intf, pm_message_t message)
+                       spin_unlock_irq(&dev->txq.lock);
+               }
+ 
+-              /* stop TX & RX */
+-              ret = lan78xx_read_reg(dev, MAC_TX, &buf);
+-              buf &= ~MAC_TX_TXEN_;
+-              ret = lan78xx_write_reg(dev, MAC_TX, buf);
+-              ret = lan78xx_read_reg(dev, MAC_RX, &buf);
+-              buf &= ~MAC_RX_RXEN_;
+-              ret = lan78xx_write_reg(dev, MAC_RX, buf);
++              /* stop RX */
++              ret = lan78xx_stop_rx_path(dev);
++              if (ret < 0)
++                      goto out;
++
++              ret = lan78xx_flush_rx_fifo(dev);
++              if (ret < 0)
++                      goto out;
+ 
+-              /* empty out the rx and queues */
++              /* stop Tx */
++              ret = lan78xx_stop_tx_path(dev);
++              if (ret < 0)
++                      goto out;
++
++              /* empty out the Rx and Tx queues */
+               netif_device_detach(dev->net);
+               lan78xx_terminate_urbs(dev);
+               usb_kill_urb(dev->urb_intr);
+ 
+               /* reattach */
+               netif_device_attach(dev->net);
+-      }
+ 
+-      if (test_bit(EVENT_DEV_ASLEEP, &dev->flags)) {
+               del_timer(&dev->stat_monitor);
+ 
+               if (PMSG_IS_AUTO(message)) {
+-                      /* auto suspend (selective suspend) */
+-                      ret = lan78xx_read_reg(dev, MAC_TX, &buf);
+-                      buf &= ~MAC_TX_TXEN_;
+-                      ret = lan78xx_write_reg(dev, MAC_TX, buf);
+-                      ret = lan78xx_read_reg(dev, MAC_RX, &buf);
+-                      buf &= ~MAC_RX_RXEN_;
+-                      ret = lan78xx_write_reg(dev, MAC_RX, buf);
++                      ret = lan78xx_set_auto_suspend(dev);
++                      if (ret < 0)
++                              goto out;
++              } else {
++                      struct lan78xx_priv *pdata;
++
++                      pdata = (struct lan78xx_priv *)(dev->data[0]);
++                      netif_carrier_off(dev->net);
++                      ret = lan78xx_set_suspend(dev, pdata->wol);
++                      if (ret < 0)
++                              goto out;
++              }
++      } else {
++              /* Interface is down; don't allow WOL and PHY
++               * events to wake up the host
++               */
++              u32 buf;
+ 
+-                      ret = lan78xx_write_reg(dev, WUCSR, 0);
+-                      ret = lan78xx_write_reg(dev, WUCSR2, 0);
+-                      ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
++              set_bit(EVENT_DEV_ASLEEP, &dev->flags);
+ 
+-                      /* set goodframe wakeup */
+-                      ret = lan78xx_read_reg(dev, WUCSR, &buf);
++              ret = lan78xx_write_reg(dev, WUCSR, 0);
++              if (ret < 0)
++                      goto out;
++              ret = lan78xx_write_reg(dev, WUCSR2, 0);
++              if (ret < 0)
++                      goto out;
+ 
+-                      buf |= WUCSR_RFE_WAKE_EN_;
+-                      buf |= WUCSR_STORE_WAKE_;
++              ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++              if (ret < 0)
++                      goto out;
+ 
+-                      ret = lan78xx_write_reg(dev, WUCSR, buf);
++              buf &= ~PMT_CTL_RES_CLR_WKP_EN_;
++              buf |= PMT_CTL_RES_CLR_WKP_STS_;
++              buf &= ~PMT_CTL_SUS_MODE_MASK_;
++              buf |= PMT_CTL_SUS_MODE_3_;
+ 
+-                      ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++              ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++              if (ret < 0)
++                      goto out;
+ 
+-                      buf &= ~PMT_CTL_RES_CLR_WKP_EN_;
+-                      buf |= PMT_CTL_RES_CLR_WKP_STS_;
++              ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++              if (ret < 0)
++                      goto out;
+ 
+-                      buf |= PMT_CTL_PHY_WAKE_EN_;
+-                      buf |= PMT_CTL_WOL_EN_;
+-                      buf &= ~PMT_CTL_SUS_MODE_MASK_;
+-                      buf |= PMT_CTL_SUS_MODE_3_;
++              buf |= PMT_CTL_WUPS_MASK_;
+ 
+-                      ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++              ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++              if (ret < 0)
++                      goto out;
++      }
+ 
+-                      ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
++      ret = 0;
++out:
++      mutex_unlock(&dev->dev_mutex);
+ 
+-                      buf |= PMT_CTL_WUPS_MASK_;
++      return ret;
++}
+ 
+-                      ret = lan78xx_write_reg(dev, PMT_CTL, buf);
++static bool lan78xx_submit_deferred_urbs(struct lan78xx_net *dev)
++{
++      bool pipe_halted = false;
++      struct urb *urb;
+ 
+-                      ret = lan78xx_read_reg(dev, MAC_RX, &buf);
+-                      buf |= MAC_RX_RXEN_;
+-                      ret = lan78xx_write_reg(dev, MAC_RX, buf);
++      while ((urb = usb_get_from_anchor(&dev->deferred))) {
++              struct sk_buff *skb = urb->context;
++              int ret;
++
++              if (!netif_device_present(dev->net) ||
++                  !netif_carrier_ok(dev->net) ||
++                  pipe_halted) {
++                      usb_free_urb(urb);
++                      dev_kfree_skb(skb);
++                      continue;
++              }
++
++              ret = usb_submit_urb(urb, GFP_ATOMIC);
++
++              if (ret == 0) {
++                      netif_trans_update(dev->net);
++                      lan78xx_queue_skb(&dev->txq, skb, tx_start);
+               } else {
+-                      lan78xx_set_suspend(dev, pdata->wol);
++                      usb_free_urb(urb);
++                      dev_kfree_skb(skb);
++
++                      if (ret == -EPIPE) {
++                              netif_stop_queue(dev->net);
++                              pipe_halted = true;
++                      } else if (ret == -ENODEV) {
++                              netif_device_detach(dev->net);
++                      }
+               }
+       }
+ 
+-      ret = 0;
+-out:
+-      return ret;
++      return pipe_halted;
+ }
+ 
+ static int lan78xx_resume(struct usb_interface *intf)
+ {
+       struct lan78xx_net *dev = usb_get_intfdata(intf);
+-      struct sk_buff *skb;
+-      struct urb *res;
++      bool dev_open;
+       int ret;
+-      u32 buf;
+ 
+-      if (!timer_pending(&dev->stat_monitor)) {
+-              dev->delta = 1;
+-              mod_timer(&dev->stat_monitor,
+-                        jiffies + STAT_UPDATE_TIMER);
+-      }
++      mutex_lock(&dev->dev_mutex);
+ 
+-      if (!--dev->suspend_count) {
+-              /* resume interrupt URBs */
+-              if (dev->urb_intr && test_bit(EVENT_DEV_OPEN, &dev->flags))
+-                              usb_submit_urb(dev->urb_intr, GFP_NOIO);
++      netif_dbg(dev, ifup, dev->net, "resuming device");
++
++      dev_open = test_bit(EVENT_DEV_OPEN, &dev->flags);
++
++      if (dev_open) {
++              bool pipe_halted = false;
++
++              ret = lan78xx_flush_tx_fifo(dev);
++              if (ret < 0)
++                      goto out;
++
++              if (dev->urb_intr) {
++                      int ret = usb_submit_urb(dev->urb_intr, GFP_KERNEL);
+ 
+-              spin_lock_irq(&dev->txq.lock);
+-              while ((res = usb_get_from_anchor(&dev->deferred))) {
+-                      skb = (struct sk_buff *)res->context;
+-                      ret = usb_submit_urb(res, GFP_ATOMIC);
+                       if (ret < 0) {
+-                              dev_kfree_skb_any(skb);
+-                              usb_free_urb(res);
+-                              usb_autopm_put_interface_async(dev->intf);
+-                      } else {
+-                              netif_trans_update(dev->net);
+-                              lan78xx_queue_skb(&dev->txq, skb, tx_start);
++                              if (ret == -ENODEV)
++                                      netif_device_detach(dev->net);
++
++                      netdev_warn(dev->net, "Failed to submit intr URB");
+                       }
+               }
+ 
++              spin_lock_irq(&dev->txq.lock);
++
++              if (netif_device_present(dev->net)) {
++                      pipe_halted = lan78xx_submit_deferred_urbs(dev);
++
++                      if (pipe_halted)
++                              lan78xx_defer_kevent(dev, EVENT_TX_HALT);
++              }
++
+               clear_bit(EVENT_DEV_ASLEEP, &dev->flags);
++
+               spin_unlock_irq(&dev->txq.lock);
+ 
+-              if (test_bit(EVENT_DEV_OPEN, &dev->flags)) {
+-                      if (!(skb_queue_len(&dev->txq) >= dev->tx_qlen))
+-                              netif_start_queue(dev->net);
+-                      tasklet_schedule(&dev->bh);
++              if (!pipe_halted &&
++                  netif_device_present(dev->net) &&
++                  (skb_queue_len(&dev->txq) < dev->tx_qlen))
++                      netif_start_queue(dev->net);
++
++              ret = lan78xx_start_tx_path(dev);
++              if (ret < 0)
++                      goto out;
++
++              tasklet_schedule(&dev->bh);
++
++              if (!timer_pending(&dev->stat_monitor)) {
++                      dev->delta = 1;
++                      mod_timer(&dev->stat_monitor,
++                                jiffies + STAT_UPDATE_TIMER);
+               }
++
++      } else {
++              clear_bit(EVENT_DEV_ASLEEP, &dev->flags);
+       }
+ 
+       ret = lan78xx_write_reg(dev, WUCSR2, 0);
++      if (ret < 0)
++              goto out;
+       ret = lan78xx_write_reg(dev, WUCSR, 0);
++      if (ret < 0)
++              goto out;
+       ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
++      if (ret < 0)
++              goto out;
+ 
+       ret = lan78xx_write_reg(dev, WUCSR2, WUCSR2_NS_RCD_ |
+                                            WUCSR2_ARP_RCD_ |
+                                            WUCSR2_IPV6_TCPSYN_RCD_ |
+                                            WUCSR2_IPV4_TCPSYN_RCD_);
++      if (ret < 0)
++              goto out;
+ 
+       ret = lan78xx_write_reg(dev, WUCSR, WUCSR_EEE_TX_WAKE_ |
+                                           WUCSR_EEE_RX_WAKE_ |
+@@ -4087,23 +4590,32 @@ static int lan78xx_resume(struct usb_interface *intf)
+                                           WUCSR_WUFR_ |
+                                           WUCSR_MPR_ |
+                                           WUCSR_BCST_FR_);
++      if (ret < 0)
++              goto out;
+ 
+-      ret = lan78xx_read_reg(dev, MAC_TX, &buf);
+-      buf |= MAC_TX_TXEN_;
+-      ret = lan78xx_write_reg(dev, MAC_TX, buf);
++      ret = 0;
++out:
++      mutex_unlock(&dev->dev_mutex);
+ 
+-      return 0;
++      return ret;
+ }
+ 
+ static int lan78xx_reset_resume(struct usb_interface *intf)
+ {
+       struct lan78xx_net *dev = usb_get_intfdata(intf);
++      int ret;
+ 
+-      lan78xx_reset(dev);
++      netif_dbg(dev, ifup, dev->net, "(reset) resuming device");
++
++      ret = lan78xx_reset(dev);
++      if (ret < 0)
++              return ret;
+ 
+       phy_start(dev->net->phydev);
+ 
+-      return lan78xx_resume(intf);
++      ret = lan78xx_resume(intf);
++
++      return ret;
+ }
+ 
+ static const struct usb_device_id products[] = {
+diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
+index a9751a83d5dbb..def45baec28f8 100644
+--- a/drivers/tty/serial/Kconfig
++++ b/drivers/tty/serial/Kconfig
+@@ -354,6 +354,7 @@ config SERIAL_MAX310X
+       depends on SPI_MASTER
+       select SERIAL_CORE
+       select REGMAP_SPI if SPI_MASTER
++      select REGMAP_I2C if I2C
+       help
+         This selects support for an advanced UART from Maxim (Dallas).
+         Supported ICs are MAX3107, MAX3108, MAX3109, MAX14830.
+diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
+index 14537878f9855..2f88eae8a55a1 100644
+--- a/drivers/tty/serial/max310x.c
++++ b/drivers/tty/serial/max310x.c
+@@ -14,9 +14,10 @@
+ #include <linux/delay.h>
+ #include <linux/device.h>
+ #include <linux/gpio/driver.h>
++#include <linux/i2c.h>
+ #include <linux/module.h>
+-#include <linux/of.h>
+-#include <linux/of_device.h>
++#include <linux/mod_devicetable.h>
++#include <linux/property.h>
+ #include <linux/regmap.h>
+ #include <linux/serial_core.h>
+ #include <linux/serial.h>
+@@ -72,7 +73,8 @@
+ #define MAX310X_GLOBALCMD_REG         MAX310X_REG_1F /* Global Command (WO) */
+ 
+ /* Extended registers */
+-#define MAX310X_REVID_EXTREG          MAX310X_REG_05 /* Revision ID */
++#define MAX310X_SPI_REVID_EXTREG      MAX310X_REG_05 /* Revision ID */
++#define MAX310X_I2C_REVID_EXTREG      (0x25) /* Revision ID */
+ 
+ /* IRQ register bits */
+ #define MAX310X_IRQ_LSR_BIT           (1 << 0) /* LSR interrupt */
+@@ -235,6 +237,10 @@
+ #define MAX310x_REV_MASK              (0xf8)
+ #define MAX310X_WRITE_BIT             0x80
+ 
++/* Port startup definitions */
++#define MAX310X_PORT_STARTUP_WAIT_RETRIES     20 /* Number of retries */
++#define MAX310X_PORT_STARTUP_WAIT_DELAY_MS    10 /* Delay between retries */
++
+ /* Crystal-related definitions */
+ #define MAX310X_XTAL_WAIT_RETRIES     20 /* Number of retries */
+ #define MAX310X_XTAL_WAIT_DELAY_MS    10 /* Delay between retries */
+@@ -249,7 +255,17 @@
+ #define MAX14830_BRGCFG_CLKDIS_BIT    (1 << 6) /* Clock Disable */
+ #define MAX14830_REV_ID                       (0xb0)
+ 
++struct max310x_if_cfg {
++      int (*extended_reg_enable)(struct device *dev, bool enable);
++
++      unsigned int rev_id_reg;
++};
++
+ struct max310x_devtype {
++      struct {
++              unsigned short min;
++              unsigned short max;
++      } slave_addr;
+       char    name[9];
+       int     nr;
+       u8      mode1;
+@@ -262,16 +278,16 @@ struct max310x_one {
+       struct work_struct      tx_work;
+       struct work_struct      md_work;
+       struct work_struct      rs_work;
++      struct regmap           *regmap;
+ 
+-      u8 wr_header;
+-      u8 rd_header;
+       u8 rx_buf[MAX310X_FIFO_SIZE];
+ };
+ #define to_max310x_port(_port) \
+       container_of(_port, struct max310x_one, port)
+ 
+ struct max310x_port {
+-      struct max310x_devtype  *devtype;
++      const struct max310x_devtype *devtype;
++      const struct max310x_if_cfg *if_cfg;
+       struct regmap           *regmap;
+       struct clk              *clk;
+ #ifdef CONFIG_GPIOLIB
+@@ -293,26 +309,26 @@ static DECLARE_BITMAP(max310x_lines, MAX310X_UART_NRMAX);
+ 
+ static u8 max310x_port_read(struct uart_port *port, u8 reg)
+ {
+-      struct max310x_port *s = dev_get_drvdata(port->dev);
++      struct max310x_one *one = to_max310x_port(port);
+       unsigned int val = 0;
+ 
+-      regmap_read(s->regmap, port->iobase + reg, &val);
++      regmap_read(one->regmap, reg, &val);
+ 
+       return val;
+ }
+ 
+ static void max310x_port_write(struct uart_port *port, u8 reg, u8 val)
+ {
+-      struct max310x_port *s = dev_get_drvdata(port->dev);
++      struct max310x_one *one = to_max310x_port(port);
+ 
+-      regmap_write(s->regmap, port->iobase + reg, val);
++      regmap_write(one->regmap, reg, val);
+ }
+ 
+ static void max310x_port_update(struct uart_port *port, u8 reg, u8 mask, u8 
val)
+ {
+-      struct max310x_port *s = dev_get_drvdata(port->dev);
++      struct max310x_one *one = to_max310x_port(port);
+ 
+-      regmap_update_bits(s->regmap, port->iobase + reg, mask, val);
++      regmap_update_bits(one->regmap, reg, mask, val);
+ }
+ 
+ static int max3107_detect(struct device *dev)
+@@ -361,13 +377,12 @@ static int max3109_detect(struct device *dev)
+       unsigned int val = 0;
+       int ret;
+ 
+-      ret = regmap_write(s->regmap, MAX310X_GLOBALCMD_REG,
+-                         MAX310X_EXTREG_ENBL);
++      ret = s->if_cfg->extended_reg_enable(dev, true);
+       if (ret)
+               return ret;
+ 
+-      regmap_read(s->regmap, MAX310X_REVID_EXTREG, &val);
+-      regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, MAX310X_EXTREG_DSBL);
++      regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val);
++      s->if_cfg->extended_reg_enable(dev, false);
+       if (((val & MAX310x_REV_MASK) != MAX3109_REV_ID)) {
+               dev_err(dev,
+                       "%s ID 0x%02x does not match\n", s->devtype->name, val);
+@@ -392,13 +407,12 @@ static int max14830_detect(struct device *dev)
+       unsigned int val = 0;
+       int ret;
+ 
+-      ret = regmap_write(s->regmap, MAX310X_GLOBALCMD_REG,
+-                         MAX310X_EXTREG_ENBL);
++      ret = s->if_cfg->extended_reg_enable(dev, true);
+       if (ret)
+               return ret;
+       
+-      regmap_read(s->regmap, MAX310X_REVID_EXTREG, &val);
+-      regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, MAX310X_EXTREG_DSBL);
++      regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val);
++      s->if_cfg->extended_reg_enable(dev, false);
+       if (((val & MAX310x_REV_MASK) != MAX14830_REV_ID)) {
+               dev_err(dev,
+                       "%s ID 0x%02x does not match\n", s->devtype->name, val);
+@@ -423,6 +437,10 @@ static const struct max310x_devtype max3107_devtype = {
+       .mode1  = MAX310X_MODE1_AUTOSLEEP_BIT | MAX310X_MODE1_IRQSEL_BIT,
+       .detect = max3107_detect,
+       .power  = max310x_power,
++      .slave_addr     = {
++              .min = 0x2c,
++              .max = 0x2f,
++      },
+ };
+ 
+ static const struct max310x_devtype max3108_devtype = {
+@@ -431,6 +449,10 @@ static const struct max310x_devtype max3108_devtype = {
+       .mode1  = MAX310X_MODE1_AUTOSLEEP_BIT,
+       .detect = max3108_detect,
+       .power  = max310x_power,
++      .slave_addr     = {
++              .min = 0x60,
++              .max = 0x6f,
++      },
+ };
+ 
+ static const struct max310x_devtype max3109_devtype = {
+@@ -439,6 +461,10 @@ static const struct max310x_devtype max3109_devtype = {
+       .mode1  = MAX310X_MODE1_AUTOSLEEP_BIT,
+       .detect = max3109_detect,
+       .power  = max310x_power,
++      .slave_addr     = {
++              .min = 0x60,
++              .max = 0x6f,
++      },
+ };
+ 
+ static const struct max310x_devtype max14830_devtype = {
+@@ -447,11 +473,15 @@ static const struct max310x_devtype max14830_devtype = {
+       .mode1  = MAX310X_MODE1_IRQSEL_BIT,
+       .detect = max14830_detect,
+       .power  = max14830_power,
++      .slave_addr     = {
++              .min = 0x60,
++              .max = 0x6f,
++      },
+ };
+ 
+ static bool max310x_reg_writeable(struct device *dev, unsigned int reg)
+ {
+-      switch (reg & 0x1f) {
++      switch (reg) {
+       case MAX310X_IRQSTS_REG:
+       case MAX310X_LSR_IRQSTS_REG:
+       case MAX310X_SPCHR_IRQSTS_REG:
+@@ -468,7 +498,7 @@ static bool max310x_reg_writeable(struct device *dev, 
unsigned int reg)
+ 
+ static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
+ {
+-      switch (reg & 0x1f) {
++      switch (reg) {
+       case MAX310X_RHR_REG:
+       case MAX310X_IRQSTS_REG:
+       case MAX310X_LSR_IRQSTS_REG:
+@@ -490,7 +520,7 @@ static bool max310x_reg_volatile(struct device *dev, 
unsigned int reg)
+ 
+ static bool max310x_reg_precious(struct device *dev, unsigned int reg)
+ {
+-      switch (reg & 0x1f) {
++      switch (reg) {
+       case MAX310X_RHR_REG:
+       case MAX310X_IRQSTS_REG:
+       case MAX310X_SPCHR_IRQSTS_REG:
+@@ -503,6 +533,11 @@ static bool max310x_reg_precious(struct device *dev, 
unsigned int reg)
+       return false;
+ }
+ 
++static bool max310x_reg_noinc(struct device *dev, unsigned int reg)
++{
++      return reg == MAX310X_RHR_REG;
++}
++
+ static int max310x_set_baud(struct uart_port *port, int baud)
+ {
+       unsigned int mode = 0, div = 0, frac = 0, c = 0, F = 0;
+@@ -556,7 +591,7 @@ static int max310x_update_best_err(unsigned long f, long 
*besterr)
+       return 1;
+ }
+ 
+-static int max310x_set_ref_clk(struct device *dev, struct max310x_port *s,
++static s32 max310x_set_ref_clk(struct device *dev, struct max310x_port *s,
+                              unsigned long freq, bool xtal)
+ {
+       unsigned int div, clksrc, pllcfg = 0;
+@@ -626,40 +661,25 @@ static int max310x_set_ref_clk(struct device *dev, 
struct max310x_port *s,
+               } while (!stable && (++try < MAX310X_XTAL_WAIT_RETRIES));
+ 
+               if (!stable)
+-                      dev_warn(dev, "clock is not stable yet\n");
++                      return dev_err_probe(dev, -EAGAIN,
++                                           "clock is not stable\n");
+       }
+ 
+-      return (int)bestfreq;
++      return bestfreq;
+ }
+ 
+ static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned 
int len)
+ {
+       struct max310x_one *one = to_max310x_port(port);
+-      struct spi_transfer xfer[] = {
+-              {
+-                      .tx_buf = &one->wr_header,
+-                      .len = sizeof(one->wr_header),
+-              }, {
+-                      .tx_buf = txbuf,
+-                      .len = len,
+-              }
+-      };
+-      spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer));
++
++      regmap_noinc_write(one->regmap, MAX310X_THR_REG, txbuf, len);
+ }
+ 
+ static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned 
int len)
+ {
+       struct max310x_one *one = to_max310x_port(port);
+-      struct spi_transfer xfer[] = {
+-              {
+-                      .tx_buf = &one->rd_header,
+-                      .len = sizeof(one->rd_header),
+-              }, {
+-                      .rx_buf = rxbuf,
+-                      .len = len,
+-              }
+-      };
+-      spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer));
++
++      regmap_noinc_read(one->regmap, MAX310X_RHR_REG, rxbuf, len);
+ }
+ 
+ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
+@@ -1261,16 +1281,18 @@ static int max310x_gpio_set_config(struct gpio_chip 
*chip, unsigned int offset,
+ }
+ #endif
+ 
+-static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
+-                       struct regmap *regmap, int irq)
++static int max310x_probe(struct device *dev, const struct max310x_devtype 
*devtype,
++                       const struct max310x_if_cfg *if_cfg,
++                       struct regmap *regmaps[], int irq)
+ {
+-      int i, ret, fmin, fmax, freq, uartclk;
+-      struct clk *clk_osc, *clk_xtal;
++      int i, ret, fmin, fmax, freq;
+       struct max310x_port *s;
+-      bool xtal = false;
++      s32 uartclk = 0;
++      bool xtal;
+ 
+-      if (IS_ERR(regmap))
+-              return PTR_ERR(regmap);
++      for (i = 0; i < devtype->nr; i++)
++              if (IS_ERR(regmaps[i]))
++                      return PTR_ERR(regmaps[i]);
+ 
+       /* Alloc port structure */
+       s = devm_kzalloc(dev, struct_size(s, p, devtype->nr), GFP_KERNEL);
+@@ -1279,23 +1301,20 @@ static int max310x_probe(struct device *dev, struct 
max310x_devtype *devtype,
+               return -ENOMEM;
+       }
+ 
+-      clk_osc = devm_clk_get(dev, "osc");
+-      clk_xtal = devm_clk_get(dev, "xtal");
+-      if (!IS_ERR(clk_osc)) {
+-              s->clk = clk_osc;
+-              fmin = 500000;
+-              fmax = 35000000;
+-      } else if (!IS_ERR(clk_xtal)) {
+-              s->clk = clk_xtal;
+-              fmin = 1000000;
+-              fmax = 4000000;
+-              xtal = true;
+-      } else if (PTR_ERR(clk_osc) == -EPROBE_DEFER ||
+-                 PTR_ERR(clk_xtal) == -EPROBE_DEFER) {
+-              return -EPROBE_DEFER;
++      /* Always ask for fixed clock rate from a property. */
++      device_property_read_u32(dev, "clock-frequency", &uartclk);
++
++      s->clk = devm_clk_get_optional(dev, "osc");
++      if (IS_ERR(s->clk))
++              return PTR_ERR(s->clk);
++      if (s->clk) {
++              xtal = false;
+       } else {
+-              dev_err(dev, "Cannot get clock\n");
+-              return -EINVAL;
++              s->clk = devm_clk_get_optional(dev, "xtal");
++              if (IS_ERR(s->clk))
++                      return PTR_ERR(s->clk);
++
++              xtal = true;
+       }
+ 
+       ret = clk_prepare_enable(s->clk);
+@@ -1303,14 +1322,31 @@ static int max310x_probe(struct device *dev, struct 
max310x_devtype *devtype,
+               return ret;
+ 
+       freq = clk_get_rate(s->clk);
++      if (freq == 0)
++              freq = uartclk;
++      if (freq == 0) {
++              dev_err(dev, "Cannot get clock rate\n");
++              ret = -EINVAL;
++              goto out_clk;
++      }
++
++      if (xtal) {
++              fmin = 1000000;
++              fmax = 4000000;
++      } else {
++              fmin = 500000;
++              fmax = 35000000;
++      }
++
+       /* Check frequency limits */
+       if (freq < fmin || freq > fmax) {
+               ret = -ERANGE;
+               goto out_clk;
+       }
+ 
+-      s->regmap = regmap;
++      s->regmap = regmaps[0];
+       s->devtype = devtype;
++      s->if_cfg = if_cfg;
+       dev_set_drvdata(dev, s);
+ 
+       /* Check device to ensure we are talking to what we expect */
+@@ -1319,25 +1355,38 @@ static int max310x_probe(struct device *dev, struct 
max310x_devtype *devtype,
+               goto out_clk;
+ 
+       for (i = 0; i < devtype->nr; i++) {
+-              unsigned int offs = i << 5;
++              bool started = false;
++              unsigned int try = 0, val = 0;
+ 
+               /* Reset port */
+-              regmap_write(s->regmap, MAX310X_MODE2_REG + offs,
++              regmap_write(regmaps[i], MAX310X_MODE2_REG,
+                            MAX310X_MODE2_RST_BIT);
+               /* Clear port reset */
+-              regmap_write(s->regmap, MAX310X_MODE2_REG + offs, 0);
++              regmap_write(regmaps[i], MAX310X_MODE2_REG, 0);
+ 
+               /* Wait for port startup */
+               do {
+-                      regmap_read(s->regmap,
+-                                  MAX310X_BRGDIVLSB_REG + offs, &ret);
+-              } while (ret != 0x01);
++                      msleep(MAX310X_PORT_STARTUP_WAIT_DELAY_MS);
++                      regmap_read(regmaps[i], MAX310X_BRGDIVLSB_REG, &val);
+ 
+-              regmap_write(s->regmap, MAX310X_MODE1_REG + offs,
+-                           devtype->mode1);
++                      if (val == 0x01)
++                              started = true;
++              } while (!started && (++try < 
MAX310X_PORT_STARTUP_WAIT_RETRIES));
++
++              if (!started) {
++                      ret = dev_err_probe(dev, -EAGAIN, "port reset 
failed\n");
++                      goto out_uart;
++              }
++
++              regmap_write(regmaps[i], MAX310X_MODE1_REG, devtype->mode1);
+       }
+ 
+       uartclk = max310x_set_ref_clk(dev, s, freq, xtal);
++      if (uartclk < 0) {
++              ret = uartclk;
++              goto out_uart;
++      }
++
+       dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk);
+ 
+       for (i = 0; i < devtype->nr; i++) {
+@@ -1357,11 +1406,13 @@ static int max310x_probe(struct device *dev, struct 
max310x_devtype *devtype,
+               s->p[i].port.fifosize   = MAX310X_FIFO_SIZE;
+               s->p[i].port.flags      = UPF_FIXED_TYPE | UPF_LOW_LATENCY;
+               s->p[i].port.iotype     = UPIO_PORT;
+-              s->p[i].port.iobase     = i * 0x20;
++              s->p[i].port.iobase     = i;
+               s->p[i].port.membase    = (void __iomem *)~0;
+               s->p[i].port.uartclk    = uartclk;
+               s->p[i].port.rs485_config = max310x_rs485_config;
+               s->p[i].port.ops        = &max310x_ops;
++              s->p[i].regmap          = regmaps[i];
++
+               /* Disable all interrupts */
+               max310x_port_write(&s->p[i].port, MAX310X_IRQEN_REG, 0);
+               /* Clear IRQ status register */
+@@ -1372,10 +1423,6 @@ static int max310x_probe(struct device *dev, struct 
max310x_devtype *devtype,
+               INIT_WORK(&s->p[i].md_work, max310x_md_proc);
+               /* Initialize queue for changing RS485 mode */
+               INIT_WORK(&s->p[i].rs_work, max310x_rs_proc);
+-              /* Initialize SPI-transfer buffers */
+-              s->p[i].wr_header = (s->p[i].port.iobase + MAX310X_THR_REG) |
+-                                  MAX310X_WRITE_BIT;
+-              s->p[i].rd_header = (s->p[i].port.iobase + MAX310X_RHR_REG);
+ 
+               /* Register port */
+               ret = uart_add_one_port(&max310x_uart, &s->p[i].port);
+@@ -1462,16 +1509,35 @@ static struct regmap_config regcfg = {
+       .val_bits = 8,
+       .write_flag_mask = MAX310X_WRITE_BIT,
+       .cache_type = REGCACHE_RBTREE,
++      .max_register = MAX310X_REG_1F,
+       .writeable_reg = max310x_reg_writeable,
+       .volatile_reg = max310x_reg_volatile,
+       .precious_reg = max310x_reg_precious,
++      .writeable_noinc_reg = max310x_reg_noinc,
++      .readable_noinc_reg = max310x_reg_noinc,
++      .max_raw_read = MAX310X_FIFO_SIZE,
++      .max_raw_write = MAX310X_FIFO_SIZE,
+ };
+ 
+ #ifdef CONFIG_SPI_MASTER
++static int max310x_spi_extended_reg_enable(struct device *dev, bool enable)
++{
++      struct max310x_port *s = dev_get_drvdata(dev);
++
++      return regmap_write(s->regmap, MAX310X_GLOBALCMD_REG,
++                          enable ? MAX310X_EXTREG_ENBL : MAX310X_EXTREG_DSBL);
++}
++
++static const struct max310x_if_cfg __maybe_unused max310x_spi_if_cfg = {
++      .extended_reg_enable = max310x_spi_extended_reg_enable,
++      .rev_id_reg = MAX310X_SPI_REVID_EXTREG,
++};
++
+ static int max310x_spi_probe(struct spi_device *spi)
+ {
+-      struct max310x_devtype *devtype;
+-      struct regmap *regmap;
++      const struct max310x_devtype *devtype;
++      struct regmap *regmaps[4];
++      unsigned int i;
+       int ret;
+ 
+       /* Setup SPI bus */
+@@ -1482,23 +1548,18 @@ static int max310x_spi_probe(struct spi_device *spi)
+       if (ret)
+               return ret;
+ 
+-      if (spi->dev.of_node) {
+-              const struct of_device_id *of_id =
+-                      of_match_device(max310x_dt_ids, &spi->dev);
+-              if (!of_id)
+-                      return -ENODEV;
+-
+-              devtype = (struct max310x_devtype *)of_id->data;
+-      } else {
+-              const struct spi_device_id *id_entry = spi_get_device_id(spi);
++      devtype = device_get_match_data(&spi->dev);
++      if (!devtype)
++              devtype = (struct max310x_devtype 
*)spi_get_device_id(spi)->driver_data;
+ 
+-              devtype = (struct max310x_devtype *)id_entry->driver_data;
++      for (i = 0; i < devtype->nr; i++) {
++              u8 port_mask = i * 0x20;
++              regcfg.read_flag_mask = port_mask;
++              regcfg.write_flag_mask = port_mask | MAX310X_WRITE_BIT;
++              regmaps[i] = devm_regmap_init_spi(spi, &regcfg);
+       }
+ 
+-      regcfg.max_register = devtype->nr * 0x20 - 1;
+-      regmap = devm_regmap_init_spi(spi, &regcfg);
+-
+-      return max310x_probe(&spi->dev, devtype, regmap, spi->irq);
++      return max310x_probe(&spi->dev, devtype, &max310x_spi_if_cfg, regmaps, 
spi->irq);
+ }
+ 
+ static int max310x_spi_remove(struct spi_device *spi)
+@@ -1518,7 +1579,7 @@ MODULE_DEVICE_TABLE(spi, max310x_id_table);
+ static struct spi_driver max310x_spi_driver = {
+       .driver = {
+               .name           = MAX310X_NAME,
+-              .of_match_table = of_match_ptr(max310x_dt_ids),
++              .of_match_table = max310x_dt_ids,
+               .pm             = &max310x_pm_ops,
+       },
+       .probe          = max310x_spi_probe,
+@@ -1527,6 +1588,101 @@ static struct spi_driver max310x_spi_driver = {
+ };
+ #endif
+ 
++#ifdef CONFIG_I2C
++static int max310x_i2c_extended_reg_enable(struct device *dev, bool enable)
++{
++      return 0;
++}
++
++static struct regmap_config regcfg_i2c = {
++      .reg_bits = 8,
++      .val_bits = 8,
++      .cache_type = REGCACHE_RBTREE,
++      .writeable_reg = max310x_reg_writeable,
++      .volatile_reg = max310x_reg_volatile,
++      .precious_reg = max310x_reg_precious,
++      .max_register = MAX310X_I2C_REVID_EXTREG,
++      .writeable_noinc_reg = max310x_reg_noinc,
++      .readable_noinc_reg = max310x_reg_noinc,
++      .max_raw_read = MAX310X_FIFO_SIZE,
++      .max_raw_write = MAX310X_FIFO_SIZE,
++};
++
++static const struct max310x_if_cfg max310x_i2c_if_cfg = {
++      .extended_reg_enable = max310x_i2c_extended_reg_enable,
++      .rev_id_reg = MAX310X_I2C_REVID_EXTREG,
++};
++
++static unsigned short max310x_i2c_slave_addr(unsigned short addr,
++                                           unsigned int nr)
++{
++      /*
++       * For MAX14830 and MAX3109, the slave address depends on what the
++       * A0 and A1 pins are tied to.
++       * See Table I2C Address Map of the datasheet.
++       * Based on that table, the following formulas were determined.
++       * UART1 - UART0 = 0x10
++       * UART2 - UART1 = 0x20 + 0x10
++       * UART3 - UART2 = 0x10
++       */
++
++      addr -= nr * 0x10;
++
++      if (nr >= 2)
++              addr -= 0x20;
++
++      return addr;
++}
++
++static int max310x_i2c_probe(struct i2c_client *client)
++{
++      const struct max310x_devtype *devtype =
++                      device_get_match_data(&client->dev);
++      struct i2c_client *port_client;
++      struct regmap *regmaps[4];
++      unsigned int i;
++      u8 port_addr;
++
++      if (client->addr < devtype->slave_addr.min ||
++              client->addr > devtype->slave_addr.max)
++              return dev_err_probe(&client->dev, -EINVAL,
++                                   "Slave addr 0x%x outside of range [0x%x, 
0x%x]\n",
++                                   client->addr, devtype->slave_addr.min,
++                                   devtype->slave_addr.max);
++
++      regmaps[0] = devm_regmap_init_i2c(client, &regcfg_i2c);
++
++      for (i = 1; i < devtype->nr; i++) {
++              port_addr = max310x_i2c_slave_addr(client->addr, i);
++              port_client = devm_i2c_new_dummy_device(&client->dev,
++                                                      client->adapter,
++                                                      port_addr);
++
++              regmaps[i] = devm_regmap_init_i2c(port_client, &regcfg_i2c);
++      }
++
++      return max310x_probe(&client->dev, devtype, &max310x_i2c_if_cfg,
++                           regmaps, client->irq);
++}
++
++static int max310x_i2c_remove(struct i2c_client *client)
++{
++      max310x_remove(&client->dev);
++
++      return 0;
++}
++
++static struct i2c_driver max310x_i2c_driver = {
++      .driver = {
++              .name           = MAX310X_NAME,
++              .of_match_table = max310x_dt_ids,
++              .pm             = &max310x_pm_ops,
++      },
++      .probe_new      = max310x_i2c_probe,
++      .remove         = max310x_i2c_remove,
++};
++#endif
++
+ static int __init max310x_uart_init(void)
+ {
+       int ret;
+@@ -1540,15 +1696,35 @@ static int __init max310x_uart_init(void)
+ #ifdef CONFIG_SPI_MASTER
+       ret = spi_register_driver(&max310x_spi_driver);
+       if (ret)
+-              uart_unregister_driver(&max310x_uart);
++              goto err_spi_register;
++#endif
++
++#ifdef CONFIG_I2C
++      ret = i2c_add_driver(&max310x_i2c_driver);
++      if (ret)
++              goto err_i2c_register;
++#endif
++
++      return 0;
++
++#ifdef CONFIG_I2C
++err_i2c_register:
++      spi_unregister_driver(&max310x_spi_driver);
+ #endif
+ 
++err_spi_register:
++      uart_unregister_driver(&max310x_uart);
++
+       return ret;
+ }
+ module_init(max310x_uart_init);
+ 
+ static void __exit max310x_uart_exit(void)
+ {
++#ifdef CONFIG_I2C
++      i2c_del_driver(&max310x_i2c_driver);
++#endif
++
+ #ifdef CONFIG_SPI_MASTER
+       spi_unregister_driver(&max310x_spi_driver);
+ #endif
+diff --git a/include/linux/regmap.h b/include/linux/regmap.h
+index dfe493ac692d2..edc095434787b 100644
+--- a/include/linux/regmap.h
++++ b/include/linux/regmap.h
+@@ -295,6 +295,17 @@ typedef void (*regmap_unlock)(void *);
+  *              read operation on a bus such as SPI, I2C, etc. Most of the
+  *              devices do not need this.
+  * @reg_write:          Same as above for writing.
++ * @reg_update_bits: Optional callback that if filled will be used to perform
++ *                 all the update_bits(rmw) operation. Should only be provided
++ *                 if the function require special handling with lock and reg
++ *                 handling and the operation cannot be represented as a 
simple
++ *                 update_bits operation on a bus such as SPI, I2C, etc.
++ * @read: Optional callback that if filled will be used to perform all the
++ *        bulk reads from the registers. Data is returned in the buffer used
++ *        to transmit data.
++ * @write: Same as above for writing.
++ * @max_raw_read: Max raw read size that can be used on the device.
++ * @max_raw_write: Max raw write size that can be used on the device.
+  * @fast_io:    Register IO is fast. Use a spinlock instead of a mutex
+  *              to perform locking. This field is ignored if custom 
lock/unlock
+  *              functions are used (see fields lock/unlock of struct 
regmap_config).
+@@ -371,6 +382,14 @@ struct regmap_config {
+ 
+       int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
+       int (*reg_write)(void *context, unsigned int reg, unsigned int val);
++      int (*reg_update_bits)(void *context, unsigned int reg,
++                             unsigned int mask, unsigned int val);
++      /* Bulk read/write */
++      int (*read)(void *context, const void *reg_buf, size_t reg_size,
++                  void *val_buf, size_t val_size);
++      int (*write)(void *context, const void *data, size_t count);
++      size_t max_raw_read;
++      size_t max_raw_write;
+ 
+       bool fast_io;
+ 
+diff --git a/include/uapi/linux/resource.h b/include/uapi/linux/resource.h
+index cc00fd0796317..74ef57b38f9f5 100644
+--- a/include/uapi/linux/resource.h
++++ b/include/uapi/linux/resource.h
+@@ -22,8 +22,8 @@
+ #define       RUSAGE_THREAD   1               /* only the calling thread */
+ 
+ struct        rusage {
+-      struct timeval ru_utime;        /* user time used */
+-      struct timeval ru_stime;        /* system time used */
++      struct __kernel_old_timeval ru_utime;   /* user time used */
++      struct __kernel_old_timeval ru_stime;   /* system time used */
+       __kernel_long_t ru_maxrss;      /* maximum resident set size */
+       __kernel_long_t ru_ixrss;       /* integral shared memory size */
+       __kernel_long_t ru_idrss;       /* integral unshared data size */
+diff --git a/kernel/sys.c b/kernel/sys.c
+index f6d6ce8da3e4a..23e88587df87d 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -1711,74 +1711,87 @@ void getrusage(struct task_struct *p, int who, struct 
rusage *r)
+       struct task_struct *t;
+       unsigned long flags;
+       u64 tgutime, tgstime, utime, stime;
+-      unsigned long maxrss = 0;
++      unsigned long maxrss;
++      struct mm_struct *mm;
++      struct signal_struct *sig = p->signal;
++      unsigned int seq = 0;
+ 
+-      memset((char *)r, 0, sizeof (*r));
++retry:
++      memset(r, 0, sizeof(*r));
+       utime = stime = 0;
++      maxrss = 0;
+ 
+       if (who == RUSAGE_THREAD) {
+               task_cputime_adjusted(current, &utime, &stime);
+               accumulate_thread_rusage(p, r);
+-              maxrss = p->signal->maxrss;
+-              goto out;
++              maxrss = sig->maxrss;
++              goto out_thread;
+       }
+ 
+-      if (!lock_task_sighand(p, &flags))
+-              return;
++      flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq);
+ 
+       switch (who) {
+       case RUSAGE_BOTH:
+       case RUSAGE_CHILDREN:
+-              utime = p->signal->cutime;
+-              stime = p->signal->cstime;
+-              r->ru_nvcsw = p->signal->cnvcsw;
+-              r->ru_nivcsw = p->signal->cnivcsw;
+-              r->ru_minflt = p->signal->cmin_flt;
+-              r->ru_majflt = p->signal->cmaj_flt;
+-              r->ru_inblock = p->signal->cinblock;
+-              r->ru_oublock = p->signal->coublock;
+-              maxrss = p->signal->cmaxrss;
++              utime = sig->cutime;
++              stime = sig->cstime;
++              r->ru_nvcsw = sig->cnvcsw;
++              r->ru_nivcsw = sig->cnivcsw;
++              r->ru_minflt = sig->cmin_flt;
++              r->ru_majflt = sig->cmaj_flt;
++              r->ru_inblock = sig->cinblock;
++              r->ru_oublock = sig->coublock;
++              maxrss = sig->cmaxrss;
+ 
+               if (who == RUSAGE_CHILDREN)
+                       break;
+               /* fall through */
+ 
+       case RUSAGE_SELF:
+-              thread_group_cputime_adjusted(p, &tgutime, &tgstime);
+-              utime += tgutime;
+-              stime += tgstime;
+-              r->ru_nvcsw += p->signal->nvcsw;
+-              r->ru_nivcsw += p->signal->nivcsw;
+-              r->ru_minflt += p->signal->min_flt;
+-              r->ru_majflt += p->signal->maj_flt;
+-              r->ru_inblock += p->signal->inblock;
+-              r->ru_oublock += p->signal->oublock;
+-              if (maxrss < p->signal->maxrss)
+-                      maxrss = p->signal->maxrss;
+-              t = p;
+-              do {
++              r->ru_nvcsw += sig->nvcsw;
++              r->ru_nivcsw += sig->nivcsw;
++              r->ru_minflt += sig->min_flt;
++              r->ru_majflt += sig->maj_flt;
++              r->ru_inblock += sig->inblock;
++              r->ru_oublock += sig->oublock;
++              if (maxrss < sig->maxrss)
++                      maxrss = sig->maxrss;
++
++              rcu_read_lock();
++              __for_each_thread(sig, t)
+                       accumulate_thread_rusage(t, r);
+-              } while_each_thread(p, t);
++              rcu_read_unlock();
++
+               break;
+ 
+       default:
+               BUG();
+       }
+-      unlock_task_sighand(p, &flags);
+ 
+-out:
+-      r->ru_utime = ns_to_timeval(utime);
+-      r->ru_stime = ns_to_timeval(stime);
++      if (need_seqretry(&sig->stats_lock, seq)) {
++              seq = 1;
++              goto retry;
++      }
++      done_seqretry_irqrestore(&sig->stats_lock, seq, flags);
+ 
+-      if (who != RUSAGE_CHILDREN) {
+-              struct mm_struct *mm = get_task_mm(p);
++      if (who == RUSAGE_CHILDREN)
++              goto out_children;
+ 
+-              if (mm) {
+-                      setmax_mm_hiwater_rss(&maxrss, mm);
+-                      mmput(mm);
+-              }
++      thread_group_cputime_adjusted(p, &tgutime, &tgstime);
++      utime += tgutime;
++      stime += tgstime;
++
++out_thread:
++      mm = get_task_mm(p);
++      if (mm) {
++              setmax_mm_hiwater_rss(&maxrss, mm);
++              mmput(mm);
+       }
++
++out_children:
+       r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */
++      r->ru_utime = ns_to_kernel_old_timeval(utime);
++      r->ru_stime = ns_to_kernel_old_timeval(stime);
+ }
+ 
+ SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru)
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index c26e832fddb7d..8eac2c890449f 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -5218,19 +5218,7 @@ static int ip6_route_multipath_add(struct fib6_config 
*cfg,
+       err_nh = NULL;
+       list_for_each_entry(nh, &rt6_nh_list, next) {
+               err = __ip6_ins_rt(nh->fib6_info, info, extack);
+-              fib6_info_release(nh->fib6_info);
+-
+-              if (!err) {
+-                      /* save reference to last route successfully inserted */
+-                      rt_last = nh->fib6_info;
+-
+-                      /* save reference to first route for notification */
+-                      if (!rt_notif)
+-                              rt_notif = nh->fib6_info;
+-              }
+ 
+-              /* nh->fib6_info is used or freed at this point, reset to NULL*/
+-              nh->fib6_info = NULL;
+               if (err) {
+                       if (replace && nhn)
+                               NL_SET_ERR_MSG_MOD(extack,
+@@ -5238,6 +5226,12 @@ static int ip6_route_multipath_add(struct fib6_config 
*cfg,
+                       err_nh = nh;
+                       goto add_errout;
+               }
++              /* save reference to last route successfully inserted */
++              rt_last = nh->fib6_info;
++
++              /* save reference to first route for notification */
++              if (!rt_notif)
++                      rt_notif = nh->fib6_info;
+ 
+               /* Because each route is added like a single route we remove
+                * these flags after the first nexthop: if there is a collision,
+@@ -5284,8 +5278,7 @@ static int ip6_route_multipath_add(struct fib6_config 
*cfg,
+ 
+ cleanup:
+       list_for_each_entry_safe(nh, nh_safe, &rt6_nh_list, next) {
+-              if (nh->fib6_info)
+-                      fib6_info_release(nh->fib6_info);
++              fib6_info_release(nh->fib6_info);
+               list_del(&nh->next);
+               kfree(nh);
+       }
+diff --git a/net/netfilter/nf_conntrack_h323_asn1.c 
b/net/netfilter/nf_conntrack_h323_asn1.c
+index 573cb44814813..814857ae3b812 100644
+--- a/net/netfilter/nf_conntrack_h323_asn1.c
++++ b/net/netfilter/nf_conntrack_h323_asn1.c
+@@ -533,6 +533,8 @@ static int decode_seq(struct bitstr *bs, const struct 
field_t *f,
+       /* Get fields bitmap */
+       if (nf_h323_error_boundary(bs, 0, f->sz))
+               return H323_ERROR_BOUND;
++      if (f->sz > 32)
++              return H323_ERROR_RANGE;
+       bmp = get_bitmap(bs, f->sz);
+       if (base)
+               *(unsigned int *)base = bmp;
+@@ -589,6 +591,8 @@ static int decode_seq(struct bitstr *bs, const struct 
field_t *f,
+       bmp2_len = get_bits(bs, 7) + 1;
+       if (nf_h323_error_boundary(bs, 0, bmp2_len))
+               return H323_ERROR_BOUND;
++      if (bmp2_len > 32)
++              return H323_ERROR_RANGE;
+       bmp2 = get_bitmap(bs, bmp2_len);
+       bmp |= bmp2 >> f->sz;
+       if (base)
+diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
+index 161c4fd715fa5..0c7f091d7d54d 100644
+--- a/net/netfilter/nft_ct.c
++++ b/net/netfilter/nft_ct.c
+@@ -1180,14 +1180,13 @@ static int nft_ct_expect_obj_init(const struct nft_ctx 
*ctx,
+       switch (priv->l3num) {
+       case NFPROTO_IPV4:
+       case NFPROTO_IPV6:
+-              if (priv->l3num != ctx->family)
+-                      return -EINVAL;
++              if (priv->l3num == ctx->family || ctx->family == NFPROTO_INET)
++                      break;
+ 
+-              fallthrough;
+-      case NFPROTO_INET:
+-              break;
++              return -EINVAL;
++      case NFPROTO_INET: /* tuple.src.l3num supports NFPROTO_IPV4/6 only */
+       default:
+-              return -EOPNOTSUPP;
++              return -EAFNOSUPPORT;
+       }
+ 
+       priv->l4proto = nla_get_u8(tb[NFTA_CT_EXPECT_L4PROTO]);
+diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
+index e18a73264c103..abb69c149644a 100644
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -431,16 +431,16 @@ static int nr_create(struct net *net, struct socket 
*sock, int protocol,
+       nr_init_timers(sk);
+ 
+       nr->t1     =
+-              msecs_to_jiffies(sysctl_netrom_transport_timeout);
++              msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_timeout));
+       nr->t2     =
+-              msecs_to_jiffies(sysctl_netrom_transport_acknowledge_delay);
++              
msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_acknowledge_delay));
+       nr->n2     =
+-              msecs_to_jiffies(sysctl_netrom_transport_maximum_tries);
++              
msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_maximum_tries));
+       nr->t4     =
+-              msecs_to_jiffies(sysctl_netrom_transport_busy_delay);
++              msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_busy_delay));
+       nr->idle   =
+-              msecs_to_jiffies(sysctl_netrom_transport_no_activity_timeout);
+-      nr->window = sysctl_netrom_transport_requested_window_size;
++              
msecs_to_jiffies(READ_ONCE(sysctl_netrom_transport_no_activity_timeout));
++      nr->window = READ_ONCE(sysctl_netrom_transport_requested_window_size);
+ 
+       nr->bpqext = 1;
+       nr->state  = NR_STATE_0;
+@@ -932,7 +932,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device 
*dev)
+                * G8PZT's Xrouter which is sending packets with command type 7
+                * as an extension of the protocol.
+                */
+-              if (sysctl_netrom_reset_circuit &&
++              if (READ_ONCE(sysctl_netrom_reset_circuit) &&
+                   (frametype != NR_RESET || flags != 0))
+                       nr_transmit_reset(skb, 1);
+ 
+diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c
+index 29e418c8c6c30..4caee8754b794 100644
+--- a/net/netrom/nr_dev.c
++++ b/net/netrom/nr_dev.c
+@@ -81,7 +81,7 @@ static int nr_header(struct sk_buff *skb, struct net_device 
*dev,
+       buff[6] |= AX25_SSSID_SPARE;
+       buff    += AX25_ADDR_LEN;
+ 
+-      *buff++ = sysctl_netrom_network_ttl_initialiser;
++      *buff++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser);
+ 
+       *buff++ = NR_PROTO_IP;
+       *buff++ = NR_PROTO_IP;
+diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c
+index 2bef3779f8935..8cbb57678a9ea 100644
+--- a/net/netrom/nr_in.c
++++ b/net/netrom/nr_in.c
+@@ -97,7 +97,7 @@ static int nr_state1_machine(struct sock *sk, struct sk_buff 
*skb,
+               break;
+ 
+       case NR_RESET:
+-              if (sysctl_netrom_reset_circuit)
++              if (READ_ONCE(sysctl_netrom_reset_circuit))
+                       nr_disconnect(sk, ECONNRESET);
+               break;
+ 
+@@ -128,7 +128,7 @@ static int nr_state2_machine(struct sock *sk, struct 
sk_buff *skb,
+               break;
+ 
+       case NR_RESET:
+-              if (sysctl_netrom_reset_circuit)
++              if (READ_ONCE(sysctl_netrom_reset_circuit))
+                       nr_disconnect(sk, ECONNRESET);
+               break;
+ 
+@@ -263,7 +263,7 @@ static int nr_state3_machine(struct sock *sk, struct 
sk_buff *skb, int frametype
+               break;
+ 
+       case NR_RESET:
+-              if (sysctl_netrom_reset_circuit)
++              if (READ_ONCE(sysctl_netrom_reset_circuit))
+                       nr_disconnect(sk, ECONNRESET);
+               break;
+ 
+diff --git a/net/netrom/nr_out.c b/net/netrom/nr_out.c
+index 44929657f5b71..5e531394a724b 100644
+--- a/net/netrom/nr_out.c
++++ b/net/netrom/nr_out.c
+@@ -204,7 +204,7 @@ void nr_transmit_buffer(struct sock *sk, struct sk_buff 
*skb)
+       dptr[6] |= AX25_SSSID_SPARE;
+       dptr += AX25_ADDR_LEN;
+ 
+-      *dptr++ = sysctl_netrom_network_ttl_initialiser;
++      *dptr++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser);
+ 
+       if (!nr_route_frame(skb, NULL)) {
+               kfree_skb(skb);
+diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
+index 89cd9de215948..37cfa880c2d05 100644
+--- a/net/netrom/nr_route.c
++++ b/net/netrom/nr_route.c
+@@ -153,7 +153,7 @@ static int __must_check nr_add_node(ax25_address *nr, 
const char *mnemonic,
+               nr_neigh->digipeat = NULL;
+               nr_neigh->ax25     = NULL;
+               nr_neigh->dev      = dev;
+-              nr_neigh->quality  = sysctl_netrom_default_path_quality;
++              nr_neigh->quality  = 
READ_ONCE(sysctl_netrom_default_path_quality);
+               nr_neigh->locked   = 0;
+               nr_neigh->count    = 0;
+               nr_neigh->number   = nr_neigh_no++;
+@@ -725,7 +725,7 @@ void nr_link_failed(ax25_cb *ax25, int reason)
+       nr_neigh->ax25 = NULL;
+       ax25_cb_put(ax25);
+ 
+-      if (++nr_neigh->failed < sysctl_netrom_link_fails_count) {
++      if (++nr_neigh->failed < READ_ONCE(sysctl_netrom_link_fails_count)) {
+               nr_neigh_put(nr_neigh);
+               return;
+       }
+@@ -763,7 +763,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
+       if (ax25 != NULL) {
+               ret = nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat,
+                                 ax25->ax25_dev->dev, 0,
+-                                sysctl_netrom_obsolescence_count_initialiser);
++                                
READ_ONCE(sysctl_netrom_obsolescence_count_initialiser));
+               if (ret)
+                       return ret;
+       }
+@@ -777,7 +777,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
+               return ret;
+       }
+ 
+-      if (!sysctl_netrom_routing_control && ax25 != NULL)
++      if (!READ_ONCE(sysctl_netrom_routing_control) && ax25 != NULL)
+               return 0;
+ 
+       /* Its Time-To-Live has expired */
+diff --git a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c
+index e2d2af924cff4..c3bbd5880850b 100644
+--- a/net/netrom/nr_subr.c
++++ b/net/netrom/nr_subr.c
+@@ -182,7 +182,8 @@ void nr_write_internal(struct sock *sk, int frametype)
+               *dptr++ = nr->my_id;
+               *dptr++ = frametype;
+               *dptr++ = nr->window;
+-              if (nr->bpqext) *dptr++ = sysctl_netrom_network_ttl_initialiser;
++              if (nr->bpqext)
++                      *dptr++ = 
READ_ONCE(sysctl_netrom_network_ttl_initialiser);
+               break;
+ 
+       case NR_DISCREQ:
+@@ -236,7 +237,7 @@ void __nr_transmit_reply(struct sk_buff *skb, int mine, 
unsigned char cmdflags)
+       dptr[6] |= AX25_SSSID_SPARE;
+       dptr += AX25_ADDR_LEN;
+ 
+-      *dptr++ = sysctl_netrom_network_ttl_initialiser;
++      *dptr++ = READ_ONCE(sysctl_netrom_network_ttl_initialiser);
+ 
+       if (mine) {
+               *dptr++ = 0;
+diff --git a/net/rds/rdma.c b/net/rds/rdma.c
+index 1c42a600fe7fa..dc0f7cf1917ff 100644
+--- a/net/rds/rdma.c
++++ b/net/rds/rdma.c
+@@ -279,6 +279,9 @@ static int __rds_rdma_map(struct rds_sock *rs, struct 
rds_get_mr_args *args,
+                       put_page(sg_page(&sg[i]));
+               kfree(sg);
+               ret = PTR_ERR(trans_private);
++              /* Trigger connection so that its ready for the next retry */
++              if (ret == -ENODEV)
++                      rds_conn_connect_if_down(cp->cp_conn);
+               goto out;
+       }
+ 
+diff --git a/net/rds/send.c b/net/rds/send.c
+index 68e2bdb08fd09..6c2c5667e3a39 100644
+--- a/net/rds/send.c
++++ b/net/rds/send.c
+@@ -1314,12 +1314,8 @@ int rds_sendmsg(struct socket *sock, struct msghdr 
*msg, size_t payload_len)
+ 
+       /* Parse any control messages the user may have included. */
+       ret = rds_cmsg_send(rs, rm, msg, &allocated_mr, &vct);
+-      if (ret) {
+-              /* Trigger connection so that its ready for the next retry */
+-              if (ret ==  -EAGAIN)
+-                      rds_conn_connect_if_down(conn);
++      if (ret)
+               goto out;
+-      }
+ 
+       if (rm->rdma.op_active && !conn->c_trans->xmit_rdma) {
+               printk_ratelimited(KERN_NOTICE "rdma_op %p conn xmit_rdma %p\n",
+diff --git a/tools/testing/selftests/vm/map_hugetlb.c 
b/tools/testing/selftests/vm/map_hugetlb.c
+index 312889edb84ab..c65c55b7a789f 100644
+--- a/tools/testing/selftests/vm/map_hugetlb.c
++++ b/tools/testing/selftests/vm/map_hugetlb.c
+@@ -15,6 +15,7 @@
+ #include <unistd.h>
+ #include <sys/mman.h>
+ #include <fcntl.h>
++#include "vm_util.h"
+ 
+ #define LENGTH (256UL*1024*1024)
+ #define PROTECTION (PROT_READ | PROT_WRITE)
+@@ -70,10 +71,16 @@ int main(int argc, char **argv)
+ {
+       void *addr;
+       int ret;
++      size_t hugepage_size;
+       size_t length = LENGTH;
+       int flags = FLAGS;
+       int shift = 0;
+ 
++      hugepage_size = default_huge_page_size();
++      /* munmap with fail if the length is not page aligned */
++      if (hugepage_size > length)
++              length = hugepage_size;
++
+       if (argc > 1)
+               length = atol(argv[1]) << 20;
+       if (argc > 2) {

Reply via email to