commit:     69042ad09e4a5c8bbee21cfb0a2d5b0eb665106e
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Mon Jun  5 11:50:42 2023 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Mon Jun  5 11:50:42 2023 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=69042ad0

Linux patch 5.4.245

Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>

 0000_README              |    4 +
 1244_linux-5.4.245.patch | 1307 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1311 insertions(+)

diff --git a/0000_README b/0000_README
index 2bc77166..780ca5e9 100644
--- a/0000_README
+++ b/0000_README
@@ -1019,6 +1019,10 @@ Patch:  1243_linux-5.4.244.patch
 From:   https://www.kernel.org
 Desc:   Linux 5.4.244
 
+Patch:  1244_linux-5.4.245.patch
+From:   https://www.kernel.org
+Desc:   Linux 5.4.245
+
 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/1244_linux-5.4.245.patch b/1244_linux-5.4.245.patch
new file mode 100644
index 00000000..39dd4d96
--- /dev/null
+++ b/1244_linux-5.4.245.patch
@@ -0,0 +1,1307 @@
+diff --git a/Makefile b/Makefile
+index a12f1af9b03b1..c0a1daa41dc04 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 5
+ PATCHLEVEL = 4
+-SUBLEVEL = 244
++SUBLEVEL = 245
+ EXTRAVERSION =
+ NAME = Kleptomaniac Octopus
+ 
+diff --git a/drivers/android/binder.c b/drivers/android/binder.c
+index 4b96742f0fe57..1c39cd12b755a 100644
+--- a/drivers/android/binder.c
++++ b/drivers/android/binder.c
+@@ -2270,24 +2270,23 @@ static void binder_deferred_fd_close(int fd)
+ static void binder_transaction_buffer_release(struct binder_proc *proc,
+                                             struct binder_thread *thread,
+                                             struct binder_buffer *buffer,
+-                                            binder_size_t failed_at,
++                                            binder_size_t off_end_offset,
+                                             bool is_failure)
+ {
+       int debug_id = buffer->debug_id;
+-      binder_size_t off_start_offset, buffer_offset, off_end_offset;
++      binder_size_t off_start_offset, buffer_offset;
+ 
+       binder_debug(BINDER_DEBUG_TRANSACTION,
+                    "%d buffer release %d, size %zd-%zd, failed at %llx\n",
+                    proc->pid, buffer->debug_id,
+                    buffer->data_size, buffer->offsets_size,
+-                   (unsigned long long)failed_at);
++                   (unsigned long long)off_end_offset);
+ 
+       if (buffer->target_node)
+               binder_dec_node(buffer->target_node, 1, 0);
+ 
+       off_start_offset = ALIGN(buffer->data_size, sizeof(void *));
+-      off_end_offset = is_failure && failed_at ? failed_at :
+-                              off_start_offset + buffer->offsets_size;
++
+       for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
+            buffer_offset += sizeof(binder_size_t)) {
+               struct binder_object_header *hdr;
+@@ -2447,6 +2446,21 @@ static void binder_transaction_buffer_release(struct 
binder_proc *proc,
+       }
+ }
+ 
++/* Clean up all the objects in the buffer */
++static inline void binder_release_entire_buffer(struct binder_proc *proc,
++                                              struct binder_thread *thread,
++                                              struct binder_buffer *buffer,
++                                              bool is_failure)
++{
++      binder_size_t off_end_offset;
++
++      off_end_offset = ALIGN(buffer->data_size, sizeof(void *));
++      off_end_offset += buffer->offsets_size;
++
++      binder_transaction_buffer_release(proc, thread, buffer,
++                                        off_end_offset, is_failure);
++}
++
+ static int binder_translate_binder(struct flat_binder_object *fp,
+                                  struct binder_transaction *t,
+                                  struct binder_thread *thread)
+@@ -3930,7 +3944,7 @@ binder_free_buf(struct binder_proc *proc,
+               binder_node_inner_unlock(buf_node);
+       }
+       trace_binder_transaction_buffer_release(buffer);
+-      binder_transaction_buffer_release(proc, thread, buffer, 0, is_failure);
++      binder_release_entire_buffer(proc, thread, buffer, is_failure);
+       binder_alloc_free_buf(&proc->alloc, buffer);
+ }
+ 
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c 
b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
+index abd066e952286..438be215bbd45 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
+@@ -3,6 +3,7 @@
+ 
+ #include <linux/mlx5/vport.h>
+ #include "lib/devcom.h"
++#include "mlx5_core.h"
+ 
+ static LIST_HEAD(devcom_list);
+ 
+@@ -14,7 +15,7 @@ static LIST_HEAD(devcom_list);
+ struct mlx5_devcom_component {
+       struct {
+               void *data;
+-      } device[MLX5_MAX_PORTS];
++      } device[MLX5_DEVCOM_PORTS_SUPPORTED];
+ 
+       mlx5_devcom_event_handler_t handler;
+       struct rw_semaphore sem;
+@@ -25,7 +26,7 @@ struct mlx5_devcom_list {
+       struct list_head list;
+ 
+       struct mlx5_devcom_component components[MLX5_DEVCOM_NUM_COMPONENTS];
+-      struct mlx5_core_dev *devs[MLX5_MAX_PORTS];
++      struct mlx5_core_dev *devs[MLX5_DEVCOM_PORTS_SUPPORTED];
+ };
+ 
+ struct mlx5_devcom {
+@@ -74,13 +75,16 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct 
mlx5_core_dev *dev)
+ 
+       if (!mlx5_core_is_pf(dev))
+               return NULL;
++      if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED)
++              return NULL;
+ 
++      mlx5_dev_list_lock();
+       sguid0 = mlx5_query_nic_system_image_guid(dev);
+       list_for_each_entry(iter, &devcom_list, list) {
+               struct mlx5_core_dev *tmp_dev = NULL;
+ 
+               idx = -1;
+-              for (i = 0; i < MLX5_MAX_PORTS; i++) {
++              for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) {
+                       if (iter->devs[i])
+                               tmp_dev = iter->devs[i];
+                       else
+@@ -100,8 +104,10 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct 
mlx5_core_dev *dev)
+ 
+       if (!priv) {
+               priv = mlx5_devcom_list_alloc();
+-              if (!priv)
+-                      return ERR_PTR(-ENOMEM);
++              if (!priv) {
++                      devcom = ERR_PTR(-ENOMEM);
++                      goto out;
++              }
+ 
+               idx = 0;
+               new_priv = true;
+@@ -112,12 +118,14 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct 
mlx5_core_dev *dev)
+       if (!devcom) {
+               if (new_priv)
+                       kfree(priv);
+-              return ERR_PTR(-ENOMEM);
++              devcom = ERR_PTR(-ENOMEM);
++              goto out;
+       }
+ 
+       if (new_priv)
+               list_add(&priv->list, &devcom_list);
+-
++out:
++      mlx5_dev_list_unlock();
+       return devcom;
+ }
+ 
+@@ -130,20 +138,23 @@ void mlx5_devcom_unregister_device(struct mlx5_devcom 
*devcom)
+       if (IS_ERR_OR_NULL(devcom))
+               return;
+ 
++      mlx5_dev_list_lock();
+       priv = devcom->priv;
+       priv->devs[devcom->idx] = NULL;
+ 
+       kfree(devcom);
+ 
+-      for (i = 0; i < MLX5_MAX_PORTS; i++)
++      for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
+               if (priv->devs[i])
+                       break;
+ 
+-      if (i != MLX5_MAX_PORTS)
+-              return;
++      if (i != MLX5_DEVCOM_PORTS_SUPPORTED)
++              goto out;
+ 
+       list_del(&priv->list);
+       kfree(priv);
++out:
++      mlx5_dev_list_unlock();
+ }
+ 
+ void mlx5_devcom_register_component(struct mlx5_devcom *devcom,
+@@ -192,7 +203,7 @@ int mlx5_devcom_send_event(struct mlx5_devcom *devcom,
+ 
+       comp = &devcom->priv->components[id];
+       down_write(&comp->sem);
+-      for (i = 0; i < MLX5_MAX_PORTS; i++)
++      for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
+               if (i != devcom->idx && comp->device[i].data) {
+                       err = comp->handler(event, comp->device[i].data,
+                                           event_data);
+@@ -240,7 +251,7 @@ void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom,
+               return NULL;
+       }
+ 
+-      for (i = 0; i < MLX5_MAX_PORTS; i++)
++      for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
+               if (i != devcom->idx)
+                       break;
+ 
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h 
b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
+index 939d5bf1581b5..94313c18bb647 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
+@@ -6,6 +6,8 @@
+ 
+ #include <linux/mlx5/driver.h>
+ 
++#define MLX5_DEVCOM_PORTS_SUPPORTED 2
++
+ enum mlx5_devcom_components {
+       MLX5_DEVCOM_ESW_OFFLOADS,
+ 
+diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
+index 1c9a1b94f6e28..4824385fe2c79 100644
+--- a/drivers/net/usb/cdc_ncm.c
++++ b/drivers/net/usb/cdc_ncm.c
+@@ -175,10 +175,17 @@ static u32 cdc_ncm_check_tx_max(struct usbnet *dev, u32 
new_tx)
+       u32 val, max, min;
+ 
+       /* clamp new_tx to sane values */
+-      min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct 
usb_cdc_ncm_nth16);
+-      max = min_t(u32, CDC_NCM_NTB_MAX_SIZE_TX, 
le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize));
+-      if (max == 0)
++      if (ctx->is_ndp16)
++              min = ctx->max_datagram_size + ctx->max_ndp_size + 
sizeof(struct usb_cdc_ncm_nth16);
++      else
++              min = ctx->max_datagram_size + ctx->max_ndp_size + 
sizeof(struct usb_cdc_ncm_nth32);
++
++      if (le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize) == 0)
+               max = CDC_NCM_NTB_MAX_SIZE_TX; /* dwNtbOutMaxSize not set */
++      else
++              max = clamp_t(u32, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize),
++                            USB_CDC_NCM_NTB_MIN_OUT_SIZE,
++                            CDC_NCM_NTB_MAX_SIZE_TX);
+ 
+       /* some devices set dwNtbOutMaxSize too low for the above default */
+       min = min(min, max);
+@@ -309,10 +316,17 @@ static ssize_t ndp_to_end_store(struct device *d,  
struct device_attribute *attr
+       if (enable == (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END))
+               return len;
+ 
+-      if (enable && !ctx->delayed_ndp16) {
+-              ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL);
+-              if (!ctx->delayed_ndp16)
+-                      return -ENOMEM;
++      if (enable) {
++              if (ctx->is_ndp16 && !ctx->delayed_ndp16) {
++                      ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, 
GFP_KERNEL);
++                      if (!ctx->delayed_ndp16)
++                              return -ENOMEM;
++              }
++              if (!ctx->is_ndp16 && !ctx->delayed_ndp32) {
++                      ctx->delayed_ndp32 = kzalloc(ctx->max_ndp_size, 
GFP_KERNEL);
++                      if (!ctx->delayed_ndp32)
++                              return -ENOMEM;
++              }
+       }
+ 
+       /* flush pending data before changing flag */
+@@ -514,6 +528,9 @@ static int cdc_ncm_init(struct usbnet *dev)
+                       dev_err(&dev->intf->dev, "SET_CRC_MODE failed\n");
+       }
+ 
++      /* use ndp16 by default */
++      ctx->is_ndp16 = 1;
++
+       /* set NTB format, if both formats are supported.
+        *
+        * "The host shall only send this command while the NCM Data
+@@ -521,14 +538,27 @@ static int cdc_ncm_init(struct usbnet *dev)
+        */
+       if (le16_to_cpu(ctx->ncm_parm.bmNtbFormatsSupported) &
+                                               USB_CDC_NCM_NTB32_SUPPORTED) {
+-              dev_dbg(&dev->intf->dev, "Setting NTB format to 16-bit\n");
+-              err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT,
+-                                     USB_TYPE_CLASS | USB_DIR_OUT
+-                                     | USB_RECIP_INTERFACE,
+-                                     USB_CDC_NCM_NTB16_FORMAT,
+-                                     iface_no, NULL, 0);
+-              if (err < 0)
++              if (ctx->drvflags & CDC_NCM_FLAG_PREFER_NTB32) {
++                      ctx->is_ndp16 = 0;
++                      dev_dbg(&dev->intf->dev, "Setting NTB format to 
32-bit\n");
++                      err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT,
++                                             USB_TYPE_CLASS | USB_DIR_OUT
++                                             | USB_RECIP_INTERFACE,
++                                             USB_CDC_NCM_NTB32_FORMAT,
++                                             iface_no, NULL, 0);
++              } else {
++                      ctx->is_ndp16 = 1;
++                      dev_dbg(&dev->intf->dev, "Setting NTB format to 
16-bit\n");
++                      err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT,
++                                             USB_TYPE_CLASS | USB_DIR_OUT
++                                             | USB_RECIP_INTERFACE,
++                                             USB_CDC_NCM_NTB16_FORMAT,
++                                             iface_no, NULL, 0);
++              }
++              if (err < 0) {
++                      ctx->is_ndp16 = 1;
+                       dev_err(&dev->intf->dev, "SET_NTB_FORMAT failed\n");
++              }
+       }
+ 
+       /* set initial device values */
+@@ -551,7 +581,10 @@ static int cdc_ncm_init(struct usbnet *dev)
+               ctx->tx_max_datagrams = CDC_NCM_DPT_DATAGRAMS_MAX;
+ 
+       /* set up maximum NDP size */
+-      ctx->max_ndp_size = sizeof(struct usb_cdc_ncm_ndp16) + 
(ctx->tx_max_datagrams + 1) * sizeof(struct usb_cdc_ncm_dpe16);
++      if (ctx->is_ndp16)
++              ctx->max_ndp_size = sizeof(struct usb_cdc_ncm_ndp16) + 
(ctx->tx_max_datagrams + 1) * sizeof(struct usb_cdc_ncm_dpe16);
++      else
++              ctx->max_ndp_size = sizeof(struct usb_cdc_ncm_ndp32) + 
(ctx->tx_max_datagrams + 1) * sizeof(struct usb_cdc_ncm_dpe32);
+ 
+       /* initial coalescing timer interval */
+       ctx->timer_interval = CDC_NCM_TIMER_INTERVAL_USEC * NSEC_PER_USEC;
+@@ -736,7 +769,10 @@ static void cdc_ncm_free(struct cdc_ncm_ctx *ctx)
+               ctx->tx_curr_skb = NULL;
+       }
+ 
+-      kfree(ctx->delayed_ndp16);
++      if (ctx->is_ndp16)
++              kfree(ctx->delayed_ndp16);
++      else
++              kfree(ctx->delayed_ndp32);
+ 
+       kfree(ctx);
+ }
+@@ -774,10 +810,8 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct 
usb_interface *intf, u8 data_
+       u8 *buf;
+       int len;
+       int temp;
+-      int err;
+       u8 iface_no;
+       struct usb_cdc_parsed_header hdr;
+-      __le16 curr_ntb_format;
+ 
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
+@@ -881,32 +915,6 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct 
usb_interface *intf, u8 data_
+               goto error2;
+       }
+ 
+-      /*
+-       * Some Huawei devices have been observed to come out of reset in NDP32 
mode.
+-       * Let's check if this is the case, and set the device to NDP16 mode 
again if
+-       * needed.
+-      */
+-      if (ctx->drvflags & CDC_NCM_FLAG_RESET_NTB16) {
+-              err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_FORMAT,
+-                                    USB_TYPE_CLASS | USB_DIR_IN | 
USB_RECIP_INTERFACE,
+-                                    0, iface_no, &curr_ntb_format, 2);
+-              if (err < 0) {
+-                      goto error2;
+-              }
+-
+-              if (curr_ntb_format == cpu_to_le16(USB_CDC_NCM_NTB32_FORMAT)) {
+-                      dev_info(&intf->dev, "resetting NTB format to 16-bit");
+-                      err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT,
+-                                             USB_TYPE_CLASS | USB_DIR_OUT
+-                                             | USB_RECIP_INTERFACE,
+-                                             USB_CDC_NCM_NTB16_FORMAT,
+-                                             iface_no, NULL, 0);
+-
+-                      if (err < 0)
+-                              goto error2;
+-              }
+-      }
+-
+       cdc_ncm_find_endpoints(dev, ctx->data);
+       cdc_ncm_find_endpoints(dev, ctx->control);
+       if (!dev->in || !dev->out || !dev->status) {
+@@ -931,9 +939,15 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct 
usb_interface *intf, u8 data_
+ 
+       /* Allocate the delayed NDP if needed. */
+       if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
+-              ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL);
+-              if (!ctx->delayed_ndp16)
+-                      goto error2;
++              if (ctx->is_ndp16) {
++                      ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, 
GFP_KERNEL);
++                      if (!ctx->delayed_ndp16)
++                              goto error2;
++              } else {
++                      ctx->delayed_ndp32 = kzalloc(ctx->max_ndp_size, 
GFP_KERNEL);
++                      if (!ctx->delayed_ndp32)
++                              goto error2;
++              }
+               dev_info(&intf->dev, "NDP will be placed at end of frame for 
this device.");
+       }
+ 
+@@ -1057,7 +1071,7 @@ static void cdc_ncm_align_tail(struct sk_buff *skb, 
size_t modulus, size_t remai
+ /* return a pointer to a valid struct usb_cdc_ncm_ndp16 of type sign, possibly
+  * allocating a new one within skb
+  */
+-static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct 
sk_buff *skb, __le32 sign, size_t reserve)
++static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp16(struct cdc_ncm_ctx *ctx, 
struct sk_buff *skb, __le32 sign, size_t reserve)
+ {
+       struct usb_cdc_ncm_ndp16 *ndp16 = NULL;
+       struct usb_cdc_ncm_nth16 *nth16 = (void *)skb->data;
+@@ -1112,12 +1126,73 @@ static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct 
cdc_ncm_ctx *ctx, struct sk_
+       return ndp16;
+ }
+ 
++static struct usb_cdc_ncm_ndp32 *cdc_ncm_ndp32(struct cdc_ncm_ctx *ctx, 
struct sk_buff *skb, __le32 sign, size_t reserve)
++{
++      struct usb_cdc_ncm_ndp32 *ndp32 = NULL;
++      struct usb_cdc_ncm_nth32 *nth32 = (void *)skb->data;
++      size_t ndpoffset = le32_to_cpu(nth32->dwNdpIndex);
++
++      /* If NDP should be moved to the end of the NCM package, we can't 
follow the
++       * NTH32 header as we would normally do. NDP isn't written to the SKB 
yet, and
++       * the wNdpIndex field in the header is actually not consistent with 
reality. It will be later.
++       */
++      if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
++              if (ctx->delayed_ndp32->dwSignature == sign)
++                      return ctx->delayed_ndp32;
++
++              /* We can only push a single NDP to the end. Return
++               * NULL to send what we've already got and queue this
++               * skb for later.
++               */
++              else if (ctx->delayed_ndp32->dwSignature)
++                      return NULL;
++      }
++
++      /* follow the chain of NDPs, looking for a match */
++      while (ndpoffset) {
++              ndp32 = (struct usb_cdc_ncm_ndp32 *)(skb->data + ndpoffset);
++              if  (ndp32->dwSignature == sign)
++                      return ndp32;
++              ndpoffset = le32_to_cpu(ndp32->dwNextNdpIndex);
++      }
++
++      /* align new NDP */
++      if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END))
++              cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, 
ctx->tx_curr_size);
++
++      /* verify that there is room for the NDP and the datagram (reserve) */
++      if ((ctx->tx_curr_size - skb->len - reserve) < ctx->max_ndp_size)
++              return NULL;
++
++      /* link to it */
++      if (ndp32)
++              ndp32->dwNextNdpIndex = cpu_to_le32(skb->len);
++      else
++              nth32->dwNdpIndex = cpu_to_le32(skb->len);
++
++      /* push a new empty NDP */
++      if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END))
++              ndp32 = skb_put_zero(skb, ctx->max_ndp_size);
++      else
++              ndp32 = ctx->delayed_ndp32;
++
++      ndp32->dwSignature = sign;
++      ndp32->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp32) + 
sizeof(struct usb_cdc_ncm_dpe32));
++      return ndp32;
++}
++
+ struct sk_buff *
+ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
+ {
+       struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
+-      struct usb_cdc_ncm_nth16 *nth16;
+-      struct usb_cdc_ncm_ndp16 *ndp16;
++      union {
++              struct usb_cdc_ncm_nth16 *nth16;
++              struct usb_cdc_ncm_nth32 *nth32;
++      } nth;
++      union {
++              struct usb_cdc_ncm_ndp16 *ndp16;
++              struct usb_cdc_ncm_ndp32 *ndp32;
++      } ndp;
+       struct sk_buff *skb_out;
+       u16 n = 0, index, ndplen;
+       u8 ready2send = 0;
+@@ -1157,6 +1232,9 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff 
*skb, __le32 sign)
+                        * further.
+                        */
+                       if (skb_out == NULL) {
++                              /* If even the smallest allocation fails, 
abort. */
++                              if (ctx->tx_curr_size == 
USB_CDC_NCM_NTB_MIN_OUT_SIZE)
++                                      goto alloc_failed;
+                               ctx->tx_low_mem_max_cnt = 
min(ctx->tx_low_mem_max_cnt + 1,
+                                                             
(unsigned)CDC_NCM_LOW_MEM_MAX_CNT);
+                               ctx->tx_low_mem_val = ctx->tx_low_mem_max_cnt;
+@@ -1175,20 +1253,23 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct 
sk_buff *skb, __le32 sign)
+                       skb_out = alloc_skb(ctx->tx_curr_size, GFP_ATOMIC);
+ 
+                       /* No allocation possible so we will abort */
+-                      if (skb_out == NULL) {
+-                              if (skb != NULL) {
+-                                      dev_kfree_skb_any(skb);
+-                                      dev->net->stats.tx_dropped++;
+-                              }
+-                              goto exit_no_skb;
+-                      }
++                      if (!skb_out)
++                              goto alloc_failed;
+                       ctx->tx_low_mem_val--;
+               }
+-              /* fill out the initial 16-bit NTB header */
+-              nth16 = skb_put_zero(skb_out, sizeof(struct usb_cdc_ncm_nth16));
+-              nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
+-              nth16->wHeaderLength = cpu_to_le16(sizeof(struct 
usb_cdc_ncm_nth16));
+-              nth16->wSequence = cpu_to_le16(ctx->tx_seq++);
++              if (ctx->is_ndp16) {
++                      /* fill out the initial 16-bit NTB header */
++                      nth.nth16 = skb_put_zero(skb_out, sizeof(struct 
usb_cdc_ncm_nth16));
++                      nth.nth16->dwSignature = 
cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
++                      nth.nth16->wHeaderLength = cpu_to_le16(sizeof(struct 
usb_cdc_ncm_nth16));
++                      nth.nth16->wSequence = cpu_to_le16(ctx->tx_seq++);
++              } else {
++                      /* fill out the initial 32-bit NTB header */
++                      nth.nth32 = skb_put_zero(skb_out, sizeof(struct 
usb_cdc_ncm_nth32));
++                      nth.nth32->dwSignature = 
cpu_to_le32(USB_CDC_NCM_NTH32_SIGN);
++                      nth.nth32->wHeaderLength = cpu_to_le16(sizeof(struct 
usb_cdc_ncm_nth32));
++                      nth.nth32->wSequence = cpu_to_le16(ctx->tx_seq++);
++              }
+ 
+               /* count total number of frames in this NTB */
+               ctx->tx_curr_frame_num = 0;
+@@ -1210,13 +1291,17 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct 
sk_buff *skb, __le32 sign)
+               }
+ 
+               /* get the appropriate NDP for this skb */
+-              ndp16 = cdc_ncm_ndp(ctx, skb_out, sign, skb->len + 
ctx->tx_modulus + ctx->tx_remainder);
++              if (ctx->is_ndp16)
++                      ndp.ndp16 = cdc_ncm_ndp16(ctx, skb_out, sign, skb->len 
+ ctx->tx_modulus + ctx->tx_remainder);
++              else
++                      ndp.ndp32 = cdc_ncm_ndp32(ctx, skb_out, sign, skb->len 
+ ctx->tx_modulus + ctx->tx_remainder);
+ 
+               /* align beginning of next frame */
+               cdc_ncm_align_tail(skb_out,  ctx->tx_modulus, 
ctx->tx_remainder, ctx->tx_curr_size);
+ 
+               /* check if we had enough room left for both NDP and frame */
+-              if (!ndp16 || skb_out->len + skb->len + delayed_ndp_size > 
ctx->tx_curr_size) {
++              if ((ctx->is_ndp16 && !ndp.ndp16) || (!ctx->is_ndp16 && 
!ndp.ndp32) ||
++                  skb_out->len + skb->len + delayed_ndp_size > 
ctx->tx_curr_size) {
+                       if (n == 0) {
+                               /* won't fit, MTU problem? */
+                               dev_kfree_skb_any(skb);
+@@ -1238,13 +1323,22 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct 
sk_buff *skb, __le32 sign)
+               }
+ 
+               /* calculate frame number withing this NDP */
+-              ndplen = le16_to_cpu(ndp16->wLength);
+-              index = (ndplen - sizeof(struct usb_cdc_ncm_ndp16)) / 
sizeof(struct usb_cdc_ncm_dpe16) - 1;
++              if (ctx->is_ndp16) {
++                      ndplen = le16_to_cpu(ndp.ndp16->wLength);
++                      index = (ndplen - sizeof(struct usb_cdc_ncm_ndp16)) / 
sizeof(struct usb_cdc_ncm_dpe16) - 1;
++
++                      /* OK, add this skb */
++                      ndp.ndp16->dpe16[index].wDatagramLength = 
cpu_to_le16(skb->len);
++                      ndp.ndp16->dpe16[index].wDatagramIndex = 
cpu_to_le16(skb_out->len);
++                      ndp.ndp16->wLength = cpu_to_le16(ndplen + sizeof(struct 
usb_cdc_ncm_dpe16));
++              } else {
++                      ndplen = le16_to_cpu(ndp.ndp32->wLength);
++                      index = (ndplen - sizeof(struct usb_cdc_ncm_ndp32)) / 
sizeof(struct usb_cdc_ncm_dpe32) - 1;
+ 
+-              /* OK, add this skb */
+-              ndp16->dpe16[index].wDatagramLength = cpu_to_le16(skb->len);
+-              ndp16->dpe16[index].wDatagramIndex = cpu_to_le16(skb_out->len);
+-              ndp16->wLength = cpu_to_le16(ndplen + sizeof(struct 
usb_cdc_ncm_dpe16));
++                      ndp.ndp32->dpe32[index].dwDatagramLength = 
cpu_to_le32(skb->len);
++                      ndp.ndp32->dpe32[index].dwDatagramIndex = 
cpu_to_le32(skb_out->len);
++                      ndp.ndp32->wLength = cpu_to_le16(ndplen + sizeof(struct 
usb_cdc_ncm_dpe32));
++              }
+               skb_put_data(skb_out, skb->data, skb->len);
+               ctx->tx_curr_frame_payload += skb->len; /* count real tx 
payload data */
+               dev_kfree_skb_any(skb);
+@@ -1291,13 +1385,22 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct 
sk_buff *skb, __le32 sign)
+ 
+       /* If requested, put NDP at end of frame. */
+       if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
+-              nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
+-              cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, 
ctx->tx_curr_size - ctx->max_ndp_size);
+-              nth16->wNdpIndex = cpu_to_le16(skb_out->len);
+-              skb_put_data(skb_out, ctx->delayed_ndp16, ctx->max_ndp_size);
++              if (ctx->is_ndp16) {
++                      nth.nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
++                      cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, 
ctx->tx_curr_size - ctx->max_ndp_size);
++                      nth.nth16->wNdpIndex = cpu_to_le16(skb_out->len);
++                      skb_put_data(skb_out, ctx->delayed_ndp16, 
ctx->max_ndp_size);
++
++                      /* Zero out delayed NDP - signature checking will 
naturally fail. */
++                      ndp.ndp16 = memset(ctx->delayed_ndp16, 0, 
ctx->max_ndp_size);
++              } else {
++                      nth.nth32 = (struct usb_cdc_ncm_nth32 *)skb_out->data;
++                      cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, 
ctx->tx_curr_size - ctx->max_ndp_size);
++                      nth.nth32->dwNdpIndex = cpu_to_le32(skb_out->len);
++                      skb_put_data(skb_out, ctx->delayed_ndp32, 
ctx->max_ndp_size);
+ 
+-              /* Zero out delayed NDP - signature checking will naturally 
fail. */
+-              ndp16 = memset(ctx->delayed_ndp16, 0, ctx->max_ndp_size);
++                      ndp.ndp32 = memset(ctx->delayed_ndp32, 0, 
ctx->max_ndp_size);
++              }
+       }
+ 
+       /* If collected data size is less or equal ctx->min_tx_pkt
+@@ -1320,8 +1423,13 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct 
sk_buff *skb, __le32 sign)
+       }
+ 
+       /* set final frame length */
+-      nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
+-      nth16->wBlockLength = cpu_to_le16(skb_out->len);
++      if (ctx->is_ndp16) {
++              nth.nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
++              nth.nth16->wBlockLength = cpu_to_le16(skb_out->len);
++      } else {
++              nth.nth32 = (struct usb_cdc_ncm_nth32 *)skb_out->data;
++              nth.nth32->dwBlockLength = cpu_to_le32(skb_out->len);
++      }
+ 
+       /* return skb */
+       ctx->tx_curr_skb = NULL;
+@@ -1339,6 +1447,11 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct 
sk_buff *skb, __le32 sign)
+ 
+       return skb_out;
+ 
++alloc_failed:
++      if (skb) {
++              dev_kfree_skb_any(skb);
++              dev->net->stats.tx_dropped++;
++      }
+ exit_no_skb:
+       /* Start timer, if there is a remaining non-empty skb */
+       if (ctx->tx_curr_skb != NULL && n > 0)
+@@ -1404,7 +1517,12 @@ cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff 
*skb, gfp_t flags)
+               goto error;
+ 
+       spin_lock_bh(&ctx->mtx);
+-      skb_out = cdc_ncm_fill_tx_frame(dev, skb, 
cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN));
++
++      if (ctx->is_ndp16)
++              skb_out = cdc_ncm_fill_tx_frame(dev, skb, 
cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN));
++      else
++              skb_out = cdc_ncm_fill_tx_frame(dev, skb, 
cpu_to_le32(USB_CDC_NCM_NDP32_NOCRC_SIGN));
++
+       spin_unlock_bh(&ctx->mtx);
+       return skb_out;
+ 
+@@ -1465,6 +1583,54 @@ error:
+ }
+ EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_nth16);
+ 
++int cdc_ncm_rx_verify_nth32(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in)
++{
++      struct usbnet *dev = netdev_priv(skb_in->dev);
++      struct usb_cdc_ncm_nth32 *nth32;
++      int len;
++      int ret = -EINVAL;
++
++      if (ctx == NULL)
++              goto error;
++
++      if (skb_in->len < (sizeof(struct usb_cdc_ncm_nth32) +
++                                      sizeof(struct usb_cdc_ncm_ndp32))) {
++              netif_dbg(dev, rx_err, dev->net, "frame too short\n");
++              goto error;
++      }
++
++      nth32 = (struct usb_cdc_ncm_nth32 *)skb_in->data;
++
++      if (nth32->dwSignature != cpu_to_le32(USB_CDC_NCM_NTH32_SIGN)) {
++              netif_dbg(dev, rx_err, dev->net,
++                        "invalid NTH32 signature <%#010x>\n",
++                        le32_to_cpu(nth32->dwSignature));
++              goto error;
++      }
++
++      len = le32_to_cpu(nth32->dwBlockLength);
++      if (len > ctx->rx_max) {
++              netif_dbg(dev, rx_err, dev->net,
++                        "unsupported NTB block length %u/%u\n", len,
++                        ctx->rx_max);
++              goto error;
++      }
++
++      if ((ctx->rx_seq + 1) != le16_to_cpu(nth32->wSequence) &&
++          (ctx->rx_seq || le16_to_cpu(nth32->wSequence)) &&
++          !((ctx->rx_seq == 0xffff) && !le16_to_cpu(nth32->wSequence))) {
++              netif_dbg(dev, rx_err, dev->net,
++                        "sequence number glitch prev=%d curr=%d\n",
++                        ctx->rx_seq, le16_to_cpu(nth32->wSequence));
++      }
++      ctx->rx_seq = le16_to_cpu(nth32->wSequence);
++
++      ret = le32_to_cpu(nth32->dwNdpIndex);
++error:
++      return ret;
++}
++EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_nth32);
++
+ /* verify NDP header and return number of datagrams, or negative error */
+ int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset)
+ {
+@@ -1501,6 +1667,42 @@ error:
+ }
+ EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_ndp16);
+ 
++/* verify NDP header and return number of datagrams, or negative error */
++int cdc_ncm_rx_verify_ndp32(struct sk_buff *skb_in, int ndpoffset)
++{
++      struct usbnet *dev = netdev_priv(skb_in->dev);
++      struct usb_cdc_ncm_ndp32 *ndp32;
++      int ret = -EINVAL;
++
++      if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp32)) > skb_in->len) {
++              netif_dbg(dev, rx_err, dev->net, "invalid NDP offset  <%u>\n",
++                        ndpoffset);
++              goto error;
++      }
++      ndp32 = (struct usb_cdc_ncm_ndp32 *)(skb_in->data + ndpoffset);
++
++      if (le16_to_cpu(ndp32->wLength) < USB_CDC_NCM_NDP32_LENGTH_MIN) {
++              netif_dbg(dev, rx_err, dev->net, "invalid DPT32 length <%u>\n",
++                        le16_to_cpu(ndp32->wLength));
++              goto error;
++      }
++
++      ret = ((le16_to_cpu(ndp32->wLength) -
++                                      sizeof(struct usb_cdc_ncm_ndp32)) /
++                                      sizeof(struct usb_cdc_ncm_dpe32));
++      ret--; /* we process NDP entries except for the last one */
++
++      if ((sizeof(struct usb_cdc_ncm_ndp32) +
++           ret * (sizeof(struct usb_cdc_ncm_dpe32))) > skb_in->len) {
++              netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret);
++              ret = -EINVAL;
++      }
++
++error:
++      return ret;
++}
++EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_ndp32);
++
+ int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+ {
+       struct sk_buff *skb;
+@@ -1509,34 +1711,66 @@ int cdc_ncm_rx_fixup(struct usbnet *dev, struct 
sk_buff *skb_in)
+       int nframes;
+       int x;
+       int offset;
+-      struct usb_cdc_ncm_ndp16 *ndp16;
+-      struct usb_cdc_ncm_dpe16 *dpe16;
++      union {
++              struct usb_cdc_ncm_ndp16 *ndp16;
++              struct usb_cdc_ncm_ndp32 *ndp32;
++      } ndp;
++      union {
++              struct usb_cdc_ncm_dpe16 *dpe16;
++              struct usb_cdc_ncm_dpe32 *dpe32;
++      } dpe;
++
+       int ndpoffset;
+       int loopcount = 50; /* arbitrary max preventing infinite loop */
+       u32 payload = 0;
+ 
+-      ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
++      if (ctx->is_ndp16)
++              ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
++      else
++              ndpoffset = cdc_ncm_rx_verify_nth32(ctx, skb_in);
++
+       if (ndpoffset < 0)
+               goto error;
+ 
+ next_ndp:
+-      nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
+-      if (nframes < 0)
+-              goto error;
++      if (ctx->is_ndp16) {
++              nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
++              if (nframes < 0)
++                      goto error;
+ 
+-      ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
++              ndp.ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + 
ndpoffset);
+ 
+-      if (ndp16->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN)) {
+-              netif_dbg(dev, rx_err, dev->net,
+-                        "invalid DPT16 signature <%#010x>\n",
+-                        le32_to_cpu(ndp16->dwSignature));
+-              goto err_ndp;
++              if (ndp.ndp16->dwSignature != 
cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN)) {
++                      netif_dbg(dev, rx_err, dev->net,
++                                "invalid DPT16 signature <%#010x>\n",
++                                le32_to_cpu(ndp.ndp16->dwSignature));
++                      goto err_ndp;
++              }
++              dpe.dpe16 = ndp.ndp16->dpe16;
++      } else {
++              nframes = cdc_ncm_rx_verify_ndp32(skb_in, ndpoffset);
++              if (nframes < 0)
++                      goto error;
++
++              ndp.ndp32 = (struct usb_cdc_ncm_ndp32 *)(skb_in->data + 
ndpoffset);
++
++              if (ndp.ndp32->dwSignature != 
cpu_to_le32(USB_CDC_NCM_NDP32_NOCRC_SIGN)) {
++                      netif_dbg(dev, rx_err, dev->net,
++                                "invalid DPT32 signature <%#010x>\n",
++                                le32_to_cpu(ndp.ndp32->dwSignature));
++                      goto err_ndp;
++              }
++              dpe.dpe32 = ndp.ndp32->dpe32;
+       }
+-      dpe16 = ndp16->dpe16;
+ 
+-      for (x = 0; x < nframes; x++, dpe16++) {
+-              offset = le16_to_cpu(dpe16->wDatagramIndex);
+-              len = le16_to_cpu(dpe16->wDatagramLength);
++      for (x = 0; x < nframes; x++) {
++              if (ctx->is_ndp16) {
++                      offset = le16_to_cpu(dpe.dpe16->wDatagramIndex);
++                      len = le16_to_cpu(dpe.dpe16->wDatagramLength);
++              } else {
++                      offset = le32_to_cpu(dpe.dpe32->dwDatagramIndex);
++                      len = le32_to_cpu(dpe.dpe32->dwDatagramLength);
++              }
+ 
+               /*
+                * CDC NCM ch. 3.7
+@@ -1567,10 +1801,19 @@ next_ndp:
+                       usbnet_skb_return(dev, skb);
+                       payload += len; /* count payload bytes in this NTB */
+               }
++
++              if (ctx->is_ndp16)
++                      dpe.dpe16++;
++              else
++                      dpe.dpe32++;
+       }
+ err_ndp:
+       /* are there more NDPs to process? */
+-      ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
++      if (ctx->is_ndp16)
++              ndpoffset = le16_to_cpu(ndp.ndp16->wNextNdpIndex);
++      else
++              ndpoffset = le32_to_cpu(ndp.ndp32->dwNextNdpIndex);
++
+       if (ndpoffset && loopcount--)
+               goto next_ndp;
+ 
+diff --git a/drivers/net/usb/huawei_cdc_ncm.c 
b/drivers/net/usb/huawei_cdc_ncm.c
+index e15a472c6a54c..099d848270042 100644
+--- a/drivers/net/usb/huawei_cdc_ncm.c
++++ b/drivers/net/usb/huawei_cdc_ncm.c
+@@ -77,11 +77,11 @@ static int huawei_cdc_ncm_bind(struct usbnet *usbnet_dev,
+        */
+       drvflags |= CDC_NCM_FLAG_NDP_TO_END;
+ 
+-      /* Additionally, it has been reported that some Huawei E3372H devices, 
with
+-       * firmware version 21.318.01.00.541, come out of reset in NTB32 format 
mode, hence
+-       * needing to be set to the NTB16 one again.
++      /* For many Huawei devices the NTB32 mode is the default and the best 
mode
++       * they work with. Huawei E5785 and E5885 devices refuse to work in 
NTB16 mode at all.
+        */
+-      drvflags |= CDC_NCM_FLAG_RESET_NTB16;
++      drvflags |= CDC_NCM_FLAG_PREFER_NTB32;
++
+       ret = cdc_ncm_bind_common(usbnet_dev, intf, 1, drvflags);
+       if (ret)
+               goto err;
+diff --git a/drivers/power/supply/bq24190_charger.c 
b/drivers/power/supply/bq24190_charger.c
+index 64d87dccea82c..f912284b2e551 100644
+--- a/drivers/power/supply/bq24190_charger.c
++++ b/drivers/power/supply/bq24190_charger.c
+@@ -1211,8 +1211,19 @@ static void bq24190_input_current_limit_work(struct 
work_struct *work)
+       struct bq24190_dev_info *bdi =
+               container_of(work, struct bq24190_dev_info,
+                            input_current_limit_work.work);
++      union power_supply_propval val;
++      int ret;
+ 
+-      power_supply_set_input_current_limit_from_supplier(bdi->charger);
++      ret = power_supply_get_property_from_supplier(bdi->charger,
++                                                    
POWER_SUPPLY_PROP_CURRENT_MAX,
++                                                    &val);
++      if (ret)
++              return;
++
++      bq24190_charger_set_property(bdi->charger,
++                                   POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
++                                   &val);
++      power_supply_changed(bdi->charger);
+ }
+ 
+ /* Sync the input-current-limit with our parent supply (if we have one) */
+diff --git a/drivers/power/supply/bq27xxx_battery.c 
b/drivers/power/supply/bq27xxx_battery.c
+index b45cbd40294b9..ffdd646d7ebc0 100644
+--- a/drivers/power/supply/bq27xxx_battery.c
++++ b/drivers/power/supply/bq27xxx_battery.c
+@@ -1862,8 +1862,8 @@ static void bq27xxx_external_power_changed(struct 
power_supply *psy)
+ {
+       struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
+ 
+-      cancel_delayed_work_sync(&di->work);
+-      schedule_delayed_work(&di->work, 0);
++      /* After charger plug in/out wait 0.5s for things to stabilize */
++      mod_delayed_work(system_wq, &di->work, HZ / 2);
+ }
+ 
+ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
+diff --git a/drivers/power/supply/power_supply_core.c 
b/drivers/power/supply/power_supply_core.c
+index fd24254d90142..3fdc988595b3a 100644
+--- a/drivers/power/supply/power_supply_core.c
++++ b/drivers/power/supply/power_supply_core.c
+@@ -375,46 +375,49 @@ int power_supply_is_system_supplied(void)
+ }
+ EXPORT_SYMBOL_GPL(power_supply_is_system_supplied);
+ 
+-static int __power_supply_get_supplier_max_current(struct device *dev,
+-                                                 void *data)
++struct psy_get_supplier_prop_data {
++      struct power_supply *psy;
++      enum power_supply_property psp;
++      union power_supply_propval *val;
++};
++
++static int __power_supply_get_supplier_property(struct device *dev, void 
*_data)
+ {
+-      union power_supply_propval ret = {0,};
+       struct power_supply *epsy = dev_get_drvdata(dev);
+-      struct power_supply *psy = data;
++      struct psy_get_supplier_prop_data *data = _data;
+ 
+-      if (__power_supply_is_supplied_by(epsy, psy))
+-              if (!epsy->desc->get_property(epsy,
+-                                            POWER_SUPPLY_PROP_CURRENT_MAX,
+-                                            &ret))
+-                      return ret.intval;
++      if (__power_supply_is_supplied_by(epsy, data->psy))
++              if (!epsy->desc->get_property(epsy, data->psp, data->val))
++                      return 1; /* Success */
+ 
+-      return 0;
++      return 0; /* Continue iterating */
+ }
+ 
+-int power_supply_set_input_current_limit_from_supplier(struct power_supply 
*psy)
++int power_supply_get_property_from_supplier(struct power_supply *psy,
++                                          enum power_supply_property psp,
++                                          union power_supply_propval *val)
+ {
+-      union power_supply_propval val = {0,};
+-      int curr;
+-
+-      if (!psy->desc->set_property)
+-              return -EINVAL;
++      struct psy_get_supplier_prop_data data = {
++              .psy = psy,
++              .psp = psp,
++              .val = val,
++      };
++      int ret;
+ 
+       /*
+        * This function is not intended for use with a supply with multiple
+-       * suppliers, we simply pick the first supply to report a non 0
+-       * max-current.
++       * suppliers, we simply pick the first supply to report the psp.
+        */
+-      curr = class_for_each_device(power_supply_class, NULL, psy,
+-                                    __power_supply_get_supplier_max_current);
+-      if (curr <= 0)
+-              return (curr == 0) ? -ENODEV : curr;
+-
+-      val.intval = curr;
++      ret = class_for_each_device(power_supply_class, NULL, &data,
++                                  __power_supply_get_supplier_property);
++      if (ret < 0)
++              return ret;
++      if (ret == 0)
++              return -ENODEV;
+ 
+-      return psy->desc->set_property(psy,
+-                              POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val);
++      return 0;
+ }
+-EXPORT_SYMBOL_GPL(power_supply_set_input_current_limit_from_supplier);
++EXPORT_SYMBOL_GPL(power_supply_get_property_from_supplier);
+ 
+ int power_supply_set_battery_charged(struct power_supply *psy)
+ {
+diff --git a/fs/io_uring.c b/fs/io_uring.c
+index e8df6345a812d..3683ddeb625ae 100644
+--- a/fs/io_uring.c
++++ b/fs/io_uring.c
+@@ -551,7 +551,8 @@ static void io_kill_timeout(struct io_kiocb *req)
+               atomic_inc(&req->ctx->cq_timeouts);
+               list_del(&req->list);
+               io_cqring_fill_event(req->ctx, req->user_data, 0);
+-              __io_free_req(req);
++              if (refcount_dec_and_test(&req->refs))
++                      __io_free_req(req);
+       }
+ }
+ 
+@@ -2079,12 +2080,12 @@ static int io_timeout(struct io_kiocb *req, const 
struct io_uring_sqe *sqe)
+       req->sequence -= span;
+ add:
+       list_add(&req->list, entry);
+-      spin_unlock_irq(&ctx->completion_lock);
+ 
+       hrtimer_init(&req->timeout.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       req->timeout.timer.function = io_timeout_fn;
+       hrtimer_start(&req->timeout.timer, timespec64_to_ktime(ts),
+                       HRTIMER_MODE_REL);
++      spin_unlock_irq(&ctx->completion_lock);
+       return 0;
+ }
+ 
+@@ -3738,9 +3739,6 @@ static void io_cancel_async_work(struct io_ring_ctx *ctx,
+ {
+       struct io_kiocb *req;
+ 
+-      if (list_empty(&ctx->task_list))
+-              return;
+-
+       spin_lock_irq(&ctx->task_lock);
+ 
+       list_for_each_entry(req, &ctx->task_list, task_list) {
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index e003afcea3f3e..4b1553f570f2c 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1360,28 +1360,28 @@ extern int send_sigurg(struct fown_struct *fown);
+  * sb->s_flags.  Note that these mirror the equivalent MS_* flags where
+  * represented in both.
+  */
+-#define SB_RDONLY      1      /* Mount read-only */
+-#define SB_NOSUID      2      /* Ignore suid and sgid bits */
+-#define SB_NODEV       4      /* Disallow access to device special files */
+-#define SB_NOEXEC      8      /* Disallow program execution */
+-#define SB_SYNCHRONOUS        16      /* Writes are synced at once */
+-#define SB_MANDLOCK   64      /* Allow mandatory locks on an FS */
+-#define SB_DIRSYNC    128     /* Directory modifications are synchronous */
+-#define SB_NOATIME    1024    /* Do not update access times. */
+-#define SB_NODIRATIME 2048    /* Do not update directory access times */
+-#define SB_SILENT     32768
+-#define SB_POSIXACL   (1<<16) /* VFS does not apply the umask */
+-#define SB_KERNMOUNT  (1<<22) /* this is a kern_mount call */
+-#define SB_I_VERSION  (1<<23) /* Update inode I_version field */
+-#define SB_LAZYTIME   (1<<25) /* Update the on-disk [acm]times lazily */
++#define SB_RDONLY       BIT(0)        /* Mount read-only */
++#define SB_NOSUID       BIT(1)        /* Ignore suid and sgid bits */
++#define SB_NODEV        BIT(2)        /* Disallow access to device special 
files */
++#define SB_NOEXEC       BIT(3)        /* Disallow program execution */
++#define SB_SYNCHRONOUS  BIT(4)        /* Writes are synced at once */
++#define SB_MANDLOCK     BIT(6)        /* Allow mandatory locks on an FS */
++#define SB_DIRSYNC      BIT(7)        /* Directory modifications are 
synchronous */
++#define SB_NOATIME      BIT(10)       /* Do not update access times. */
++#define SB_NODIRATIME   BIT(11)       /* Do not update directory access times 
*/
++#define SB_SILENT       BIT(15)
++#define SB_POSIXACL     BIT(16)       /* VFS does not apply the umask */
++#define SB_KERNMOUNT    BIT(22)       /* this is a kern_mount call */
++#define SB_I_VERSION    BIT(23)       /* Update inode I_version field */
++#define SB_LAZYTIME     BIT(25)       /* Update the on-disk [acm]times lazily 
*/
+ 
+ /* These sb flags are internal to the kernel */
+-#define SB_SUBMOUNT     (1<<26)
+-#define SB_FORCE      (1<<27)
+-#define SB_NOSEC      (1<<28)
+-#define SB_BORN               (1<<29)
+-#define SB_ACTIVE     (1<<30)
+-#define SB_NOUSER     (1<<31)
++#define SB_SUBMOUNT     BIT(26)
++#define SB_FORCE        BIT(27)
++#define SB_NOSEC        BIT(28)
++#define SB_BORN         BIT(29)
++#define SB_ACTIVE       BIT(30)
++#define SB_NOUSER       BIT(31)
+ 
+ /*
+  *    Umount options
+diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
+index 28413f737e7d0..f4aad9554de2e 100644
+--- a/include/linux/power_supply.h
++++ b/include/linux/power_supply.h
+@@ -383,8 +383,9 @@ extern int power_supply_batinfo_ocv2cap(struct 
power_supply_battery_info *info,
+                                       int ocv, int temp);
+ extern void power_supply_changed(struct power_supply *psy);
+ extern int power_supply_am_i_supplied(struct power_supply *psy);
+-extern int power_supply_set_input_current_limit_from_supplier(
+-                                       struct power_supply *psy);
++int power_supply_get_property_from_supplier(struct power_supply *psy,
++                                          enum power_supply_property psp,
++                                          union power_supply_propval *val);
+ extern int power_supply_set_battery_charged(struct power_supply *psy);
+ 
+ #ifdef CONFIG_POWER_SUPPLY
+diff --git a/include/linux/usb/cdc_ncm.h b/include/linux/usb/cdc_ncm.h
+index 1646c06989df7..0ce4377545f82 100644
+--- a/include/linux/usb/cdc_ncm.h
++++ b/include/linux/usb/cdc_ncm.h
+@@ -46,9 +46,12 @@
+ #define CDC_NCM_DATA_ALTSETTING_NCM           1
+ #define CDC_NCM_DATA_ALTSETTING_MBIM          2
+ 
+-/* CDC NCM subclass 3.2.1 */
++/* CDC NCM subclass 3.3.1 */
+ #define USB_CDC_NCM_NDP16_LENGTH_MIN          0x10
+ 
++/* CDC NCM subclass 3.3.2 */
++#define USB_CDC_NCM_NDP32_LENGTH_MIN          0x20
++
+ /* Maximum NTB length */
+ #define       CDC_NCM_NTB_MAX_SIZE_TX                 32768   /* bytes */
+ #define       CDC_NCM_NTB_MAX_SIZE_RX                 32768   /* bytes */
+@@ -84,7 +87,7 @@
+ /* Driver flags */
+ #define CDC_NCM_FLAG_NDP_TO_END                       0x02    /* NDP is 
placed at end of frame */
+ #define CDC_MBIM_FLAG_AVOID_ALTSETTING_TOGGLE 0x04    /* Avoid altsetting 
toggle during init */
+-#define CDC_NCM_FLAG_RESET_NTB16 0x08 /* set NDP16 one more time after 
altsetting switch */
++#define CDC_NCM_FLAG_PREFER_NTB32 0x08        /* prefer NDP32 over NDP16 */
+ 
+ #define cdc_ncm_comm_intf_is_mbim(x)  ((x)->desc.bInterfaceSubClass == 
USB_CDC_SUBCLASS_MBIM && \
+                                      (x)->desc.bInterfaceProtocol == 
USB_CDC_PROTO_NONE)
+@@ -113,7 +116,11 @@ struct cdc_ncm_ctx {
+ 
+       u32 timer_interval;
+       u32 max_ndp_size;
+-      struct usb_cdc_ncm_ndp16 *delayed_ndp16;
++      u8 is_ndp16;
++      union {
++              struct usb_cdc_ncm_ndp16 *delayed_ndp16;
++              struct usb_cdc_ncm_ndp32 *delayed_ndp32;
++      };
+ 
+       u32 tx_timer_pending;
+       u32 tx_curr_frame_num;
+@@ -150,6 +157,8 @@ void cdc_ncm_unbind(struct usbnet *dev, struct 
usb_interface *intf);
+ struct sk_buff *cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff 
*skb, __le32 sign);
+ int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in);
+ int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset);
++int cdc_ncm_rx_verify_nth32(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in);
++int cdc_ncm_rx_verify_ndp32(struct sk_buff *skb_in, int ndpoffset);
+ struct sk_buff *
+ cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags);
+ int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in);
+diff --git a/include/net/ip.h b/include/net/ip.h
+index db841ab388c0e..0ebe5385efcae 100644
+--- a/include/net/ip.h
++++ b/include/net/ip.h
+@@ -73,6 +73,7 @@ struct ipcm_cookie {
+       __be32                  addr;
+       int                     oif;
+       struct ip_options_rcu   *opt;
++      __u8                    protocol;
+       __u8                    ttl;
+       __s16                   tos;
+       char                    priority;
+@@ -93,6 +94,7 @@ static inline void ipcm_init_sk(struct ipcm_cookie *ipcm,
+       ipcm->sockc.tsflags = inet->sk.sk_tsflags;
+       ipcm->oif = inet->sk.sk_bound_dev_if;
+       ipcm->addr = inet->inet_saddr;
++      ipcm->protocol = inet->inet_num;
+ }
+ 
+ #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
+diff --git a/include/uapi/linux/in.h b/include/uapi/linux/in.h
+index 60e1241d4b77b..f5ac290c22509 100644
+--- a/include/uapi/linux/in.h
++++ b/include/uapi/linux/in.h
+@@ -154,6 +154,8 @@ struct in_addr {
+ #define MCAST_MSFILTER                        48
+ #define IP_MULTICAST_ALL              49
+ #define IP_UNICAST_IF                 50
++#define IP_LOCAL_PORT_RANGE           51
++#define IP_PROTOCOL                   52
+ 
+ #define MCAST_EXCLUDE 0
+ #define MCAST_INCLUDE 1
+diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
+index 4f8f5204ae7a0..45f6ce1f380e0 100644
+--- a/net/bluetooth/hci_sock.c
++++ b/net/bluetooth/hci_sock.c
+@@ -973,6 +973,34 @@ static int hci_sock_ioctl(struct socket *sock, unsigned 
int cmd,
+ 
+       BT_DBG("cmd %x arg %lx", cmd, arg);
+ 
++      /* Make sure the cmd is valid before doing anything */
++      switch (cmd) {
++      case HCIGETDEVLIST:
++      case HCIGETDEVINFO:
++      case HCIGETCONNLIST:
++      case HCIDEVUP:
++      case HCIDEVDOWN:
++      case HCIDEVRESET:
++      case HCIDEVRESTAT:
++      case HCISETSCAN:
++      case HCISETAUTH:
++      case HCISETENCRYPT:
++      case HCISETPTYPE:
++      case HCISETLINKPOL:
++      case HCISETLINKMODE:
++      case HCISETACLMTU:
++      case HCISETSCOMTU:
++      case HCIINQUIRY:
++      case HCISETRAW:
++      case HCIGETCONNINFO:
++      case HCIGETAUTHINFO:
++      case HCIBLOCKADDR:
++      case HCIUNBLOCKADDR:
++              break;
++      default:
++              return -ENOIOCTLCMD;
++      }
++
+       lock_sock(sk);
+ 
+       if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
+diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
+index aa3fd61818c47..0c528f642eb86 100644
+--- a/net/ipv4/ip_sockglue.c
++++ b/net/ipv4/ip_sockglue.c
+@@ -316,7 +316,14 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, 
struct ipcm_cookie *ipc,
+                       ipc->tos = val;
+                       ipc->priority = rt_tos2priority(ipc->tos);
+                       break;
+-
++              case IP_PROTOCOL:
++                      if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)))
++                              return -EINVAL;
++                      val = *(int *)CMSG_DATA(cmsg);
++                      if (val < 1 || val > 255)
++                              return -EINVAL;
++                      ipc->protocol = val;
++                      break;
+               default:
+                       return -EINVAL;
+               }
+@@ -1524,6 +1531,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, 
int optname,
+       case IP_MINTTL:
+               val = inet->min_ttl;
+               break;
++      case IP_PROTOCOL:
++              val = inet_sk(sk)->inet_num;
++              break;
+       default:
+               release_sock(sk);
+               return -ENOPROTOOPT;
+diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
+index ddc24e57dc555..1044f4985922f 100644
+--- a/net/ipv4/raw.c
++++ b/net/ipv4/raw.c
+@@ -558,6 +558,9 @@ static int raw_sendmsg(struct sock *sk, struct msghdr 
*msg, size_t len)
+       }
+ 
+       ipcm_init_sk(&ipc, inet);
++      /* Keep backward compat */
++      if (hdrincl)
++              ipc.protocol = IPPROTO_RAW;
+ 
+       if (msg->msg_controllen) {
+               err = ip_cmsg_send(sk, msg, &ipc, false);
+@@ -625,7 +628,7 @@ static int raw_sendmsg(struct sock *sk, struct msghdr 
*msg, size_t len)
+ 
+       flowi4_init_output(&fl4, ipc.oif, ipc.sockc.mark, tos,
+                          RT_SCOPE_UNIVERSE,
+-                         hdrincl ? IPPROTO_RAW : sk->sk_protocol,
++                         hdrincl ? ipc.protocol : sk->sk_protocol,
+                          inet_sk_flowi_flags(sk) |
+                           (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
+                          daddr, saddr, 0, 0, sk->sk_uid);
+diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
+index bf052d68e1f5a..731485b18de31 100644
+--- a/net/ipv6/raw.c
++++ b/net/ipv6/raw.c
+@@ -828,7 +828,8 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr 
*msg, size_t len)
+ 
+               if (!proto)
+                       proto = inet->inet_num;
+-              else if (proto != inet->inet_num)
++              else if (proto != inet->inet_num &&
++                       inet->inet_num != IPPROTO_RAW)
+                       return -EINVAL;
+ 
+               if (proto > 255)
+diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
+index 4747daf901e71..754f473ce3de4 100644
+--- a/net/netfilter/nf_conntrack_netlink.c
++++ b/net/netfilter/nf_conntrack_netlink.c
+@@ -1229,9 +1229,6 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] 
= {
+ 
+ static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data)
+ {
+-      if (test_bit(IPS_OFFLOAD_BIT, &ct->status))
+-              return 0;
+-
+       return ctnetlink_filter_match(ct, data);
+ }
+ 
+@@ -1294,11 +1291,6 @@ static int ctnetlink_del_conntrack(struct net *net, 
struct sock *ctnl,
+ 
+       ct = nf_ct_tuplehash_to_ctrack(h);
+ 
+-      if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) {
+-              nf_ct_put(ct);
+-              return -EBUSY;
+-      }
+-
+       if (cda[CTA_ID]) {
+               __be32 id = nla_get_be32(cda[CTA_ID]);
+ 


Reply via email to