commit:     f7bbb47875585cd1095f9aaab4a30a71a497d3b5
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Wed Feb  6 17:09:32 2019 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Wed Feb  6 17:09:32 2019 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=f7bbb478

proj/linux-patches: Linux patch 4.20.7

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

 0000_README             |    4 +
 1006_linux-4.20.7.patch | 3159 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 3163 insertions(+)

diff --git a/0000_README b/0000_README
index 8bd4163..82d04f4 100644
--- a/0000_README
+++ b/0000_README
@@ -67,6 +67,10 @@ Patch:  1005_linux-4.20.6.patch
 From:   http://www.kernel.org
 Desc:   Linux 4.20.6
 
+Patch:  1006_linux-4.20.7.patch
+From:   http://www.kernel.org
+Desc:   Linux 4.20.7
+
 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/1006_linux-4.20.7.patch b/1006_linux-4.20.7.patch
new file mode 100644
index 0000000..c2844b2
--- /dev/null
+++ b/1006_linux-4.20.7.patch
@@ -0,0 +1,3159 @@
+diff --git a/Makefile b/Makefile
+index 523922ea9c97..efc46cce5919 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 4
+ PATCHLEVEL = 20
+-SUBLEVEL = 6
++SUBLEVEL = 7
+ EXTRAVERSION =
+ NAME = Shy Crocodile
+ 
+diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c
+index 318394ed5c7a..5e11ad3164e0 100644
+--- a/arch/arm/mach-cns3xxx/pcie.c
++++ b/arch/arm/mach-cns3xxx/pcie.c
+@@ -83,7 +83,7 @@ static void __iomem *cns3xxx_pci_map_bus(struct pci_bus *bus,
+       } else /* remote PCI bus */
+               base = cnspci->cfg1_regs + ((busno & 0xf) << 20);
+ 
+-      return base + (where & 0xffc) + (devfn << 12);
++      return base + where + (devfn << 12);
+ }
+ 
+ static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
+index 29cdc99688f3..9859e1178e6b 100644
+--- a/arch/arm64/kernel/hibernate.c
++++ b/arch/arm64/kernel/hibernate.c
+@@ -299,8 +299,10 @@ int swsusp_arch_suspend(void)
+               dcache_clean_range(__idmap_text_start, __idmap_text_end);
+ 
+               /* Clean kvm setup code to PoC? */
+-              if (el2_reset_needed())
++              if (el2_reset_needed()) {
+                       dcache_clean_range(__hyp_idmap_text_start, 
__hyp_idmap_text_end);
++                      dcache_clean_range(__hyp_text_start, __hyp_text_end);
++              }
+ 
+               /* make the crash dump kernel image protected again */
+               crash_post_resume();
+diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
+index e1261fbaa374..17f325ba831e 100644
+--- a/arch/arm64/kernel/hyp-stub.S
++++ b/arch/arm64/kernel/hyp-stub.S
+@@ -28,6 +28,8 @@
+ #include <asm/virt.h>
+ 
+       .text
++      .pushsection    .hyp.text, "ax"
++
+       .align 11
+ 
+ ENTRY(__hyp_stub_vectors)
+diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c
+index ba6b41790fcd..b09b6f75f759 100644
+--- a/arch/arm64/kernel/kaslr.c
++++ b/arch/arm64/kernel/kaslr.c
+@@ -88,6 +88,7 @@ u64 __init kaslr_early_init(u64 dt_phys)
+        * we end up running with module randomization disabled.
+        */
+       module_alloc_base = (u64)_etext - MODULES_VSIZE;
++      __flush_dcache_area(&module_alloc_base, sizeof(module_alloc_base));
+ 
+       /*
+        * Try to map the FDT early. If this fails, we simply bail,
+diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
+index 30695a868107..5c9073bace83 100644
+--- a/arch/arm64/mm/flush.c
++++ b/arch/arm64/mm/flush.c
+@@ -33,7 +33,11 @@ void sync_icache_aliases(void *kaddr, unsigned long len)
+               __clean_dcache_area_pou(kaddr, len);
+               __flush_icache_all();
+       } else {
+-              flush_icache_range(addr, addr + len);
++              /*
++               * Don't issue kick_all_cpus_sync() after I-cache invalidation
++               * for user mappings.
++               */
++              __flush_icache_range(addr, addr + len);
+       }
+ }
+ 
+diff --git a/drivers/gpio/gpio-altera-a10sr.c 
b/drivers/gpio/gpio-altera-a10sr.c
+index 6b11f1314248..7f9e0304b510 100644
+--- a/drivers/gpio/gpio-altera-a10sr.c
++++ b/drivers/gpio/gpio-altera-a10sr.c
+@@ -66,8 +66,10 @@ static int altr_a10sr_gpio_direction_input(struct gpio_chip 
*gc,
+ static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc,
+                                           unsigned int nr, int value)
+ {
+-      if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT))
++      if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) 
{
++              altr_a10sr_gpio_set(gc, nr, value);
+               return 0;
++      }
+       return -EINVAL;
+ }
+ 
+diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c
+index e0d6a0a7bc69..e41223c05f6e 100644
+--- a/drivers/gpio/gpio-eic-sprd.c
++++ b/drivers/gpio/gpio-eic-sprd.c
+@@ -180,7 +180,18 @@ static void sprd_eic_free(struct gpio_chip *chip, 
unsigned int offset)
+ 
+ static int sprd_eic_get(struct gpio_chip *chip, unsigned int offset)
+ {
+-      return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
++      struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
++
++      switch (sprd_eic->type) {
++      case SPRD_EIC_DEBOUNCE:
++              return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
++      case SPRD_EIC_ASYNC:
++              return sprd_eic_read(chip, offset, SPRD_EIC_ASYNC_DATA);
++      case SPRD_EIC_SYNC:
++              return sprd_eic_read(chip, offset, SPRD_EIC_SYNC_DATA);
++      default:
++              return -ENOTSUPP;
++      }
+ }
+ 
+ static int sprd_eic_direction_input(struct gpio_chip *chip, unsigned int 
offset)
+@@ -368,6 +379,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, 
unsigned int flow_type)
+                       irq_set_handler_locked(data, handle_edge_irq);
+                       break;
+               case IRQ_TYPE_EDGE_BOTH:
++                      sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 
0);
+                       sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 
1);
+                       irq_set_handler_locked(data, handle_edge_irq);
+                       break;
+diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c
+index adf72dda25a2..68a35b65925a 100644
+--- a/drivers/gpio/gpio-pcf857x.c
++++ b/drivers/gpio/gpio-pcf857x.c
+@@ -84,6 +84,7 @@ MODULE_DEVICE_TABLE(of, pcf857x_of_table);
+  */
+ struct pcf857x {
+       struct gpio_chip        chip;
++      struct irq_chip         irqchip;
+       struct i2c_client       *client;
+       struct mutex            lock;           /* protect 'out' */
+       unsigned                out;            /* software latch */
+@@ -252,18 +253,6 @@ static void pcf857x_irq_bus_sync_unlock(struct irq_data 
*data)
+       mutex_unlock(&gpio->lock);
+ }
+ 
+-static struct irq_chip pcf857x_irq_chip = {
+-      .name           = "pcf857x",
+-      .irq_enable     = pcf857x_irq_enable,
+-      .irq_disable    = pcf857x_irq_disable,
+-      .irq_ack        = noop,
+-      .irq_mask       = noop,
+-      .irq_unmask     = noop,
+-      .irq_set_wake   = pcf857x_irq_set_wake,
+-      .irq_bus_lock           = pcf857x_irq_bus_lock,
+-      .irq_bus_sync_unlock    = pcf857x_irq_bus_sync_unlock,
+-};
+-
+ /*-------------------------------------------------------------------------*/
+ 
+ static int pcf857x_probe(struct i2c_client *client,
+@@ -376,8 +365,17 @@ static int pcf857x_probe(struct i2c_client *client,
+ 
+       /* Enable irqchip if we have an interrupt */
+       if (client->irq) {
++              gpio->irqchip.name = "pcf857x",
++              gpio->irqchip.irq_enable = pcf857x_irq_enable,
++              gpio->irqchip.irq_disable = pcf857x_irq_disable,
++              gpio->irqchip.irq_ack = noop,
++              gpio->irqchip.irq_mask = noop,
++              gpio->irqchip.irq_unmask = noop,
++              gpio->irqchip.irq_set_wake = pcf857x_irq_set_wake,
++              gpio->irqchip.irq_bus_lock = pcf857x_irq_bus_lock,
++              gpio->irqchip.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock,
+               status = gpiochip_irqchip_add_nested(&gpio->chip,
+-                                                   &pcf857x_irq_chip,
++                                                   &gpio->irqchip,
+                                                    0, handle_level_irq,
+                                                    IRQ_TYPE_NONE);
+               if (status) {
+@@ -392,7 +390,7 @@ static int pcf857x_probe(struct i2c_client *client,
+               if (status)
+                       goto fail;
+ 
+-              gpiochip_set_nested_irqchip(&gpio->chip, &pcf857x_irq_chip,
++              gpiochip_set_nested_irqchip(&gpio->chip, &gpio->irqchip,
+                                           client->irq);
+               gpio->irq_parent = client->irq;
+       }
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index a2cbb474901c..76913e23cf3a 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -828,7 +828,14 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
+       /* Do not leak kernel stack to userspace */
+       memset(&ge, 0, sizeof(ge));
+ 
+-      ge.timestamp = le->timestamp;
++      /*
++       * We may be running from a nested threaded interrupt in which case
++       * we didn't get the timestamp from lineevent_irq_handler().
++       */
++      if (!le->timestamp)
++              ge.timestamp = ktime_get_real_ns();
++      else
++              ge.timestamp = le->timestamp;
+ 
+       if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
+           && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
+diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
+index f82bac086666..5d500e58d5ce 100644
+--- a/drivers/gpu/drm/msm/msm_gpu.h
++++ b/drivers/gpu/drm/msm/msm_gpu.h
+@@ -63,7 +63,7 @@ struct msm_gpu_funcs {
+       struct msm_ringbuffer *(*active_ring)(struct msm_gpu *gpu);
+       void (*recover)(struct msm_gpu *gpu);
+       void (*destroy)(struct msm_gpu *gpu);
+-#ifdef CONFIG_DEBUG_FS
++#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
+       /* show GPU status in debugfs: */
+       void (*show)(struct msm_gpu *gpu, struct msm_gpu_state *state,
+                       struct drm_printer *p);
+diff --git a/drivers/infiniband/core/uverbs_main.c 
b/drivers/infiniband/core/uverbs_main.c
+index 6d373f5515b7..50a97471a2be 100644
+--- a/drivers/infiniband/core/uverbs_main.c
++++ b/drivers/infiniband/core/uverbs_main.c
+@@ -262,6 +262,9 @@ void ib_uverbs_release_file(struct kref *ref)
+       if (atomic_dec_and_test(&file->device->refcount))
+               ib_uverbs_comp_dev(file->device);
+ 
++      if (file->async_file)
++              kref_put(&file->async_file->ref,
++                       ib_uverbs_release_async_event_file);
+       put_device(&file->device->dev);
+       kfree(file);
+ }
+@@ -997,11 +1000,19 @@ void uverbs_user_mmap_disassociate(struct 
ib_uverbs_file *ufile)
+ 
+               /* Get an arbitrary mm pointer that hasn't been cleaned yet */
+               mutex_lock(&ufile->umap_lock);
+-              if (!list_empty(&ufile->umaps)) {
+-                      mm = list_first_entry(&ufile->umaps,
+-                                            struct rdma_umap_priv, list)
+-                                   ->vma->vm_mm;
+-                      mmget(mm);
++              while (!list_empty(&ufile->umaps)) {
++                      int ret;
++
++                      priv = list_first_entry(&ufile->umaps,
++                                              struct rdma_umap_priv, list);
++                      mm = priv->vma->vm_mm;
++                      ret = mmget_not_zero(mm);
++                      if (!ret) {
++                              list_del_init(&priv->list);
++                              mm = NULL;
++                              continue;
++                      }
++                      break;
+               }
+               mutex_unlock(&ufile->umap_lock);
+               if (!mm)
+@@ -1132,10 +1143,6 @@ static int ib_uverbs_close(struct inode *inode, struct 
file *filp)
+       list_del_init(&file->list);
+       mutex_unlock(&file->device->lists_mutex);
+ 
+-      if (file->async_file)
+-              kref_put(&file->async_file->ref,
+-                       ib_uverbs_release_async_event_file);
+-
+       kref_put(&file->ref, ib_uverbs_release_file);
+ 
+       return 0;
+diff --git a/drivers/infiniband/hw/hfi1/file_ops.c 
b/drivers/infiniband/hw/hfi1/file_ops.c
+index c22ebc774a6a..f9a7e9d29c8b 100644
+--- a/drivers/infiniband/hw/hfi1/file_ops.c
++++ b/drivers/infiniband/hw/hfi1/file_ops.c
+@@ -488,7 +488,7 @@ static int hfi1_file_mmap(struct file *fp, struct 
vm_area_struct *vma)
+               vmf = 1;
+               break;
+       case STATUS:
+-              if (flags & (unsigned long)(VM_WRITE | VM_EXEC)) {
++              if (flags & VM_WRITE) {
+                       ret = -EPERM;
+                       goto done;
+               }
+diff --git a/drivers/infiniband/sw/rdmavt/qp.c 
b/drivers/infiniband/sw/rdmavt/qp.c
+index 1735deb1a9d4..79ac9c3c0e5a 100644
+--- a/drivers/infiniband/sw/rdmavt/qp.c
++++ b/drivers/infiniband/sw/rdmavt/qp.c
+@@ -2903,6 +2903,8 @@ send:
+                       goto op_err;
+               if (!ret)
+                       goto rnr_nak;
++              if (wqe->length > qp->r_len)
++                      goto inv_err;
+               break;
+ 
+       case IB_WR_RDMA_WRITE_WITH_IMM:
+@@ -3071,7 +3073,10 @@ op_err:
+       goto err;
+ 
+ inv_err:
+-      send_status = IB_WC_REM_INV_REQ_ERR;
++      send_status =
++              sqp->ibqp.qp_type == IB_QPT_RC ?
++                      IB_WC_REM_INV_REQ_ERR :
++                      IB_WC_SUCCESS;
+       wc.status = IB_WC_LOC_QP_OP_ERR;
+       goto err;
+ 
+diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
+index f3afab82f3ee..7ec9c6739170 100644
+--- a/drivers/iommu/intel-iommu.c
++++ b/drivers/iommu/intel-iommu.c
+@@ -5204,7 +5204,7 @@ static void intel_iommu_put_resv_regions(struct device 
*dev,
+       struct iommu_resv_region *entry, *next;
+ 
+       list_for_each_entry_safe(entry, next, head, list) {
+-              if (entry->type == IOMMU_RESV_RESERVED)
++              if (entry->type == IOMMU_RESV_MSI)
+                       kfree(entry);
+       }
+ }
+diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c
+index ec3a5ef7fee0..cbbe6b6535be 100644
+--- a/drivers/md/raid5-cache.c
++++ b/drivers/md/raid5-cache.c
+@@ -1935,12 +1935,14 @@ out:
+ }
+ 
+ static struct stripe_head *
+-r5c_recovery_alloc_stripe(struct r5conf *conf,
+-                        sector_t stripe_sect)
++r5c_recovery_alloc_stripe(
++              struct r5conf *conf,
++              sector_t stripe_sect,
++              int noblock)
+ {
+       struct stripe_head *sh;
+ 
+-      sh = raid5_get_active_stripe(conf, stripe_sect, 0, 1, 0);
++      sh = raid5_get_active_stripe(conf, stripe_sect, 0, noblock, 0);
+       if (!sh)
+               return NULL;  /* no more stripe available */
+ 
+@@ -2150,7 +2152,7 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
+                                               stripe_sect);
+ 
+               if (!sh) {
+-                      sh = r5c_recovery_alloc_stripe(conf, stripe_sect);
++                      sh = r5c_recovery_alloc_stripe(conf, stripe_sect, 1);
+                       /*
+                        * cannot get stripe from raid5_get_active_stripe
+                        * try replay some stripes
+@@ -2159,20 +2161,29 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
+                               r5c_recovery_replay_stripes(
+                                       cached_stripe_list, ctx);
+                               sh = r5c_recovery_alloc_stripe(
+-                                      conf, stripe_sect);
++                                      conf, stripe_sect, 1);
+                       }
+                       if (!sh) {
++                              int new_size = conf->min_nr_stripes * 2;
+                               pr_debug("md/raid:%s: Increasing stripe cache 
size to %d to recovery data on journal.\n",
+                                       mdname(mddev),
+-                                      conf->min_nr_stripes * 2);
+-                              raid5_set_cache_size(mddev,
+-                                                   conf->min_nr_stripes * 2);
+-                              sh = r5c_recovery_alloc_stripe(conf,
+-                                                             stripe_sect);
++                                      new_size);
++                              ret = raid5_set_cache_size(mddev, new_size);
++                              if (conf->min_nr_stripes <= new_size / 2) {
++                                      pr_err("md/raid:%s: Cannot increase 
cache size, ret=%d, new_size=%d, min_nr_stripes=%d, max_nr_stripes=%d\n",
++                                              mdname(mddev),
++                                              ret,
++                                              new_size,
++                                              conf->min_nr_stripes,
++                                              conf->max_nr_stripes);
++                                      return -ENOMEM;
++                              }
++                              sh = r5c_recovery_alloc_stripe(
++                                      conf, stripe_sect, 0);
+                       }
+                       if (!sh) {
+                               pr_err("md/raid:%s: Cannot get enough stripes 
due to memory pressure. Recovery failed.\n",
+-                                     mdname(mddev));
++                                      mdname(mddev));
+                               return -ENOMEM;
+                       }
+                       list_add_tail(&sh->lru, cached_stripe_list);
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index 4990f0319f6c..cecea901ab8c 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -6369,6 +6369,7 @@ raid5_show_stripe_cache_size(struct mddev *mddev, char 
*page)
+ int
+ raid5_set_cache_size(struct mddev *mddev, int size)
+ {
++      int result = 0;
+       struct r5conf *conf = mddev->private;
+ 
+       if (size <= 16 || size > 32768)
+@@ -6385,11 +6386,14 @@ raid5_set_cache_size(struct mddev *mddev, int size)
+ 
+       mutex_lock(&conf->cache_size_mutex);
+       while (size > conf->max_nr_stripes)
+-              if (!grow_one_stripe(conf, GFP_KERNEL))
++              if (!grow_one_stripe(conf, GFP_KERNEL)) {
++                      conf->min_nr_stripes = conf->max_nr_stripes;
++                      result = -ENOMEM;
+                       break;
++              }
+       mutex_unlock(&conf->cache_size_mutex);
+ 
+-      return 0;
++      return result;
+ }
+ EXPORT_SYMBOL(raid5_set_cache_size);
+ 
+diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c
+index 768972af8b85..0d3b7473bc21 100644
+--- a/drivers/mmc/host/bcm2835.c
++++ b/drivers/mmc/host/bcm2835.c
+@@ -1427,6 +1427,8 @@ static int bcm2835_probe(struct platform_device *pdev)
+ 
+ err:
+       dev_dbg(dev, "%s -> err %d\n", __func__, ret);
++      if (host->dma_chan_rxtx)
++              dma_release_channel(host->dma_chan_rxtx);
+       mmc_free_host(mmc);
+ 
+       return ret;
+diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
+index 6334cc752d8b..4ff7646d0d29 100644
+--- a/drivers/mmc/host/mtk-sd.c
++++ b/drivers/mmc/host/mtk-sd.c
+@@ -846,7 +846,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned 
char timing, u32 hz)
+ 
+       if (timing == MMC_TIMING_MMC_HS400 &&
+           host->dev_comp->hs400_tune)
+-              sdr_set_field(host->base + PAD_CMD_TUNE,
++              sdr_set_field(host->base + tune_reg,
+                             MSDC_PAD_TUNE_CMDRRDLY,
+                             host->hs400_cmd_int_delay);
+       dev_dbg(host->dev, "sclk: %d, timing: %d\n", host->mmc->actual_clock,
+diff --git a/drivers/net/ethernet/freescale/ucc_geth.c 
b/drivers/net/ethernet/freescale/ucc_geth.c
+index 32e02700feaa..91d7965b3dab 100644
+--- a/drivers/net/ethernet/freescale/ucc_geth.c
++++ b/drivers/net/ethernet/freescale/ucc_geth.c
+@@ -1883,6 +1883,8 @@ static void ucc_geth_free_tx(struct ucc_geth_private 
*ugeth)
+       u16 i, j;
+       u8 __iomem *bd;
+ 
++      netdev_reset_queue(ugeth->ndev);
++
+       ug_info = ugeth->ug_info;
+       uf_info = &ug_info->uf_info;
+ 
+diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c 
b/drivers/net/ethernet/mellanox/mlx4/fw.c
+index babcfd9c0571..75213046563c 100644
+--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
++++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
+@@ -2064,9 +2064,11 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
+ {
+       struct mlx4_cmd_mailbox *mailbox;
+       __be32 *outbox;
++      u64 qword_field;
+       u32 dword_field;
+-      int err;
++      u16 word_field;
+       u8 byte_field;
++      int err;
+       static const u8 a0_dmfs_query_hw_steering[] =  {
+               [0] = MLX4_STEERING_DMFS_A0_DEFAULT,
+               [1] = MLX4_STEERING_DMFS_A0_DYNAMIC,
+@@ -2094,19 +2096,32 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
+ 
+       /* QPC/EEC/CQC/EQC/RDMARC attributes */
+ 
+-      MLX4_GET(param->qpc_base,      outbox, INIT_HCA_QPC_BASE_OFFSET);
+-      MLX4_GET(param->log_num_qps,   outbox, INIT_HCA_LOG_QP_OFFSET);
+-      MLX4_GET(param->srqc_base,     outbox, INIT_HCA_SRQC_BASE_OFFSET);
+-      MLX4_GET(param->log_num_srqs,  outbox, INIT_HCA_LOG_SRQ_OFFSET);
+-      MLX4_GET(param->cqc_base,      outbox, INIT_HCA_CQC_BASE_OFFSET);
+-      MLX4_GET(param->log_num_cqs,   outbox, INIT_HCA_LOG_CQ_OFFSET);
+-      MLX4_GET(param->altc_base,     outbox, INIT_HCA_ALTC_BASE_OFFSET);
+-      MLX4_GET(param->auxc_base,     outbox, INIT_HCA_AUXC_BASE_OFFSET);
+-      MLX4_GET(param->eqc_base,      outbox, INIT_HCA_EQC_BASE_OFFSET);
+-      MLX4_GET(param->log_num_eqs,   outbox, INIT_HCA_LOG_EQ_OFFSET);
+-      MLX4_GET(param->num_sys_eqs,   outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
+-      MLX4_GET(param->rdmarc_base,   outbox, INIT_HCA_RDMARC_BASE_OFFSET);
+-      MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET);
++      MLX4_GET(qword_field, outbox, INIT_HCA_QPC_BASE_OFFSET);
++      param->qpc_base = qword_field & ~((u64)0x1f);
++      MLX4_GET(byte_field, outbox, INIT_HCA_LOG_QP_OFFSET);
++      param->log_num_qps = byte_field & 0x1f;
++      MLX4_GET(qword_field, outbox, INIT_HCA_SRQC_BASE_OFFSET);
++      param->srqc_base = qword_field & ~((u64)0x1f);
++      MLX4_GET(byte_field, outbox, INIT_HCA_LOG_SRQ_OFFSET);
++      param->log_num_srqs = byte_field & 0x1f;
++      MLX4_GET(qword_field, outbox, INIT_HCA_CQC_BASE_OFFSET);
++      param->cqc_base = qword_field & ~((u64)0x1f);
++      MLX4_GET(byte_field, outbox, INIT_HCA_LOG_CQ_OFFSET);
++      param->log_num_cqs = byte_field & 0x1f;
++      MLX4_GET(qword_field, outbox, INIT_HCA_ALTC_BASE_OFFSET);
++      param->altc_base = qword_field;
++      MLX4_GET(qword_field, outbox, INIT_HCA_AUXC_BASE_OFFSET);
++      param->auxc_base = qword_field;
++      MLX4_GET(qword_field, outbox, INIT_HCA_EQC_BASE_OFFSET);
++      param->eqc_base = qword_field & ~((u64)0x1f);
++      MLX4_GET(byte_field, outbox, INIT_HCA_LOG_EQ_OFFSET);
++      param->log_num_eqs = byte_field & 0x1f;
++      MLX4_GET(word_field, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
++      param->num_sys_eqs = word_field & 0xfff;
++      MLX4_GET(qword_field, outbox, INIT_HCA_RDMARC_BASE_OFFSET);
++      param->rdmarc_base = qword_field & ~((u64)0x1f);
++      MLX4_GET(byte_field, outbox, INIT_HCA_LOG_RD_OFFSET);
++      param->log_rd_per_qp = byte_field & 0x7;
+ 
+       MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET);
+       if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) {
+@@ -2125,22 +2140,21 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
+       /* steering attributes */
+       if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
+               MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
+-              MLX4_GET(param->log_mc_entry_sz, outbox,
+-                       INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
+-              MLX4_GET(param->log_mc_table_sz, outbox,
+-                       INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
+-              MLX4_GET(byte_field, outbox,
+-                       INIT_HCA_FS_A0_OFFSET);
++              MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
++              param->log_mc_entry_sz = byte_field & 0x1f;
++              MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
++              param->log_mc_table_sz = byte_field & 0x1f;
++              MLX4_GET(byte_field, outbox, INIT_HCA_FS_A0_OFFSET);
+               param->dmfs_high_steer_mode =
+                       a0_dmfs_query_hw_steering[(byte_field >> 6) & 3];
+       } else {
+               MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET);
+-              MLX4_GET(param->log_mc_entry_sz, outbox,
+-                       INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
+-              MLX4_GET(param->log_mc_hash_sz,  outbox,
+-                       INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
+-              MLX4_GET(param->log_mc_table_sz, outbox,
+-                       INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
++              MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
++              param->log_mc_entry_sz = byte_field & 0x1f;
++              MLX4_GET(byte_field,  outbox, INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
++              param->log_mc_hash_sz = byte_field & 0x1f;
++              MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
++              param->log_mc_table_sz = byte_field & 0x1f;
+       }
+ 
+       /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
+@@ -2164,15 +2178,18 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
+       /* TPT attributes */
+ 
+       MLX4_GET(param->dmpt_base,  outbox, INIT_HCA_DMPT_BASE_OFFSET);
+-      MLX4_GET(param->mw_enabled, outbox, INIT_HCA_TPT_MW_OFFSET);
+-      MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
++      MLX4_GET(byte_field, outbox, INIT_HCA_TPT_MW_OFFSET);
++      param->mw_enabled = byte_field >> 7;
++      MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
++      param->log_mpt_sz = byte_field & 0x3f;
+       MLX4_GET(param->mtt_base,   outbox, INIT_HCA_MTT_BASE_OFFSET);
+       MLX4_GET(param->cmpt_base,  outbox, INIT_HCA_CMPT_BASE_OFFSET);
+ 
+       /* UAR attributes */
+ 
+       MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET);
+-      MLX4_GET(param->log_uar_sz, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
++      MLX4_GET(byte_field, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
++      param->log_uar_sz = byte_field & 0xf;
+ 
+       /* phv_check enable */
+       MLX4_GET(byte_field, outbox, INIT_HCA_CACHELINE_SZ_OFFSET);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c 
b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+index d004957328f9..3908ed554474 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+@@ -1133,13 +1133,6 @@ static int esw_vport_ingress_config(struct mlx5_eswitch 
*esw,
+       int err = 0;
+       u8 *smac_v;
+ 
+-      if (vport->info.spoofchk && !is_valid_ether_addr(vport->info.mac)) {
+-              mlx5_core_warn(esw->dev,
+-                             "vport[%d] configure ingress rules failed, 
illegal mac with spoofchk\n",
+-                             vport->vport);
+-              return -EPERM;
+-      }
+-
+       esw_vport_cleanup_ingress_rules(esw, vport);
+ 
+       if (!vport->info.vlan && !vport->info.qos && !vport->info.spoofchk) {
+@@ -1696,7 +1689,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
+       int vport_num;
+       int err;
+ 
+-      if (!MLX5_ESWITCH_MANAGER(dev))
++      if (!MLX5_VPORT_MANAGER(dev))
+               return 0;
+ 
+       esw_info(dev,
+@@ -1765,7 +1758,7 @@ abort:
+ 
+ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
+ {
+-      if (!esw || !MLX5_ESWITCH_MANAGER(esw->dev))
++      if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
+               return;
+ 
+       esw_info(esw->dev, "cleanup\n");
+@@ -1812,13 +1805,10 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch 
*esw,
+       mutex_lock(&esw->state_lock);
+       evport = &esw->vports[vport];
+ 
+-      if (evport->info.spoofchk && !is_valid_ether_addr(mac)) {
++      if (evport->info.spoofchk && !is_valid_ether_addr(mac))
+               mlx5_core_warn(esw->dev,
+-                             "MAC invalidation is not allowed when spoofchk 
is on, vport(%d)\n",
++                             "Set invalid MAC while spoofchk is on, 
vport(%d)\n",
+                              vport);
+-              err = -EPERM;
+-              goto unlock;
+-      }
+ 
+       err = mlx5_modify_nic_vport_mac_address(esw->dev, vport, mac);
+       if (err) {
+@@ -1964,6 +1954,10 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch 
*esw,
+       evport = &esw->vports[vport];
+       pschk = evport->info.spoofchk;
+       evport->info.spoofchk = spoofchk;
++      if (pschk && !is_valid_ether_addr(evport->info.mac))
++              mlx5_core_warn(esw->dev,
++                             "Spoofchk in set while MAC is invalid, 
vport(%d)\n",
++                             evport->vport);
+       if (evport->enabled && esw->mode == SRIOV_LEGACY)
+               err = esw_vport_ingress_config(esw, evport);
+       if (err)
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c 
b/drivers/net/ethernet/renesas/ravb_main.c
+index defed0d0c51d..e7f8ab6e4391 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -350,7 +350,7 @@ static int ravb_ring_init(struct net_device *ndev, int q)
+       int i;
+ 
+       priv->rx_buf_sz = (ndev->mtu <= 1492 ? PKT_BUF_SZ : ndev->mtu) +
+-              ETH_HLEN + VLAN_HLEN;
++              ETH_HLEN + VLAN_HLEN + sizeof(__sum16);
+ 
+       /* Allocate RX and TX skb rings */
+       priv->rx_skb[q] = kcalloc(priv->num_rx_ring[q],
+@@ -533,13 +533,15 @@ static void ravb_rx_csum(struct sk_buff *skb)
+ {
+       u8 *hw_csum;
+ 
+-      /* The hardware checksum is 2 bytes appended to packet data */
+-      if (unlikely(skb->len < 2))
++      /* The hardware checksum is contained in sizeof(__sum16) (2) bytes
++       * appended to packet data
++       */
++      if (unlikely(skb->len < sizeof(__sum16)))
+               return;
+-      hw_csum = skb_tail_pointer(skb) - 2;
++      hw_csum = skb_tail_pointer(skb) - sizeof(__sum16);
+       skb->csum = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum));
+       skb->ip_summed = CHECKSUM_COMPLETE;
+-      skb_trim(skb, skb->len - 2);
++      skb_trim(skb, skb->len - sizeof(__sum16));
+ }
+ 
+ /* Packet receive function for Ethernet AVB */
+diff --git a/drivers/net/ipvlan/ipvlan_main.c 
b/drivers/net/ipvlan/ipvlan_main.c
+index 4a949569ec4c..5fb541897863 100644
+--- a/drivers/net/ipvlan/ipvlan_main.c
++++ b/drivers/net/ipvlan/ipvlan_main.c
+@@ -97,12 +97,12 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, 
u16 nval)
+                       err = ipvlan_register_nf_hook(read_pnet(&port->pnet));
+                       if (!err) {
+                               mdev->l3mdev_ops = &ipvl_l3mdev_ops;
+-                              mdev->priv_flags |= IFF_L3MDEV_MASTER;
++                              mdev->priv_flags |= IFF_L3MDEV_RX_HANDLER;
+                       } else
+                               goto fail;
+               } else if (port->mode == IPVLAN_MODE_L3S) {
+                       /* Old mode was L3S */
+-                      mdev->priv_flags &= ~IFF_L3MDEV_MASTER;
++                      mdev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
+                       ipvlan_unregister_nf_hook(read_pnet(&port->pnet));
+                       mdev->l3mdev_ops = NULL;
+               }
+@@ -162,7 +162,7 @@ static void ipvlan_port_destroy(struct net_device *dev)
+       struct sk_buff *skb;
+ 
+       if (port->mode == IPVLAN_MODE_L3S) {
+-              dev->priv_flags &= ~IFF_L3MDEV_MASTER;
++              dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
+               ipvlan_unregister_nf_hook(dev_net(dev));
+               dev->l3mdev_ops = NULL;
+       }
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 6658658246d2..1e6f0da1fa8e 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -862,8 +862,6 @@ static int tun_attach(struct tun_struct *tun, struct file 
*file,
+       if (rtnl_dereference(tun->xdp_prog))
+               sock_set_flag(&tfile->sk, SOCK_XDP);
+ 
+-      tun_set_real_num_queues(tun);
+-
+       /* device is allowed to go away first, so no need to hold extra
+        * refcnt.
+        */
+@@ -875,6 +873,7 @@ static int tun_attach(struct tun_struct *tun, struct file 
*file,
+       rcu_assign_pointer(tfile->tun, tun);
+       rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
+       tun->numqueues++;
++      tun_set_real_num_queues(tun);
+ out:
+       return err;
+ }
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index ea672145f6a6..da500c77c5b9 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -57,6 +57,8 @@ module_param(napi_tx, bool, 0644);
+ #define VIRTIO_XDP_TX         BIT(0)
+ #define VIRTIO_XDP_REDIR      BIT(1)
+ 
++#define VIRTIO_XDP_FLAG       BIT(0)
++
+ /* RX packet size EWMA. The average packet size is used to determine the 
packet
+  * buffer size when refilling RX rings. As the entire RX ring may be refilled
+  * at once, the weight is chosen so that the EWMA will be insensitive to 
short-
+@@ -251,6 +253,21 @@ struct padded_vnet_hdr {
+       char padding[4];
+ };
+ 
++static bool is_xdp_frame(void *ptr)
++{
++      return (unsigned long)ptr & VIRTIO_XDP_FLAG;
++}
++
++static void *xdp_to_ptr(struct xdp_frame *ptr)
++{
++      return (void *)((unsigned long)ptr | VIRTIO_XDP_FLAG);
++}
++
++static struct xdp_frame *ptr_to_xdp(void *ptr)
++{
++      return (struct xdp_frame *)((unsigned long)ptr & ~VIRTIO_XDP_FLAG);
++}
++
+ /* Converting between virtqueue no. and kernel tx/rx queue no.
+  * 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq
+  */
+@@ -461,7 +478,8 @@ static int __virtnet_xdp_xmit_one(struct virtnet_info *vi,
+ 
+       sg_init_one(sq->sg, xdpf->data, xdpf->len);
+ 
+-      err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdpf, GFP_ATOMIC);
++      err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdp_to_ptr(xdpf),
++                                 GFP_ATOMIC);
+       if (unlikely(err))
+               return -ENOSPC; /* Caller handle free/refcnt */
+ 
+@@ -481,36 +499,37 @@ static int virtnet_xdp_xmit(struct net_device *dev,
+ {
+       struct virtnet_info *vi = netdev_priv(dev);
+       struct receive_queue *rq = vi->rq;
+-      struct xdp_frame *xdpf_sent;
+       struct bpf_prog *xdp_prog;
+       struct send_queue *sq;
+       unsigned int len;
+       int drops = 0;
+       int kicks = 0;
+       int ret, err;
++      void *ptr;
+       int i;
+ 
+-      sq = virtnet_xdp_sq(vi);
+-
+-      if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) {
+-              ret = -EINVAL;
+-              drops = n;
+-              goto out;
+-      }
+-
+       /* Only allow ndo_xdp_xmit if XDP is loaded on dev, as this
+        * indicate XDP resources have been successfully allocated.
+        */
+       xdp_prog = rcu_dereference(rq->xdp_prog);
+-      if (!xdp_prog) {
+-              ret = -ENXIO;
++      if (!xdp_prog)
++              return -ENXIO;
++
++      sq = virtnet_xdp_sq(vi);
++
++      if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) {
++              ret = -EINVAL;
+               drops = n;
+               goto out;
+       }
+ 
+       /* Free up any pending old buffers before queueing new ones. */
+-      while ((xdpf_sent = virtqueue_get_buf(sq->vq, &len)) != NULL)
+-              xdp_return_frame(xdpf_sent);
++      while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
++              if (likely(is_xdp_frame(ptr)))
++                      xdp_return_frame(ptr_to_xdp(ptr));
++              else
++                      napi_consume_skb(ptr, false);
++      }
+ 
+       for (i = 0; i < n; i++) {
+               struct xdp_frame *xdpf = frames[i];
+@@ -1329,20 +1348,28 @@ static int virtnet_receive(struct receive_queue *rq, 
int budget,
+       return stats.packets;
+ }
+ 
+-static void free_old_xmit_skbs(struct send_queue *sq)
++static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi)
+ {
+-      struct sk_buff *skb;
+       unsigned int len;
+       unsigned int packets = 0;
+       unsigned int bytes = 0;
++      void *ptr;
+ 
+-      while ((skb = virtqueue_get_buf(sq->vq, &len)) != NULL) {
+-              pr_debug("Sent skb %p\n", skb);
++      while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
++              if (likely(!is_xdp_frame(ptr))) {
++                      struct sk_buff *skb = ptr;
+ 
+-              bytes += skb->len;
+-              packets++;
++                      pr_debug("Sent skb %p\n", skb);
++
++                      bytes += skb->len;
++                      napi_consume_skb(skb, in_napi);
++              } else {
++                      struct xdp_frame *frame = ptr_to_xdp(ptr);
+ 
+-              dev_consume_skb_any(skb);
++                      bytes += frame->len;
++                      xdp_return_frame(frame);
++              }
++              packets++;
+       }
+ 
+       /* Avoid overhead when no packets have been processed
+@@ -1357,6 +1384,16 @@ static void free_old_xmit_skbs(struct send_queue *sq)
+       u64_stats_update_end(&sq->stats.syncp);
+ }
+ 
++static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
++{
++      if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
++              return false;
++      else if (q < vi->curr_queue_pairs)
++              return true;
++      else
++              return false;
++}
++
+ static void virtnet_poll_cleantx(struct receive_queue *rq)
+ {
+       struct virtnet_info *vi = rq->vq->vdev->priv;
+@@ -1364,11 +1401,11 @@ static void virtnet_poll_cleantx(struct receive_queue 
*rq)
+       struct send_queue *sq = &vi->sq[index];
+       struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, index);
+ 
+-      if (!sq->napi.weight)
++      if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
+               return;
+ 
+       if (__netif_tx_trylock(txq)) {
+-              free_old_xmit_skbs(sq);
++              free_old_xmit_skbs(sq, true);
+               __netif_tx_unlock(txq);
+       }
+ 
+@@ -1441,10 +1478,18 @@ static int virtnet_poll_tx(struct napi_struct *napi, 
int budget)
+ {
+       struct send_queue *sq = container_of(napi, struct send_queue, napi);
+       struct virtnet_info *vi = sq->vq->vdev->priv;
+-      struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, vq2txq(sq->vq));
++      unsigned int index = vq2txq(sq->vq);
++      struct netdev_queue *txq;
+ 
++      if (unlikely(is_xdp_raw_buffer_queue(vi, index))) {
++              /* We don't need to enable cb for XDP */
++              napi_complete_done(napi, 0);
++              return 0;
++      }
++
++      txq = netdev_get_tx_queue(vi->dev, index);
+       __netif_tx_lock(txq, raw_smp_processor_id());
+-      free_old_xmit_skbs(sq);
++      free_old_xmit_skbs(sq, true);
+       __netif_tx_unlock(txq);
+ 
+       virtqueue_napi_complete(napi, sq->vq, 0);
+@@ -1513,7 +1558,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, 
struct net_device *dev)
+       bool use_napi = sq->napi.weight;
+ 
+       /* Free up any pending old buffers before queueing new ones. */
+-      free_old_xmit_skbs(sq);
++      free_old_xmit_skbs(sq, false);
+ 
+       if (use_napi && kick)
+               virtqueue_enable_cb_delayed(sq->vq);
+@@ -1556,7 +1601,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, 
struct net_device *dev)
+               if (!use_napi &&
+                   unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
+                       /* More just got used, free them then recheck. */
+-                      free_old_xmit_skbs(sq);
++                      free_old_xmit_skbs(sq, false);
+                       if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
+                               netif_start_subqueue(dev, qnum);
+                               virtqueue_disable_cb(sq->vq);
+@@ -2394,6 +2439,10 @@ static int virtnet_xdp_set(struct net_device *dev, 
struct bpf_prog *prog,
+               return -ENOMEM;
+       }
+ 
++      old_prog = rtnl_dereference(vi->rq[0].xdp_prog);
++      if (!prog && !old_prog)
++              return 0;
++
+       if (prog) {
+               prog = bpf_prog_add(prog, vi->max_queue_pairs - 1);
+               if (IS_ERR(prog))
+@@ -2401,36 +2450,62 @@ static int virtnet_xdp_set(struct net_device *dev, 
struct bpf_prog *prog,
+       }
+ 
+       /* Make sure NAPI is not using any XDP TX queues for RX. */
+-      if (netif_running(dev))
+-              for (i = 0; i < vi->max_queue_pairs; i++)
++      if (netif_running(dev)) {
++              for (i = 0; i < vi->max_queue_pairs; i++) {
+                       napi_disable(&vi->rq[i].napi);
++                      virtnet_napi_tx_disable(&vi->sq[i].napi);
++              }
++      }
++
++      if (!prog) {
++              for (i = 0; i < vi->max_queue_pairs; i++) {
++                      rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
++                      if (i == 0)
++                              virtnet_restore_guest_offloads(vi);
++              }
++              synchronize_net();
++      }
+ 
+-      netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
+       err = _virtnet_set_queues(vi, curr_qp + xdp_qp);
+       if (err)
+               goto err;
++      netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
+       vi->xdp_queue_pairs = xdp_qp;
+ 
+-      for (i = 0; i < vi->max_queue_pairs; i++) {
+-              old_prog = rtnl_dereference(vi->rq[i].xdp_prog);
+-              rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
+-              if (i == 0) {
+-                      if (!old_prog)
++      if (prog) {
++              for (i = 0; i < vi->max_queue_pairs; i++) {
++                      rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
++                      if (i == 0 && !old_prog)
+                               virtnet_clear_guest_offloads(vi);
+-                      if (!prog)
+-                              virtnet_restore_guest_offloads(vi);
+               }
++      }
++
++      for (i = 0; i < vi->max_queue_pairs; i++) {
+               if (old_prog)
+                       bpf_prog_put(old_prog);
+-              if (netif_running(dev))
++              if (netif_running(dev)) {
+                       virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
++                      virtnet_napi_tx_enable(vi, vi->sq[i].vq,
++                                             &vi->sq[i].napi);
++              }
+       }
+ 
+       return 0;
+ 
+ err:
+-      for (i = 0; i < vi->max_queue_pairs; i++)
+-              virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
++      if (!prog) {
++              virtnet_clear_guest_offloads(vi);
++              for (i = 0; i < vi->max_queue_pairs; i++)
++                      rcu_assign_pointer(vi->rq[i].xdp_prog, old_prog);
++      }
++
++      if (netif_running(dev)) {
++              for (i = 0; i < vi->max_queue_pairs; i++) {
++                      virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
++                      virtnet_napi_tx_enable(vi, vi->sq[i].vq,
++                                             &vi->sq[i].napi);
++              }
++      }
+       if (prog)
+               bpf_prog_sub(prog, vi->max_queue_pairs - 1);
+       return err;
+@@ -2586,16 +2661,6 @@ static void free_receive_page_frags(struct virtnet_info 
*vi)
+                       put_page(vi->rq[i].alloc_frag.page);
+ }
+ 
+-static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
+-{
+-      if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
+-              return false;
+-      else if (q < vi->curr_queue_pairs)
+-              return true;
+-      else
+-              return false;
+-}
+-
+ static void free_unused_bufs(struct virtnet_info *vi)
+ {
+       void *buf;
+@@ -2604,10 +2669,10 @@ static void free_unused_bufs(struct virtnet_info *vi)
+       for (i = 0; i < vi->max_queue_pairs; i++) {
+               struct virtqueue *vq = vi->sq[i].vq;
+               while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
+-                      if (!is_xdp_raw_buffer_queue(vi, i))
++                      if (!is_xdp_frame(buf))
+                               dev_kfree_skb(buf);
+                       else
+-                              put_page(virt_to_head_page(buf));
++                              xdp_return_frame(ptr_to_xdp(buf));
+               }
+       }
+ 
+diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
+index ecea92f68c87..45c0b1f4cb69 100644
+--- a/drivers/of/dynamic.c
++++ b/drivers/of/dynamic.c
+@@ -275,9 +275,6 @@ void __of_detach_node(struct device_node *np)
+ 
+ /**
+  * of_detach_node() - "Unplug" a node from the device tree.
+- *
+- * The caller must hold a reference to the node.  The memory associated with
+- * the node is not freed until its refcount goes to zero.
+  */
+ int of_detach_node(struct device_node *np)
+ {
+@@ -333,6 +330,25 @@ void of_node_release(struct kobject *kobj)
+       if (!of_node_check_flag(node, OF_DYNAMIC))
+               return;
+ 
++      if (of_node_check_flag(node, OF_OVERLAY)) {
++
++              if (!of_node_check_flag(node, OF_OVERLAY_FREE_CSET)) {
++                      /* premature refcount of zero, do not free memory */
++                      pr_err("ERROR: memory leak before free overlay 
changeset,  %pOF\n",
++                             node);
++                      return;
++              }
++
++              /*
++               * If node->properties non-empty then properties were added
++               * to this node either by different overlay that has not
++               * yet been removed, or by a non-overlay mechanism.
++               */
++              if (node->properties)
++                      pr_err("ERROR: %s(), unexpected properties in %pOF\n",
++                             __func__, node);
++      }
++
+       property_list_free(node->properties);
+       property_list_free(node->deadprops);
+ 
+@@ -437,6 +453,16 @@ struct device_node *__of_node_dup(const struct 
device_node *np,
+ 
+ static void __of_changeset_entry_destroy(struct of_changeset_entry *ce)
+ {
++      if (ce->action == OF_RECONFIG_ATTACH_NODE &&
++          of_node_check_flag(ce->np, OF_OVERLAY)) {
++              if (kref_read(&ce->np->kobj.kref) > 1) {
++                      pr_err("ERROR: memory leak, expected refcount 1 instead 
of %d, of_node_get()/of_node_put() unbalanced - destroy cset entry: attach 
overlay node %pOF\n",
++                             kref_read(&ce->np->kobj.kref), ce->np);
++              } else {
++                      of_node_set_flag(ce->np, OF_OVERLAY_FREE_CSET);
++              }
++      }
++
+       of_node_put(ce->np);
+       list_del(&ce->node);
+       kfree(ce);
+diff --git a/drivers/of/kobj.c b/drivers/of/kobj.c
+index 7a0a18980b98..c72eef988041 100644
+--- a/drivers/of/kobj.c
++++ b/drivers/of/kobj.c
+@@ -133,6 +133,9 @@ int __of_attach_node_sysfs(struct device_node *np)
+       }
+       if (!name)
+               return -ENOMEM;
++
++      of_node_get(np);
++
+       rc = kobject_add(&np->kobj, parent, "%s", name);
+       kfree(name);
+       if (rc)
+@@ -159,6 +162,5 @@ void __of_detach_node_sysfs(struct device_node *np)
+               kobject_del(&np->kobj);
+       }
+ 
+-      /* finally remove the kobj_init ref */
+       of_node_put(np);
+ }
+diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
+index 1e058196f23f..9808aae4621a 100644
+--- a/drivers/of/overlay.c
++++ b/drivers/of/overlay.c
+@@ -23,6 +23,26 @@
+ 
+ #include "of_private.h"
+ 
++/**
++ * struct target - info about current target node as recursing through overlay
++ * @np:                       node where current level of overlay will be 
applied
++ * @in_livetree:      @np is a node in the live devicetree
++ *
++ * Used in the algorithm to create the portion of a changeset that describes
++ * an overlay fragment, which is a devicetree subtree.  Initially @np is a 
node
++ * in the live devicetree where the overlay subtree is targeted to be grafted
++ * into.  When recursing to the next level of the overlay subtree, the target
++ * also recurses to the next level of the live devicetree, as long as overlay
++ * subtree node also exists in the live devicetree.  When a node in the 
overlay
++ * subtree does not exist at the same level in the live devicetree, target->np
++ * points to a newly allocated node, and all subsequent targets in the subtree
++ * will be newly allocated nodes.
++ */
++struct target {
++      struct device_node *np;
++      bool in_livetree;
++};
++
+ /**
+  * struct fragment - info about fragment nodes in overlay expanded device tree
+  * @target:   target of the overlay operation
+@@ -72,8 +92,7 @@ static int devicetree_corrupt(void)
+ }
+ 
+ static int build_changeset_next_level(struct overlay_changeset *ovcs,
+-              struct device_node *target_node,
+-              const struct device_node *overlay_node);
++              struct target *target, const struct device_node *overlay_node);
+ 
+ /*
+  * of_resolve_phandles() finds the largest phandle in the live tree.
+@@ -257,14 +276,17 @@ err_free_target_path:
+ /**
+  * add_changeset_property() - add @overlay_prop to overlay changeset
+  * @ovcs:             overlay changeset
+- * @target_node:      where to place @overlay_prop in live tree
++ * @target:           where @overlay_prop will be placed
+  * @overlay_prop:     property to add or update, from overlay tree
+  * @is_symbols_prop:  1 if @overlay_prop is from node "/__symbols__"
+  *
+- * If @overlay_prop does not already exist in @target_node, add changeset 
entry
+- * to add @overlay_prop in @target_node, else add changeset entry to update
++ * If @overlay_prop does not already exist in live devicetree, add changeset
++ * entry to add @overlay_prop in @target, else add changeset entry to update
+  * value of @overlay_prop.
+  *
++ * @target may be either in the live devicetree or in a new subtree that
++ * is contained in the changeset.
++ *
+  * Some special properties are not updated (no error returned).
+  *
+  * Update of property in symbols node is not allowed.
+@@ -273,20 +295,22 @@ err_free_target_path:
+  * invalid @overlay.
+  */
+ static int add_changeset_property(struct overlay_changeset *ovcs,
+-              struct device_node *target_node,
+-              struct property *overlay_prop,
++              struct target *target, struct property *overlay_prop,
+               bool is_symbols_prop)
+ {
+       struct property *new_prop = NULL, *prop;
+       int ret = 0;
+ 
+-      prop = of_find_property(target_node, overlay_prop->name, NULL);
+-
+       if (!of_prop_cmp(overlay_prop->name, "name") ||
+           !of_prop_cmp(overlay_prop->name, "phandle") ||
+           !of_prop_cmp(overlay_prop->name, "linux,phandle"))
+               return 0;
+ 
++      if (target->in_livetree)
++              prop = of_find_property(target->np, overlay_prop->name, NULL);
++      else
++              prop = NULL;
++
+       if (is_symbols_prop) {
+               if (prop)
+                       return -EINVAL;
+@@ -299,10 +323,10 @@ static int add_changeset_property(struct 
overlay_changeset *ovcs,
+               return -ENOMEM;
+ 
+       if (!prop)
+-              ret = of_changeset_add_property(&ovcs->cset, target_node,
++              ret = of_changeset_add_property(&ovcs->cset, target->np,
+                                               new_prop);
+       else
+-              ret = of_changeset_update_property(&ovcs->cset, target_node,
++              ret = of_changeset_update_property(&ovcs->cset, target->np,
+                                                  new_prop);
+ 
+       if (ret) {
+@@ -315,14 +339,14 @@ static int add_changeset_property(struct 
overlay_changeset *ovcs,
+ 
+ /**
+  * add_changeset_node() - add @node (and children) to overlay changeset
+- * @ovcs:             overlay changeset
+- * @target_node:      where to place @node in live tree
+- * @node:             node from within overlay device tree fragment
++ * @ovcs:     overlay changeset
++ * @target:   where @node will be placed in live tree or changeset
++ * @node:     node from within overlay device tree fragment
+  *
+- * If @node does not already exist in @target_node, add changeset entry
+- * to add @node in @target_node.
++ * If @node does not already exist in @target, add changeset entry
++ * to add @node in @target.
+  *
+- * If @node already exists in @target_node, and the existing node has
++ * If @node already exists in @target, and the existing node has
+  * a phandle, the overlay node is not allowed to have a phandle.
+  *
+  * If @node has child nodes, add the children recursively via
+@@ -355,38 +379,46 @@ static int add_changeset_property(struct 
overlay_changeset *ovcs,
+  * invalid @overlay.
+  */
+ static int add_changeset_node(struct overlay_changeset *ovcs,
+-              struct device_node *target_node, struct device_node *node)
++              struct target *target, struct device_node *node)
+ {
+       const char *node_kbasename;
+       struct device_node *tchild;
++      struct target target_child;
+       int ret = 0;
+ 
+       node_kbasename = kbasename(node->full_name);
+ 
+-      for_each_child_of_node(target_node, tchild)
++      for_each_child_of_node(target->np, tchild)
+               if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name)))
+                       break;
+ 
+       if (!tchild) {
+-              tchild = __of_node_dup(node, node_kbasename);
++              tchild = __of_node_dup(NULL, node_kbasename);
+               if (!tchild)
+                       return -ENOMEM;
+ 
+-              tchild->parent = target_node;
++              tchild->parent = target->np;
++              of_node_set_flag(tchild, OF_OVERLAY);
+ 
+               ret = of_changeset_attach_node(&ovcs->cset, tchild);
+               if (ret)
+                       return ret;
+ 
+-              ret = build_changeset_next_level(ovcs, tchild, node);
++              target_child.np = tchild;
++              target_child.in_livetree = false;
++
++              ret = build_changeset_next_level(ovcs, &target_child, node);
+               of_node_put(tchild);
+               return ret;
+       }
+ 
+-      if (node->phandle && tchild->phandle)
++      if (node->phandle && tchild->phandle) {
+               ret = -EINVAL;
+-      else
+-              ret = build_changeset_next_level(ovcs, tchild, node);
++      } else {
++              target_child.np = tchild;
++              target_child.in_livetree = target->in_livetree;
++              ret = build_changeset_next_level(ovcs, &target_child, node);
++      }
+       of_node_put(tchild);
+ 
+       return ret;
+@@ -395,7 +427,7 @@ static int add_changeset_node(struct overlay_changeset 
*ovcs,
+ /**
+  * build_changeset_next_level() - add level of overlay changeset
+  * @ovcs:             overlay changeset
+- * @target_node:      where to place @overlay_node in live tree
++ * @target:           where to place @overlay_node in live tree
+  * @overlay_node:     node from within an overlay device tree fragment
+  *
+  * Add the properties (if any) and nodes (if any) from @overlay_node to the
+@@ -408,27 +440,26 @@ static int add_changeset_node(struct overlay_changeset 
*ovcs,
+  * invalid @overlay_node.
+  */
+ static int build_changeset_next_level(struct overlay_changeset *ovcs,
+-              struct device_node *target_node,
+-              const struct device_node *overlay_node)
++              struct target *target, const struct device_node *overlay_node)
+ {
+       struct device_node *child;
+       struct property *prop;
+       int ret;
+ 
+       for_each_property_of_node(overlay_node, prop) {
+-              ret = add_changeset_property(ovcs, target_node, prop, 0);
++              ret = add_changeset_property(ovcs, target, prop, 0);
+               if (ret) {
+                       pr_debug("Failed to apply prop @%pOF/%s, err=%d\n",
+-                               target_node, prop->name, ret);
++                               target->np, prop->name, ret);
+                       return ret;
+               }
+       }
+ 
+       for_each_child_of_node(overlay_node, child) {
+-              ret = add_changeset_node(ovcs, target_node, child);
++              ret = add_changeset_node(ovcs, target, child);
+               if (ret) {
+                       pr_debug("Failed to apply node @%pOF/%pOFn, err=%d\n",
+-                               target_node, child, ret);
++                               target->np, child, ret);
+                       of_node_put(child);
+                       return ret;
+               }
+@@ -441,17 +472,17 @@ static int build_changeset_next_level(struct 
overlay_changeset *ovcs,
+  * Add the properties from __overlay__ node to the @ovcs->cset changeset.
+  */
+ static int build_changeset_symbols_node(struct overlay_changeset *ovcs,
+-              struct device_node *target_node,
++              struct target *target,
+               const struct device_node *overlay_symbols_node)
+ {
+       struct property *prop;
+       int ret;
+ 
+       for_each_property_of_node(overlay_symbols_node, prop) {
+-              ret = add_changeset_property(ovcs, target_node, prop, 1);
++              ret = add_changeset_property(ovcs, target, prop, 1);
+               if (ret) {
+                       pr_debug("Failed to apply prop @%pOF/%s, err=%d\n",
+-                               target_node, prop->name, ret);
++                               target->np, prop->name, ret);
+                       return ret;
+               }
+       }
+@@ -474,6 +505,7 @@ static int build_changeset_symbols_node(struct 
overlay_changeset *ovcs,
+ static int build_changeset(struct overlay_changeset *ovcs)
+ {
+       struct fragment *fragment;
++      struct target target;
+       int fragments_count, i, ret;
+ 
+       /*
+@@ -488,7 +520,9 @@ static int build_changeset(struct overlay_changeset *ovcs)
+       for (i = 0; i < fragments_count; i++) {
+               fragment = &ovcs->fragments[i];
+ 
+-              ret = build_changeset_next_level(ovcs, fragment->target,
++              target.np = fragment->target;
++              target.in_livetree = true;
++              ret = build_changeset_next_level(ovcs, &target,
+                                                fragment->overlay);
+               if (ret) {
+                       pr_debug("apply failed '%pOF'\n", fragment->target);
+@@ -498,7 +532,10 @@ static int build_changeset(struct overlay_changeset *ovcs)
+ 
+       if (ovcs->symbols_fragment) {
+               fragment = &ovcs->fragments[ovcs->count - 1];
+-              ret = build_changeset_symbols_node(ovcs, fragment->target,
++
++              target.np = fragment->target;
++              target.in_livetree = true;
++              ret = build_changeset_symbols_node(ovcs, &target,
+                                                  fragment->overlay);
+               if (ret) {
+                       pr_debug("apply failed '%pOF'\n", fragment->target);
+@@ -516,7 +553,7 @@ static int build_changeset(struct overlay_changeset *ovcs)
+  * 1) "target" property containing the phandle of the target
+  * 2) "target-path" property containing the path of the target
+  */
+-static struct device_node *find_target_node(struct device_node *info_node)
++static struct device_node *find_target(struct device_node *info_node)
+ {
+       struct device_node *node;
+       const char *path;
+@@ -622,7 +659,7 @@ static int init_overlay_changeset(struct overlay_changeset 
*ovcs,
+ 
+               fragment = &fragments[cnt];
+               fragment->overlay = overlay_node;
+-              fragment->target = find_target_node(node);
++              fragment->target = find_target(node);
+               if (!fragment->target) {
+                       of_node_put(fragment->overlay);
+                       ret = -EINVAL;
+diff --git a/drivers/platform/x86/asus-nb-wmi.c 
b/drivers/platform/x86/asus-nb-wmi.c
+index db2af09067db..b6f2ff95c3ed 100644
+--- a/drivers/platform/x86/asus-nb-wmi.c
++++ b/drivers/platform/x86/asus-nb-wmi.c
+@@ -442,8 +442,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
+       { KE_KEY, 0x30, { KEY_VOLUMEUP } },
+       { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
+       { KE_KEY, 0x32, { KEY_MUTE } },
+-      { KE_KEY, 0x33, { KEY_DISPLAYTOGGLE } }, /* LCD on */
+-      { KE_KEY, 0x34, { KEY_DISPLAY_OFF } }, /* LCD off */
++      { KE_KEY, 0x35, { KEY_SCREENLOCK } },
+       { KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
+       { KE_KEY, 0x41, { KEY_NEXTSONG } },
+       { KE_KEY, 0x43, { KEY_STOPCD } }, /* Stop/Eject */
+diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
+index 784df2b49628..4954718b2754 100644
+--- a/drivers/vhost/net.c
++++ b/drivers/vhost/net.c
+@@ -1293,7 +1293,8 @@ static int vhost_net_open(struct inode *inode, struct 
file *f)
+               n->vqs[i].rx_ring = NULL;
+               vhost_net_buf_init(&n->vqs[i].rxq);
+       }
+-      vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX);
++      vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX,
++                     UIO_MAXIOV + VHOST_NET_BATCH);
+ 
+       vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, 
dev);
+       vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, EPOLLIN, dev);
+diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
+index 50dffe83714c..73a4adeab096 100644
+--- a/drivers/vhost/scsi.c
++++ b/drivers/vhost/scsi.c
+@@ -1628,7 +1628,7 @@ static int vhost_scsi_open(struct inode *inode, struct 
file *f)
+               vqs[i] = &vs->vqs[i].vq;
+               vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick;
+       }
+-      vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ);
++      vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ, UIO_MAXIOV);
+ 
+       vhost_scsi_init_inflight(vs, NULL);
+ 
+diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
+index c66fc8308b5e..cf82e7266397 100644
+--- a/drivers/vhost/vhost.c
++++ b/drivers/vhost/vhost.c
+@@ -390,9 +390,9 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
+               vq->indirect = kmalloc_array(UIO_MAXIOV,
+                                            sizeof(*vq->indirect),
+                                            GFP_KERNEL);
+-              vq->log = kmalloc_array(UIO_MAXIOV, sizeof(*vq->log),
++              vq->log = kmalloc_array(dev->iov_limit, sizeof(*vq->log),
+                                       GFP_KERNEL);
+-              vq->heads = kmalloc_array(UIO_MAXIOV, sizeof(*vq->heads),
++              vq->heads = kmalloc_array(dev->iov_limit, sizeof(*vq->heads),
+                                         GFP_KERNEL);
+               if (!vq->indirect || !vq->log || !vq->heads)
+                       goto err_nomem;
+@@ -414,7 +414,7 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev)
+ }
+ 
+ void vhost_dev_init(struct vhost_dev *dev,
+-                  struct vhost_virtqueue **vqs, int nvqs)
++                  struct vhost_virtqueue **vqs, int nvqs, int iov_limit)
+ {
+       struct vhost_virtqueue *vq;
+       int i;
+@@ -427,6 +427,7 @@ void vhost_dev_init(struct vhost_dev *dev,
+       dev->iotlb = NULL;
+       dev->mm = NULL;
+       dev->worker = NULL;
++      dev->iov_limit = iov_limit;
+       init_llist_head(&dev->work_list);
+       init_waitqueue_head(&dev->wait);
+       INIT_LIST_HEAD(&dev->read_list);
+diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
+index 1b675dad5e05..9490e7ddb340 100644
+--- a/drivers/vhost/vhost.h
++++ b/drivers/vhost/vhost.h
+@@ -170,9 +170,11 @@ struct vhost_dev {
+       struct list_head read_list;
+       struct list_head pending_list;
+       wait_queue_head_t wait;
++      int iov_limit;
+ };
+ 
+-void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int 
nvqs);
++void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs,
++                  int nvqs, int iov_limit);
+ long vhost_dev_set_owner(struct vhost_dev *dev);
+ bool vhost_dev_has_owner(struct vhost_dev *dev);
+ long vhost_dev_check_owner(struct vhost_dev *);
+diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
+index 98ed5be132c6..fa93f6711d8d 100644
+--- a/drivers/vhost/vsock.c
++++ b/drivers/vhost/vsock.c
+@@ -531,7 +531,7 @@ static int vhost_vsock_dev_open(struct inode *inode, 
struct file *file)
+       vsock->vqs[VSOCK_VQ_TX].handle_kick = vhost_vsock_handle_tx_kick;
+       vsock->vqs[VSOCK_VQ_RX].handle_kick = vhost_vsock_handle_rx_kick;
+ 
+-      vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs));
++      vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs), UIO_MAXIOV);
+ 
+       file->private_data = vsock;
+       spin_lock_init(&vsock->send_pkt_list_lock);
+diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
+index 47f1183b3dbe..92b572eb6d30 100644
+--- a/fs/btrfs/ctree.c
++++ b/fs/btrfs/ctree.c
+@@ -967,6 +967,48 @@ static noinline int update_ref_for_cow(struct 
btrfs_trans_handle *trans,
+       return 0;
+ }
+ 
++static struct extent_buffer *alloc_tree_block_no_bg_flush(
++                                        struct btrfs_trans_handle *trans,
++                                        struct btrfs_root *root,
++                                        u64 parent_start,
++                                        const struct btrfs_disk_key *disk_key,
++                                        int level,
++                                        u64 hint,
++                                        u64 empty_size)
++{
++      struct btrfs_fs_info *fs_info = root->fs_info;
++      struct extent_buffer *ret;
++
++      /*
++       * If we are COWing a node/leaf from the extent, chunk, device or free
++       * space trees, make sure that we do not finish block group creation of
++       * pending block groups. We do this to avoid a deadlock.
++       * COWing can result in allocation of a new chunk, and flushing pending
++       * block groups (btrfs_create_pending_block_groups()) can be triggered
++       * when finishing allocation of a new chunk. Creation of a pending block
++       * group modifies the extent, chunk, device and free space trees,
++       * therefore we could deadlock with ourselves since we are holding a
++       * lock on an extent buffer that btrfs_create_pending_block_groups() may
++       * try to COW later.
++       * For similar reasons, we also need to delay flushing pending block
++       * groups when splitting a leaf or node, from one of those trees, since
++       * we are holding a write lock on it and its parent or when inserting a
++       * new root node for one of those trees.
++       */
++      if (root == fs_info->extent_root ||
++          root == fs_info->chunk_root ||
++          root == fs_info->dev_root ||
++          root == fs_info->free_space_root)
++              trans->can_flush_pending_bgs = false;
++
++      ret = btrfs_alloc_tree_block(trans, root, parent_start,
++                                   root->root_key.objectid, disk_key, level,
++                                   hint, empty_size);
++      trans->can_flush_pending_bgs = true;
++
++      return ret;
++}
++
+ /*
+  * does the dirty work in cow of a single block.  The parent block (if
+  * supplied) is updated to point to the new cow copy.  The new buffer is 
marked
+@@ -1014,28 +1056,8 @@ static noinline int __btrfs_cow_block(struct 
btrfs_trans_handle *trans,
+       if ((root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && parent)
+               parent_start = parent->start;
+ 
+-      /*
+-       * If we are COWing a node/leaf from the extent, chunk, device or free
+-       * space trees, make sure that we do not finish block group creation of
+-       * pending block groups. We do this to avoid a deadlock.
+-       * COWing can result in allocation of a new chunk, and flushing pending
+-       * block groups (btrfs_create_pending_block_groups()) can be triggered
+-       * when finishing allocation of a new chunk. Creation of a pending block
+-       * group modifies the extent, chunk, device and free space trees,
+-       * therefore we could deadlock with ourselves since we are holding a
+-       * lock on an extent buffer that btrfs_create_pending_block_groups() may
+-       * try to COW later.
+-       */
+-      if (root == fs_info->extent_root ||
+-          root == fs_info->chunk_root ||
+-          root == fs_info->dev_root ||
+-          root == fs_info->free_space_root)
+-              trans->can_flush_pending_bgs = false;
+-
+-      cow = btrfs_alloc_tree_block(trans, root, parent_start,
+-                      root->root_key.objectid, &disk_key, level,
+-                      search_start, empty_size);
+-      trans->can_flush_pending_bgs = true;
++      cow = alloc_tree_block_no_bg_flush(trans, root, parent_start, &disk_key,
++                                         level, search_start, empty_size);
+       if (IS_ERR(cow))
+               return PTR_ERR(cow);
+ 
+@@ -3342,8 +3364,8 @@ static noinline int insert_new_root(struct 
btrfs_trans_handle *trans,
+       else
+               btrfs_node_key(lower, &lower_key, 0);
+ 
+-      c = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid,
+-                                 &lower_key, level, root->node->start, 0);
++      c = alloc_tree_block_no_bg_flush(trans, root, 0, &lower_key, level,
++                                       root->node->start, 0);
+       if (IS_ERR(c))
+               return PTR_ERR(c);
+ 
+@@ -3472,8 +3494,8 @@ static noinline int split_node(struct btrfs_trans_handle 
*trans,
+       mid = (c_nritems + 1) / 2;
+       btrfs_node_key(c, &disk_key, mid);
+ 
+-      split = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid,
+-                      &disk_key, level, c->start, 0);
++      split = alloc_tree_block_no_bg_flush(trans, root, 0, &disk_key, level,
++                                           c->start, 0);
+       if (IS_ERR(split))
+               return PTR_ERR(split);
+ 
+@@ -4257,8 +4279,8 @@ again:
+       else
+               btrfs_item_key(l, &disk_key, mid);
+ 
+-      right = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid,
+-                      &disk_key, 0, l->start, 0);
++      right = alloc_tree_block_no_bg_flush(trans, root, 0, &disk_key, 0,
++                                           l->start, 0);
+       if (IS_ERR(right))
+               return PTR_ERR(right);
+ 
+diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
+index 645fc81e2a94..38f6cb0bc5f6 100644
+--- a/fs/btrfs/super.c
++++ b/fs/btrfs/super.c
+@@ -1677,6 +1677,7 @@ static struct dentry *btrfs_mount(struct 
file_system_type *fs_type, int flags,
+                               flags | SB_RDONLY, device_name, data);
+                       if (IS_ERR(mnt_root)) {
+                               root = ERR_CAST(mnt_root);
++                              kfree(subvol_name);
+                               goto out;
+                       }
+ 
+@@ -1686,12 +1687,14 @@ static struct dentry *btrfs_mount(struct 
file_system_type *fs_type, int flags,
+                       if (error < 0) {
+                               root = ERR_PTR(error);
+                               mntput(mnt_root);
++                              kfree(subvol_name);
+                               goto out;
+                       }
+               }
+       }
+       if (IS_ERR(mnt_root)) {
+               root = ERR_CAST(mnt_root);
++              kfree(subvol_name);
+               goto out;
+       }
+ 
+diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
+index b83ab72cf855..b14e1abb891c 100644
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -50,6 +50,7 @@
+ #include "cifs_unicode.h"
+ #include "cifs_debug.h"
+ #include "cifs_fs_sb.h"
++#include "dns_resolve.h"
+ #include "ntlmssp.h"
+ #include "nterr.h"
+ #include "rfc1002pdu.h"
+@@ -318,6 +319,53 @@ static void cifs_prune_tlinks(struct work_struct *work);
+ static int cifs_setup_volume_info(struct smb_vol *volume_info, char 
*mount_data,
+                                       const char *devname, bool is_smb3);
+ 
++/*
++ * Resolve hostname and set ip addr in tcp ses. Useful for hostnames that may
++ * get their ip addresses changed at some point.
++ *
++ * This should be called with server->srv_mutex held.
++ */
++#ifdef CONFIG_CIFS_DFS_UPCALL
++static int reconn_set_ipaddr(struct TCP_Server_Info *server)
++{
++      int rc;
++      int len;
++      char *unc, *ipaddr = NULL;
++
++      if (!server->hostname)
++              return -EINVAL;
++
++      len = strlen(server->hostname) + 3;
++
++      unc = kmalloc(len, GFP_KERNEL);
++      if (!unc) {
++              cifs_dbg(FYI, "%s: failed to create UNC path\n", __func__);
++              return -ENOMEM;
++      }
++      snprintf(unc, len, "\\\\%s", server->hostname);
++
++      rc = dns_resolve_server_name_to_ip(unc, &ipaddr);
++      kfree(unc);
++
++      if (rc < 0) {
++              cifs_dbg(FYI, "%s: failed to resolve server part of %s to IP: 
%d\n",
++                       __func__, server->hostname, rc);
++              return rc;
++      }
++
++      rc = cifs_convert_address((struct sockaddr *)&server->dstaddr, ipaddr,
++                                strlen(ipaddr));
++      kfree(ipaddr);
++
++      return !rc ? -1 : 0;
++}
++#else
++static inline int reconn_set_ipaddr(struct TCP_Server_Info *server)
++{
++      return 0;
++}
++#endif
++
+ /*
+  * cifs tcp session reconnection
+  *
+@@ -418,6 +466,11 @@ cifs_reconnect(struct TCP_Server_Info *server)
+                       rc = generic_ip_connect(server);
+               if (rc) {
+                       cifs_dbg(FYI, "reconnect error %d\n", rc);
++                      rc = reconn_set_ipaddr(server);
++                      if (rc) {
++                              cifs_dbg(FYI, "%s: failed to resolve hostname: 
%d\n",
++                                       __func__, rc);
++                      }
+                       mutex_unlock(&server->srv_mutex);
+                       msleep(3000);
+               } else {
+diff --git a/fs/cifs/file.c b/fs/cifs/file.c
+index d5c3e0725849..8431854b129f 100644
+--- a/fs/cifs/file.c
++++ b/fs/cifs/file.c
+@@ -2670,6 +2670,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct 
iov_iter *from,
+ 
+                       rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
+                       if (rc) {
++                              kvfree(wdata->pages);
+                               kfree(wdata);
+                               add_credits_and_wake_if(server, credits, 0);
+                               break;
+@@ -2681,6 +2682,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct 
iov_iter *from,
+                       if (rc) {
+                               for (i = 0; i < nr_pages; i++)
+                                       put_page(wdata->pages[i]);
++                              kvfree(wdata->pages);
+                               kfree(wdata);
+                               add_credits_and_wake_if(server, credits, 0);
+                               break;
+@@ -3360,8 +3362,12 @@ cifs_send_async_read(loff_t offset, size_t len, struct 
cifsFileInfo *open_file,
+                       }
+ 
+                       rc = cifs_read_allocate_pages(rdata, npages);
+-                      if (rc)
+-                              goto error;
++                      if (rc) {
++                              kvfree(rdata->pages);
++                              kfree(rdata);
++                              add_credits_and_wake_if(server, credits, 0);
++                              break;
++                      }
+ 
+                       rdata->tailsz = PAGE_SIZE;
+               }
+@@ -3381,7 +3387,6 @@ cifs_send_async_read(loff_t offset, size_t len, struct 
cifsFileInfo *open_file,
+               if (!rdata->cfile->invalidHandle ||
+                   !(rc = cifs_reopen_file(rdata->cfile, true)))
+                       rc = server->ops->async_readv(rdata);
+-error:
+               if (rc) {
+                       add_credits_and_wake_if(server, rdata->credits, 0);
+                       kref_put(&rdata->refcount,
+diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
+index 836c59fca049..c393ac255af7 100644
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -3139,8 +3139,17 @@ smb2_readv_callback(struct mid_q_entry *mid)
+               rdata->mr = NULL;
+       }
+ #endif
+-      if (rdata->result)
++      if (rdata->result && rdata->result != -ENODATA) {
+               cifs_stats_fail_inc(tcon, SMB2_READ_HE);
++              trace_smb3_read_err(0 /* xid */,
++                                  rdata->cfile->fid.persistent_fid,
++                                  tcon->tid, tcon->ses->Suid, rdata->offset,
++                                  rdata->bytes, rdata->result);
++      } else
++              trace_smb3_read_done(0 /* xid */,
++                                   rdata->cfile->fid.persistent_fid,
++                                   tcon->tid, tcon->ses->Suid,
++                                   rdata->offset, rdata->got_bytes);
+ 
+       queue_work(cifsiod_wq, &rdata->work);
+       DeleteMidQEntry(mid);
+@@ -3215,13 +3224,11 @@ smb2_async_readv(struct cifs_readdata *rdata)
+       if (rc) {
+               kref_put(&rdata->refcount, cifs_readdata_release);
+               cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
+-              trace_smb3_read_err(rc, 0 /* xid */, io_parms.persistent_fid,
+-                                 io_parms.tcon->tid, io_parms.tcon->ses->Suid,
+-                                 io_parms.offset, io_parms.length);
+-      } else
+-              trace_smb3_read_done(0 /* xid */, io_parms.persistent_fid,
+-                                 io_parms.tcon->tid, io_parms.tcon->ses->Suid,
+-                                 io_parms.offset, io_parms.length);
++              trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid,
++                                  io_parms.tcon->tid,
++                                  io_parms.tcon->ses->Suid,
++                                  io_parms.offset, io_parms.length, rc);
++      }
+ 
+       cifs_small_buf_release(buf);
+       return rc;
+@@ -3265,10 +3272,11 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms 
*io_parms,
+               if (rc != -ENODATA) {
+                       cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
+                       cifs_dbg(VFS, "Send error in read = %d\n", rc);
++                      trace_smb3_read_err(xid, req->PersistentFileId,
++                                          io_parms->tcon->tid, ses->Suid,
++                                          io_parms->offset, io_parms->length,
++                                          rc);
+               }
+-              trace_smb3_read_err(rc, xid, req->PersistentFileId,
+-                                  io_parms->tcon->tid, ses->Suid,
+-                                  io_parms->offset, io_parms->length);
+               free_rsp_buf(resp_buftype, rsp_iov.iov_base);
+               return rc == -ENODATA ? 0 : rc;
+       } else
+@@ -3354,8 +3362,17 @@ smb2_writev_callback(struct mid_q_entry *mid)
+               wdata->mr = NULL;
+       }
+ #endif
+-      if (wdata->result)
++      if (wdata->result) {
+               cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
++              trace_smb3_write_err(0 /* no xid */,
++                                   wdata->cfile->fid.persistent_fid,
++                                   tcon->tid, tcon->ses->Suid, wdata->offset,
++                                   wdata->bytes, wdata->result);
++      } else
++              trace_smb3_write_done(0 /* no xid */,
++                                    wdata->cfile->fid.persistent_fid,
++                                    tcon->tid, tcon->ses->Suid,
++                                    wdata->offset, wdata->bytes);
+ 
+       queue_work(cifsiod_wq, &wdata->work);
+       DeleteMidQEntry(mid);
+@@ -3497,10 +3514,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
+                                    wdata->bytes, rc);
+               kref_put(&wdata->refcount, release);
+               cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
+-      } else
+-              trace_smb3_write_done(0 /* no xid */, req->PersistentFileId,
+-                                   tcon->tid, tcon->ses->Suid, wdata->offset,
+-                                   wdata->bytes);
++      }
+ 
+ async_writev_out:
+       cifs_small_buf_release(req);
+@@ -3726,8 +3740,8 @@ SMB2_query_directory(const unsigned int xid, struct 
cifs_tcon *tcon,
+                   rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) {
+                       srch_inf->endOfSearch = true;
+                       rc = 0;
+-              }
+-              cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
++              } else
++                      cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
+               goto qdir_exit;
+       }
+ 
+@@ -4325,8 +4339,8 @@ SMB2_lease_break(const unsigned int xid, struct 
cifs_tcon *tcon,
+       rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
+       cifs_small_buf_release(req);
+ 
+-      please_key_low = (__u64 *)req->LeaseKey;
+-      please_key_high = (__u64 *)(req->LeaseKey+8);
++      please_key_low = (__u64 *)lease_key;
++      please_key_high = (__u64 *)(lease_key+8);
+       if (rc) {
+               cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
+               trace_smb3_lease_err(le32_to_cpu(lease_state), tcon->tid,
+diff --git a/fs/dcache.c b/fs/dcache.c
+index 2593153471cf..44e5652b2664 100644
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -1188,15 +1188,11 @@ static enum lru_status 
dentry_lru_isolate_shrink(struct list_head *item,
+  */
+ void shrink_dcache_sb(struct super_block *sb)
+ {
+-      long freed;
+-
+       do {
+               LIST_HEAD(dispose);
+ 
+-              freed = list_lru_walk(&sb->s_dentry_lru,
++              list_lru_walk(&sb->s_dentry_lru,
+                       dentry_lru_isolate_shrink, &dispose, 1024);
+-
+-              this_cpu_sub(nr_dentry_unused, freed);
+               shrink_dentry_list(&dispose);
+       } while (list_lru_count(&sb->s_dentry_lru) > 0);
+ }
+diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
+index 8d7916570362..b08a530433ad 100644
+--- a/fs/gfs2/rgrp.c
++++ b/fs/gfs2/rgrp.c
+@@ -1780,9 +1780,9 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, 
u32 *minext,
+                       goto next_iter;
+               }
+               if (ret == -E2BIG) {
+-                      n += rbm->bii - initial_bii;
+                       rbm->bii = 0;
+                       rbm->offset = 0;
++                      n += (rbm->bii - initial_bii);
+                       goto res_covered_end_of_rgrp;
+               }
+               return ret;
+diff --git a/fs/nfs/write.c b/fs/nfs/write.c
+index 586726a590d8..d790faff8e47 100644
+--- a/fs/nfs/write.c
++++ b/fs/nfs/write.c
+@@ -621,11 +621,12 @@ static int nfs_page_async_flush(struct 
nfs_pageio_descriptor *pgio,
+       nfs_set_page_writeback(page);
+       WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags));
+ 
+-      ret = 0;
++      ret = req->wb_context->error;
+       /* If there is a fatal error that covers this write, just exit */
+-      if (nfs_error_is_fatal_on_server(req->wb_context->error))
++      if (nfs_error_is_fatal_on_server(ret))
+               goto out_launder;
+ 
++      ret = 0;
+       if (!nfs_pageio_add_request(pgio, req)) {
+               ret = pgio->pg_error;
+               /*
+@@ -635,9 +636,9 @@ static int nfs_page_async_flush(struct 
nfs_pageio_descriptor *pgio,
+                       nfs_context_set_write_error(req->wb_context, ret);
+                       if (nfs_error_is_fatal_on_server(ret))
+                               goto out_launder;
+-              }
++              } else
++                      ret = -EAGAIN;
+               nfs_redirty_request(req);
+-              ret = -EAGAIN;
+       } else
+               nfs_add_stats(page_file_mapping(page)->host,
+                               NFSIOS_WRITEPAGES, 1);
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index 857f8abf7b91..d5e38eddfb49 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -1487,6 +1487,7 @@ struct net_device_ops {
+  * @IFF_NO_RX_HANDLER: device doesn't support the rx_handler hook
+  * @IFF_FAILOVER: device is a failover master device
+  * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device
++ * @IFF_L3MDEV_RX_HANDLER: only invoke the rx handler of L3 master device
+  */
+ enum netdev_priv_flags {
+       IFF_802_1Q_VLAN                 = 1<<0,
+@@ -1518,6 +1519,7 @@ enum netdev_priv_flags {
+       IFF_NO_RX_HANDLER               = 1<<26,
+       IFF_FAILOVER                    = 1<<27,
+       IFF_FAILOVER_SLAVE              = 1<<28,
++      IFF_L3MDEV_RX_HANDLER           = 1<<29,
+ };
+ 
+ #define IFF_802_1Q_VLAN                       IFF_802_1Q_VLAN
+@@ -1548,6 +1550,7 @@ enum netdev_priv_flags {
+ #define IFF_NO_RX_HANDLER             IFF_NO_RX_HANDLER
+ #define IFF_FAILOVER                  IFF_FAILOVER
+ #define IFF_FAILOVER_SLAVE            IFF_FAILOVER_SLAVE
++#define IFF_L3MDEV_RX_HANDLER         IFF_L3MDEV_RX_HANDLER
+ 
+ /**
+  *    struct net_device - The DEVICE structure.
+@@ -4523,6 +4526,11 @@ static inline bool netif_supports_nofcs(struct 
net_device *dev)
+       return dev->priv_flags & IFF_SUPP_NOFCS;
+ }
+ 
++static inline bool netif_has_l3_rx_handler(const struct net_device *dev)
++{
++      return dev->priv_flags & IFF_L3MDEV_RX_HANDLER;
++}
++
+ static inline bool netif_is_l3_master(const struct net_device *dev)
+ {
+       return dev->priv_flags & IFF_L3MDEV_MASTER;
+diff --git a/include/linux/of.h b/include/linux/of.h
+index a5aee3c438ad..664cd5573ae2 100644
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -138,11 +138,16 @@ extern struct device_node *of_aliases;
+ extern struct device_node *of_stdout;
+ extern raw_spinlock_t devtree_lock;
+ 
+-/* flag descriptions (need to be visible even when !CONFIG_OF) */
+-#define OF_DYNAMIC    1 /* node and properties were allocated via kmalloc */
+-#define OF_DETACHED   2 /* node has been detached from the device tree */
+-#define OF_POPULATED  3 /* device already created for the node */
+-#define OF_POPULATED_BUS      4 /* of_platform_populate recursed to children 
of this node */
++/*
++ * struct device_node flag descriptions
++ * (need to be visible even when !CONFIG_OF)
++ */
++#define OF_DYNAMIC            1 /* (and properties) allocated via kmalloc */
++#define OF_DETACHED           2 /* detached from the device tree */
++#define OF_POPULATED          3 /* device already created */
++#define OF_POPULATED_BUS      4 /* platform bus created for children */
++#define OF_OVERLAY            5 /* allocated for an overlay */
++#define OF_OVERLAY_FREE_CSET  6 /* in overlay cset being freed */
+ 
+ #define OF_BAD_ADDR   ((u64)-1)
+ 
+diff --git a/include/linux/sched/coredump.h b/include/linux/sched/coredump.h
+index ec912d01126f..ecdc6542070f 100644
+--- a/include/linux/sched/coredump.h
++++ b/include/linux/sched/coredump.h
+@@ -71,6 +71,7 @@ static inline int get_dumpable(struct mm_struct *mm)
+ #define MMF_HUGE_ZERO_PAGE    23      /* mm has ever used the global huge 
zero page */
+ #define MMF_DISABLE_THP               24      /* disable THP for all VMAs */
+ #define MMF_OOM_VICTIM                25      /* mm is the oom victim */
++#define MMF_OOM_REAP_QUEUED   26      /* mm was queued for oom_reaper */
+ #define MMF_DISABLE_THP_MASK  (1 << MMF_DISABLE_THP)
+ 
+ #define MMF_INIT_MASK         (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK |\
+diff --git a/include/net/l3mdev.h b/include/net/l3mdev.h
+index 3832099289c5..128487658ff7 100644
+--- a/include/net/l3mdev.h
++++ b/include/net/l3mdev.h
+@@ -142,7 +142,8 @@ struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 
proto)
+ 
+       if (netif_is_l3_slave(skb->dev))
+               master = netdev_master_upper_dev_get_rcu(skb->dev);
+-      else if (netif_is_l3_master(skb->dev))
++      else if (netif_is_l3_master(skb->dev) ||
++               netif_has_l3_rx_handler(skb->dev))
+               master = skb->dev;
+ 
+       if (master && master->l3mdev_ops->l3mdev_l3_rcv)
+diff --git a/include/net/tls.h b/include/net/tls.h
+index 3cbcd12303fd..9f167e77d8ca 100644
+--- a/include/net/tls.h
++++ b/include/net/tls.h
+@@ -120,6 +120,8 @@ struct tls_rec {
+       struct scatterlist sg_aead_out[2];
+ 
+       char aad_space[TLS_AAD_SPACE_SIZE];
++      u8 iv_data[TLS_CIPHER_AES_GCM_128_IV_SIZE +
++                 TLS_CIPHER_AES_GCM_128_SALT_SIZE];
+       struct aead_request aead_req;
+       u8 aead_req_ctx[];
+ };
+diff --git a/kernel/exit.c b/kernel/exit.c
+index 0e21e6d21f35..55b4fa6d01eb 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -558,12 +558,14 @@ static struct task_struct *find_alive_thread(struct 
task_struct *p)
+       return NULL;
+ }
+ 
+-static struct task_struct *find_child_reaper(struct task_struct *father)
++static struct task_struct *find_child_reaper(struct task_struct *father,
++                                              struct list_head *dead)
+       __releases(&tasklist_lock)
+       __acquires(&tasklist_lock)
+ {
+       struct pid_namespace *pid_ns = task_active_pid_ns(father);
+       struct task_struct *reaper = pid_ns->child_reaper;
++      struct task_struct *p, *n;
+ 
+       if (likely(reaper != father))
+               return reaper;
+@@ -579,6 +581,12 @@ static struct task_struct *find_child_reaper(struct 
task_struct *father)
+               panic("Attempted to kill init! exitcode=0x%08x\n",
+                       father->signal->group_exit_code ?: father->exit_code);
+       }
++
++      list_for_each_entry_safe(p, n, dead, ptrace_entry) {
++              list_del_init(&p->ptrace_entry);
++              release_task(p);
++      }
++
+       zap_pid_ns_processes(pid_ns);
+       write_lock_irq(&tasklist_lock);
+ 
+@@ -668,7 +676,7 @@ static void forget_original_parent(struct task_struct 
*father,
+               exit_ptrace(father, dead);
+ 
+       /* Can drop and reacquire tasklist_lock */
+-      reaper = find_child_reaper(father);
++      reaper = find_child_reaper(father, dead);
+       if (list_empty(&father->children))
+               return;
+ 
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index a80832487981..c5c708c83af0 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -4270,7 +4270,8 @@ long follow_hugetlb_page(struct mm_struct *mm, struct 
vm_area_struct *vma,
+                               break;
+                       }
+                       if (ret & VM_FAULT_RETRY) {
+-                              if (nonblocking)
++                              if (nonblocking &&
++                                  !(fault_flags & FAULT_FLAG_RETRY_NOWAIT))
+                                       *nonblocking = 0;
+                               *nr_pages = 0;
+                               /*
+diff --git a/mm/memory-failure.c b/mm/memory-failure.c
+index 7c72f2a95785..831be5ff5f4d 100644
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -372,7 +372,8 @@ static void kill_procs(struct list_head *to_kill, int 
forcekill, bool fail,
+                       if (fail || tk->addr_valid == 0) {
+                               pr_err("Memory failure: %#lx: forcibly killing 
%s:%d because of failure to unmap corrupted page\n",
+                                      pfn, tk->tsk->comm, tk->tsk->pid);
+-                              force_sig(SIGKILL, tk->tsk);
++                              do_send_sig_info(SIGKILL, SEND_SIG_PRIV,
++                                               tk->tsk, PIDTYPE_PID);
+                       }
+ 
+                       /*
+diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
+index cea0880eadfb..21d94b5677e8 100644
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -1302,23 +1302,27 @@ int test_pages_in_a_zone(unsigned long start_pfn, 
unsigned long end_pfn,
+ static unsigned long scan_movable_pages(unsigned long start, unsigned long 
end)
+ {
+       unsigned long pfn;
+-      struct page *page;
++
+       for (pfn = start; pfn < end; pfn++) {
+-              if (pfn_valid(pfn)) {
+-                      page = pfn_to_page(pfn);
+-                      if (PageLRU(page))
+-                              return pfn;
+-                      if (__PageMovable(page))
+-                              return pfn;
+-                      if (PageHuge(page)) {
+-                              if 
(hugepage_migration_supported(page_hstate(page)) &&
+-                                  page_huge_active(page))
+-                                      return pfn;
+-                              else
+-                                      pfn = round_up(pfn + 1,
+-                                              1 << compound_order(page)) - 1;
+-                      }
+-              }
++              struct page *page, *head;
++              unsigned long skip;
++
++              if (!pfn_valid(pfn))
++                      continue;
++              page = pfn_to_page(pfn);
++              if (PageLRU(page))
++                      return pfn;
++              if (__PageMovable(page))
++                      return pfn;
++
++              if (!PageHuge(page))
++                      continue;
++              head = compound_head(page);
++              if (hugepage_migration_supported(page_hstate(head)) &&
++                  page_huge_active(head))
++                      return pfn;
++              skip = (1 << compound_order(head)) - (page - head);
++              pfn += skip - 1;
+       }
+       return 0;
+ }
+diff --git a/mm/migrate.c b/mm/migrate.c
+index f7e4bfdc13b7..9638cd59fef1 100644
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -1108,10 +1108,13 @@ out:
+        * If migration is successful, decrease refcount of the newpage
+        * which will not free the page because new page owner increased
+        * refcounter. As well, if it is LRU page, add the page to LRU
+-       * list in here.
++       * list in here. Use the old state of the isolated source page to
++       * determine if we migrated a LRU page. newpage was already unlocked
++       * and possibly modified by its owner - don't rely on the page
++       * state.
+        */
+       if (rc == MIGRATEPAGE_SUCCESS) {
+-              if (unlikely(__PageMovable(newpage)))
++              if (unlikely(!is_lru))
+                       put_page(newpage);
+               else
+                       putback_lru_page(newpage);
+diff --git a/mm/oom_kill.c b/mm/oom_kill.c
+index 6589f60d5018..cc317efdcb43 100644
+--- a/mm/oom_kill.c
++++ b/mm/oom_kill.c
+@@ -634,8 +634,8 @@ static int oom_reaper(void *unused)
+ 
+ static void wake_oom_reaper(struct task_struct *tsk)
+ {
+-      /* tsk is already queued? */
+-      if (tsk == oom_reaper_list || tsk->oom_reaper_list)
++      /* mm is already queued? */
++      if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags))
+               return;
+ 
+       get_task_struct(tsk);
+@@ -962,6 +962,13 @@ static void oom_kill_process(struct oom_control *oc, 
const char *message)
+        * still freeing memory.
+        */
+       read_lock(&tasklist_lock);
++
++      /*
++       * The task 'p' might have already exited before reaching here. The
++       * put_task_struct() will free task_struct 'p' while the loop still try
++       * to access the field of 'p', so, get an extra reference.
++       */
++      get_task_struct(p);
+       for_each_thread(p, t) {
+               list_for_each_entry(child, &t->children, sibling) {
+                       unsigned int child_points;
+@@ -981,6 +988,7 @@ static void oom_kill_process(struct oom_control *oc, const 
char *message)
+                       }
+               }
+       }
++      put_task_struct(p);
+       read_unlock(&tasklist_lock);
+ 
+       /*
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 722d50dbf8a4..43f8a4fd4968 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -8624,6 +8624,9 @@ int init_dummy_netdev(struct net_device *dev)
+       set_bit(__LINK_STATE_PRESENT, &dev->state);
+       set_bit(__LINK_STATE_START, &dev->state);
+ 
++      /* napi_busy_loop stats accounting wants this */
++      dev_net_set(dev, &init_net);
++
+       /* Note : We dont allocate pcpu_refcnt for dummy devices,
+        * because users of this 'device' dont need to change
+        * its refcount.
+diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c
+index 7efe740c06eb..511b32ea2533 100644
+--- a/net/ipv4/gre_demux.c
++++ b/net/ipv4/gre_demux.c
+@@ -25,6 +25,7 @@
+ #include <linux/spinlock.h>
+ #include <net/protocol.h>
+ #include <net/gre.h>
++#include <net/erspan.h>
+ 
+ #include <net/icmp.h>
+ #include <net/route.h>
+@@ -119,6 +120,22 @@ int gre_parse_header(struct sk_buff *skb, struct 
tnl_ptk_info *tpi,
+                       hdr_len += 4;
+       }
+       tpi->hdr_len = hdr_len;
++
++      /* ERSPAN ver 1 and 2 protocol sets GRE key field
++       * to 0 and sets the configured key in the
++       * inner erspan header field
++       */
++      if (greh->protocol == htons(ETH_P_ERSPAN) ||
++          greh->protocol == htons(ETH_P_ERSPAN2)) {
++              struct erspan_base_hdr *ershdr;
++
++              if (!pskb_may_pull(skb, nhs + hdr_len + sizeof(*ershdr)))
++                      return -EINVAL;
++
++              ershdr = (struct erspan_base_hdr *)options;
++              tpi->key = cpu_to_be32(get_session_id(ershdr));
++      }
++
+       return hdr_len;
+ }
+ EXPORT_SYMBOL(gre_parse_header);
+diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
+index 3407a82d4549..b5488c5197bc 100644
+--- a/net/ipv4/ip_gre.c
++++ b/net/ipv4/ip_gre.c
+@@ -266,20 +266,11 @@ static int erspan_rcv(struct sk_buff *skb, struct 
tnl_ptk_info *tpi,
+       int len;
+ 
+       itn = net_generic(net, erspan_net_id);
+-      len = gre_hdr_len + sizeof(*ershdr);
+-
+-      /* Check based hdr len */
+-      if (unlikely(!pskb_may_pull(skb, len)))
+-              return PACKET_REJECT;
+ 
+       iph = ip_hdr(skb);
+       ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
+       ver = ershdr->ver;
+ 
+-      /* The original GRE header does not have key field,
+-       * Use ERSPAN 10-bit session ID as key.
+-       */
+-      tpi->key = cpu_to_be32(get_session_id(ershdr));
+       tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
+                                 tpi->flags | TUNNEL_KEY,
+                                 iph->saddr, iph->daddr, tpi->key);
+@@ -1468,12 +1459,17 @@ static int ipgre_fill_info(struct sk_buff *skb, const 
struct net_device *dev)
+ {
+       struct ip_tunnel *t = netdev_priv(dev);
+       struct ip_tunnel_parm *p = &t->parms;
++      __be16 o_flags = p->o_flags;
++
++      if ((t->erspan_ver == 1 || t->erspan_ver == 2) &&
++          !t->collect_md)
++              o_flags |= TUNNEL_KEY;
+ 
+       if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
+           nla_put_be16(skb, IFLA_GRE_IFLAGS,
+                        gre_tnl_flags_to_gre_flags(p->i_flags)) ||
+           nla_put_be16(skb, IFLA_GRE_OFLAGS,
+-                       gre_tnl_flags_to_gre_flags(p->o_flags)) ||
++                       gre_tnl_flags_to_gre_flags(o_flags)) ||
+           nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
+           nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
+           nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index e3cb53b0ef67..d2b597674d60 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -5120,6 +5120,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct 
netlink_callback *cb,
+                       if (idev) {
+                               err = in6_dump_addrs(idev, skb, cb, s_ip_idx,
+                                                    &fillargs);
++                              if (err > 0)
++                                      err = 0;
+                       }
+                       goto put_tgt_net;
+               }
+diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
+index 4dc935838184..d99753b5e39b 100644
+--- a/net/ipv6/af_inet6.c
++++ b/net/ipv6/af_inet6.c
+@@ -362,6 +362,9 @@ static int __inet6_bind(struct sock *sk, struct sockaddr 
*uaddr, int addr_len,
+                                       err = -EINVAL;
+                                       goto out_unlock;
+                               }
++                      }
++
++                      if (sk->sk_bound_dev_if) {
+                               dev = dev_get_by_index_rcu(net, 
sk->sk_bound_dev_if);
+                               if (!dev) {
+                                       err = -ENODEV;
+diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
+index b529a79ac222..94903061f324 100644
+--- a/net/ipv6/ip6_gre.c
++++ b/net/ipv6/ip6_gre.c
+@@ -532,13 +532,9 @@ static int ip6erspan_rcv(struct sk_buff *skb, int 
gre_hdr_len,
+       struct ip6_tnl *tunnel;
+       u8 ver;
+ 
+-      if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr))))
+-              return PACKET_REJECT;
+-
+       ipv6h = ipv6_hdr(skb);
+       ershdr = (struct erspan_base_hdr *)skb->data;
+       ver = ershdr->ver;
+-      tpi->key = cpu_to_be32(get_session_id(ershdr));
+ 
+       tunnel = ip6gre_tunnel_lookup(skb->dev,
+                                     &ipv6h->saddr, &ipv6h->daddr, tpi->key,
+@@ -2106,12 +2102,17 @@ static int ip6gre_fill_info(struct sk_buff *skb, const 
struct net_device *dev)
+ {
+       struct ip6_tnl *t = netdev_priv(dev);
+       struct __ip6_tnl_parm *p = &t->parms;
++      __be16 o_flags = p->o_flags;
++
++      if ((p->erspan_ver == 1 || p->erspan_ver == 2) &&
++          !p->collect_md)
++              o_flags |= TUNNEL_KEY;
+ 
+       if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
+           nla_put_be16(skb, IFLA_GRE_IFLAGS,
+                        gre_tnl_flags_to_gre_flags(p->i_flags)) ||
+           nla_put_be16(skb, IFLA_GRE_OFLAGS,
+-                       gre_tnl_flags_to_gre_flags(p->o_flags)) ||
++                       gre_tnl_flags_to_gre_flags(o_flags)) ||
+           nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
+           nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
+           nla_put_in6_addr(skb, IFLA_GRE_LOCAL, &p->laddr) ||
+diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
+index eb3220812b56..edda3f9daab9 100644
+--- a/net/ipv6/ip6mr.c
++++ b/net/ipv6/ip6mr.c
+@@ -1516,6 +1516,9 @@ static void mroute_clean_tables(struct mr_table *mrt, 
bool all)
+                       continue;
+               rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
+               list_del_rcu(&c->list);
++              call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
++                                             FIB_EVENT_ENTRY_DEL,
++                                             (struct mfc6_cache *)c, mrt->id);
+               mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
+               mr_cache_put(c);
+       }
+@@ -1524,10 +1527,6 @@ static void mroute_clean_tables(struct mr_table *mrt, 
bool all)
+               spin_lock_bh(&mfc_unres_lock);
+               list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
+                       list_del(&c->list);
+-                      call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
+-                                                     FIB_EVENT_ENTRY_DEL,
+-                                                     (struct mfc6_cache *)c,
+-                                                     mrt->id);
+                       mr6_netlink_event(mrt, (struct mfc6_cache *)c,
+                                         RTM_DELROUTE);
+                       ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
+diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
+index 8181ee7e1e27..ee5403cbe655 100644
+--- a/net/ipv6/seg6_iptunnel.c
++++ b/net/ipv6/seg6_iptunnel.c
+@@ -146,6 +146,8 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct 
ipv6_sr_hdr *osrh, int proto)
+       } else {
+               ip6_flow_hdr(hdr, 0, flowlabel);
+               hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb));
++
++              memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+       }
+ 
+       hdr->nexthdr = NEXTHDR_ROUTING;
+diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
+index 26f1d435696a..fed6becc5daf 100644
+--- a/net/l2tp/l2tp_core.c
++++ b/net/l2tp/l2tp_core.c
+@@ -83,8 +83,7 @@
+ #define L2TP_SLFLAG_S    0x40000000
+ #define L2TP_SL_SEQ_MASK   0x00ffffff
+ 
+-#define L2TP_HDR_SIZE_SEQ             10
+-#define L2TP_HDR_SIZE_NOSEQ           6
++#define L2TP_HDR_SIZE_MAX             14
+ 
+ /* Default trace flags */
+ #define L2TP_DEFAULT_DEBUG_FLAGS      0
+@@ -808,7 +807,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, 
struct sk_buff *skb)
+       __skb_pull(skb, sizeof(struct udphdr));
+ 
+       /* Short packet? */
+-      if (!pskb_may_pull(skb, L2TP_HDR_SIZE_SEQ)) {
++      if (!pskb_may_pull(skb, L2TP_HDR_SIZE_MAX)) {
+               l2tp_info(tunnel, L2TP_MSG_DATA,
+                         "%s: recv short packet (len=%d)\n",
+                         tunnel->name, skb->len);
+@@ -884,6 +883,10 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, 
struct sk_buff *skb)
+               goto error;
+       }
+ 
++      if (tunnel->version == L2TP_HDR_VER_3 &&
++          l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
++              goto error;
++
+       l2tp_recv_common(session, skb, ptr, optr, hdrflags, length);
+       l2tp_session_dec_refcount(session);
+ 
+diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
+index 9c9afe94d389..b2ce90260c35 100644
+--- a/net/l2tp/l2tp_core.h
++++ b/net/l2tp/l2tp_core.h
+@@ -301,6 +301,26 @@ static inline bool l2tp_tunnel_uses_xfrm(const struct 
l2tp_tunnel *tunnel)
+ }
+ #endif
+ 
++static inline int l2tp_v3_ensure_opt_in_linear(struct l2tp_session *session, 
struct sk_buff *skb,
++                                             unsigned char **ptr, unsigned 
char **optr)
++{
++      int opt_len = session->peer_cookie_len + 
l2tp_get_l2specific_len(session);
++
++      if (opt_len > 0) {
++              int off = *ptr - *optr;
++
++              if (!pskb_may_pull(skb, off + opt_len))
++                      return -1;
++
++              if (skb->data != *optr) {
++                      *optr = skb->data;
++                      *ptr = skb->data + off;
++              }
++      }
++
++      return 0;
++}
++
+ #define l2tp_printk(ptr, type, func, fmt, ...)                                
\
+ do {                                                                  \
+       if (((ptr)->debug) & (type))                                    \
+diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
+index 35f6f86d4dcc..d4c60523c549 100644
+--- a/net/l2tp/l2tp_ip.c
++++ b/net/l2tp/l2tp_ip.c
+@@ -165,6 +165,9 @@ static int l2tp_ip_recv(struct sk_buff *skb)
+               print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
+       }
+ 
++      if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
++              goto discard_sess;
++
+       l2tp_recv_common(session, skb, ptr, optr, 0, skb->len);
+       l2tp_session_dec_refcount(session);
+ 
+diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
+index 237f1a4a0b0c..0ae6899edac0 100644
+--- a/net/l2tp/l2tp_ip6.c
++++ b/net/l2tp/l2tp_ip6.c
+@@ -178,6 +178,9 @@ static int l2tp_ip6_recv(struct sk_buff *skb)
+               print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
+       }
+ 
++      if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
++              goto discard_sess;
++
+       l2tp_recv_common(session, skb, ptr, optr, 0, skb->len);
+       l2tp_session_dec_refcount(session);
+ 
+diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c
+index cbd51ed5a2d7..908e53ab47a4 100644
+--- a/net/netrom/nr_timer.c
++++ b/net/netrom/nr_timer.c
+@@ -52,21 +52,21 @@ void nr_start_t1timer(struct sock *sk)
+ {
+       struct nr_sock *nr = nr_sk(sk);
+ 
+-      mod_timer(&nr->t1timer, jiffies + nr->t1);
++      sk_reset_timer(sk, &nr->t1timer, jiffies + nr->t1);
+ }
+ 
+ void nr_start_t2timer(struct sock *sk)
+ {
+       struct nr_sock *nr = nr_sk(sk);
+ 
+-      mod_timer(&nr->t2timer, jiffies + nr->t2);
++      sk_reset_timer(sk, &nr->t2timer, jiffies + nr->t2);
+ }
+ 
+ void nr_start_t4timer(struct sock *sk)
+ {
+       struct nr_sock *nr = nr_sk(sk);
+ 
+-      mod_timer(&nr->t4timer, jiffies + nr->t4);
++      sk_reset_timer(sk, &nr->t4timer, jiffies + nr->t4);
+ }
+ 
+ void nr_start_idletimer(struct sock *sk)
+@@ -74,37 +74,37 @@ void nr_start_idletimer(struct sock *sk)
+       struct nr_sock *nr = nr_sk(sk);
+ 
+       if (nr->idle > 0)
+-              mod_timer(&nr->idletimer, jiffies + nr->idle);
++              sk_reset_timer(sk, &nr->idletimer, jiffies + nr->idle);
+ }
+ 
+ void nr_start_heartbeat(struct sock *sk)
+ {
+-      mod_timer(&sk->sk_timer, jiffies + 5 * HZ);
++      sk_reset_timer(sk, &sk->sk_timer, jiffies + 5 * HZ);
+ }
+ 
+ void nr_stop_t1timer(struct sock *sk)
+ {
+-      del_timer(&nr_sk(sk)->t1timer);
++      sk_stop_timer(sk, &nr_sk(sk)->t1timer);
+ }
+ 
+ void nr_stop_t2timer(struct sock *sk)
+ {
+-      del_timer(&nr_sk(sk)->t2timer);
++      sk_stop_timer(sk, &nr_sk(sk)->t2timer);
+ }
+ 
+ void nr_stop_t4timer(struct sock *sk)
+ {
+-      del_timer(&nr_sk(sk)->t4timer);
++      sk_stop_timer(sk, &nr_sk(sk)->t4timer);
+ }
+ 
+ void nr_stop_idletimer(struct sock *sk)
+ {
+-      del_timer(&nr_sk(sk)->idletimer);
++      sk_stop_timer(sk, &nr_sk(sk)->idletimer);
+ }
+ 
+ void nr_stop_heartbeat(struct sock *sk)
+ {
+-      del_timer(&sk->sk_timer);
++      sk_stop_timer(sk, &sk->sk_timer);
+ }
+ 
+ int nr_t1timer_running(struct sock *sk)
+diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
+index 77e9f85a2c92..f2ff21d7df08 100644
+--- a/net/rose/rose_route.c
++++ b/net/rose/rose_route.c
+@@ -850,6 +850,7 @@ void rose_link_device_down(struct net_device *dev)
+ 
+ /*
+  *    Route a frame to an appropriate AX.25 connection.
++ *    A NULL ax25_cb indicates an internally generated frame.
+  */
+ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
+ {
+@@ -867,6 +868,10 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
+ 
+       if (skb->len < ROSE_MIN_LEN)
+               return res;
++
++      if (!ax25)
++              return rose_loopback_queue(skb, NULL);
++
+       frametype = skb->data[2];
+       lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
+       if (frametype == ROSE_CALL_REQUEST &&
+diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
+index 0bae07e9c9e7..4fede55b9010 100644
+--- a/net/sctp/ipv6.c
++++ b/net/sctp/ipv6.c
+@@ -277,7 +277,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, 
union sctp_addr *saddr,
+ 
+       if (saddr) {
+               fl6->saddr = saddr->v6.sin6_addr;
+-              fl6->fl6_sport = saddr->v6.sin6_port;
++              if (!fl6->fl6_sport)
++                      fl6->fl6_sport = saddr->v6.sin6_port;
+ 
+               pr_debug("src=%pI6 - ", &fl6->saddr);
+       }
+diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
+index 85af878f5668..8410ccc57c40 100644
+--- a/net/sctp/protocol.c
++++ b/net/sctp/protocol.c
+@@ -440,7 +440,8 @@ static void sctp_v4_get_dst(struct sctp_transport *t, 
union sctp_addr *saddr,
+       }
+       if (saddr) {
+               fl4->saddr = saddr->v4.sin_addr.s_addr;
+-              fl4->fl4_sport = saddr->v4.sin_port;
++              if (!fl4->fl4_sport)
++                      fl4->fl4_sport = saddr->v4.sin_port;
+       }
+ 
+       pr_debug("%s: dst:%pI4, src:%pI4 - ", __func__, &fl4->daddr,
+diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
+index f4ac6c592e13..d05c57664e36 100644
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -495,7 +495,10 @@ struct sctp_chunk *sctp_make_init_ack(const struct 
sctp_association *asoc,
+        *
+        * [INIT ACK back to where the INIT came from.]
+        */
+-      retval->transport = chunk->transport;
++      if (chunk->transport)
++              retval->transport =
++                      sctp_assoc_lookup_paddr(asoc,
++                                              &chunk->transport->ipaddr);
+ 
+       retval->subh.init_hdr =
+               sctp_addto_chunk(retval, sizeof(initack), &initack);
+@@ -642,8 +645,10 @@ struct sctp_chunk *sctp_make_cookie_ack(const struct 
sctp_association *asoc,
+        *
+        * [COOKIE ACK back to where the COOKIE ECHO came from.]
+        */
+-      if (retval && chunk)
+-              retval->transport = chunk->transport;
++      if (retval && chunk && chunk->transport)
++              retval->transport =
++                      sctp_assoc_lookup_paddr(asoc,
++                                              &chunk->transport->ipaddr);
+ 
+       return retval;
+ }
+diff --git a/net/sctp/stream.c b/net/sctp/stream.c
+index 3892e7630f3a..80e0ae5534ec 100644
+--- a/net/sctp/stream.c
++++ b/net/sctp/stream.c
+@@ -585,9 +585,9 @@ struct sctp_chunk *sctp_process_strreset_outreq(
+       struct sctp_strreset_outreq *outreq = param.v;
+       struct sctp_stream *stream = &asoc->stream;
+       __u32 result = SCTP_STRRESET_DENIED;
+-      __u16 i, nums, flags = 0;
+       __be16 *str_p = NULL;
+       __u32 request_seq;
++      __u16 i, nums;
+ 
+       request_seq = ntohl(outreq->request_seq);
+ 
+@@ -615,6 +615,15 @@ struct sctp_chunk *sctp_process_strreset_outreq(
+       if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ))
+               goto out;
+ 
++      nums = (ntohs(param.p->length) - sizeof(*outreq)) / sizeof(__u16);
++      str_p = outreq->list_of_streams;
++      for (i = 0; i < nums; i++) {
++              if (ntohs(str_p[i]) >= stream->incnt) {
++                      result = SCTP_STRRESET_ERR_WRONG_SSN;
++                      goto out;
++              }
++      }
++
+       if (asoc->strreset_chunk) {
+               if (!sctp_chunk_lookup_strreset_param(
+                               asoc, outreq->response_seq,
+@@ -637,32 +646,19 @@ struct sctp_chunk *sctp_process_strreset_outreq(
+                       sctp_chunk_put(asoc->strreset_chunk);
+                       asoc->strreset_chunk = NULL;
+               }
+-
+-              flags = SCTP_STREAM_RESET_INCOMING_SSN;
+       }
+ 
+-      nums = (ntohs(param.p->length) - sizeof(*outreq)) / sizeof(__u16);
+-      if (nums) {
+-              str_p = outreq->list_of_streams;
+-              for (i = 0; i < nums; i++) {
+-                      if (ntohs(str_p[i]) >= stream->incnt) {
+-                              result = SCTP_STRRESET_ERR_WRONG_SSN;
+-                              goto out;
+-                      }
+-              }
+-
++      if (nums)
+               for (i = 0; i < nums; i++)
+                       SCTP_SI(stream, ntohs(str_p[i]))->mid = 0;
+-      } else {
++      else
+               for (i = 0; i < stream->incnt; i++)
+                       SCTP_SI(stream, i)->mid = 0;
+-      }
+ 
+       result = SCTP_STRRESET_PERFORMED;
+ 
+       *evp = sctp_ulpevent_make_stream_reset_event(asoc,
+-              flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p,
+-              GFP_ATOMIC);
++              SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
+ 
+ out:
+       sctp_update_strreset_result(asoc, result);
+@@ -738,9 +734,6 @@ struct sctp_chunk *sctp_process_strreset_inreq(
+ 
+       result = SCTP_STRRESET_PERFORMED;
+ 
+-      *evp = sctp_ulpevent_make_stream_reset_event(asoc,
+-              SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
+-
+ out:
+       sctp_update_strreset_result(asoc, result);
+ err:
+@@ -873,6 +866,14 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
+       if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ))
+               goto out;
+ 
++      in = ntohs(addstrm->number_of_streams);
++      incnt = stream->incnt + in;
++      if (!in || incnt > SCTP_MAX_STREAM)
++              goto out;
++
++      if (sctp_stream_alloc_in(stream, incnt, GFP_ATOMIC))
++              goto out;
++
+       if (asoc->strreset_chunk) {
+               if (!sctp_chunk_lookup_strreset_param(
+                       asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS)) {
+@@ -896,14 +897,6 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
+               }
+       }
+ 
+-      in = ntohs(addstrm->number_of_streams);
+-      incnt = stream->incnt + in;
+-      if (!in || incnt > SCTP_MAX_STREAM)
+-              goto out;
+-
+-      if (sctp_stream_alloc_in(stream, incnt, GFP_ATOMIC))
+-              goto out;
+-
+       stream->incnt = incnt;
+ 
+       result = SCTP_STRRESET_PERFORMED;
+@@ -973,9 +966,6 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in(
+ 
+       result = SCTP_STRRESET_PERFORMED;
+ 
+-      *evp = sctp_ulpevent_make_stream_change_event(asoc,
+-              0, 0, ntohs(addstrm->number_of_streams), GFP_ATOMIC);
+-
+ out:
+       sctp_update_strreset_result(asoc, result);
+ err:
+@@ -1036,10 +1026,10 @@ struct sctp_chunk *sctp_process_strreset_resp(
+                                       sout->mid_uo = 0;
+                               }
+                       }
+-
+-                      flags = SCTP_STREAM_RESET_OUTGOING_SSN;
+               }
+ 
++              flags |= SCTP_STREAM_RESET_OUTGOING_SSN;
++
+               for (i = 0; i < stream->outcnt; i++)
+                       SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
+ 
+@@ -1058,6 +1048,8 @@ struct sctp_chunk *sctp_process_strreset_resp(
+               nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) /
+                      sizeof(__u16);
+ 
++              flags |= SCTP_STREAM_RESET_INCOMING_SSN;
++
+               *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags,
+                       nums, str_p, GFP_ATOMIC);
+       } else if (req->type == SCTP_PARAM_RESET_TSN_REQUEST) {
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index 29b27858fff1..419314ba94ec 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -439,6 +439,8 @@ static int tls_do_encryption(struct sock *sk,
+       struct scatterlist *sge = sk_msg_elem(msg_en, start);
+       int rc;
+ 
++      memcpy(rec->iv_data, tls_ctx->tx.iv, sizeof(rec->iv_data));
++
+       sge->offset += tls_ctx->tx.prepend_size;
+       sge->length -= tls_ctx->tx.prepend_size;
+ 
+@@ -448,7 +450,7 @@ static int tls_do_encryption(struct sock *sk,
+       aead_request_set_ad(aead_req, TLS_AAD_SPACE_SIZE);
+       aead_request_set_crypt(aead_req, rec->sg_aead_in,
+                              rec->sg_aead_out,
+-                             data_len, tls_ctx->tx.iv);
++                             data_len, rec->iv_data);
+ 
+       aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                 tls_encrypt_done, sk);
+@@ -1768,7 +1770,9 @@ void tls_sw_free_resources_tx(struct sock *sk)
+       if (atomic_read(&ctx->encrypt_pending))
+               crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
+ 
++      release_sock(sk);
+       cancel_delayed_work_sync(&ctx->tx_work.work);
++      lock_sock(sk);
+ 
+       /* Tx whatever records we can transmit and abandon the rest */
+       tls_tx_records(sk, -1);
+diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
+index 40013b26f671..6c99fa8ac5fa 100644
+--- a/sound/core/pcm_lib.c
++++ b/sound/core/pcm_lib.c
+@@ -2112,6 +2112,13 @@ int pcm_lib_apply_appl_ptr(struct snd_pcm_substream 
*substream,
+       return 0;
+ }
+ 
++/* allow waiting for a capture stream that hasn't been started */
++#if IS_ENABLED(CONFIG_SND_PCM_OSS)
++#define wait_capture_start(substream) ((substream)->oss.oss)
++#else
++#define wait_capture_start(substream) false
++#endif
++
+ /* the common loop for read/write data */
+ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
+                                    void *data, bool interleaved,
+@@ -2182,7 +2189,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct 
snd_pcm_substream *substream,
+                       err = snd_pcm_start(substream);
+                       if (err < 0)
+                               goto _end_unlock;
+-              } else {
++              } else if (!wait_capture_start(substream)) {
+                       /* nothing to do */
+                       err = 0;
+                       goto _end_unlock;
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 8ddd016c04d0..0bfd78b7e0ca 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -117,6 +117,7 @@ struct alc_spec {
+       int codec_variant;      /* flag for other variants */
+       unsigned int has_alc5505_dsp:1;
+       unsigned int no_depop_delay:1;
++      unsigned int done_hp_init:1;
+ 
+       /* for PLL fix */
+       hda_nid_t pll_nid;
+@@ -3372,6 +3373,48 @@ static void alc_default_shutup(struct hda_codec *codec)
+       snd_hda_shutup_pins(codec);
+ }
+ 
++static void alc294_hp_init(struct hda_codec *codec)
++{
++      struct alc_spec *spec = codec->spec;
++      hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
++      int i, val;
++
++      if (!hp_pin)
++              return;
++
++      snd_hda_codec_write(codec, hp_pin, 0,
++                          AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
++
++      msleep(100);
++
++      snd_hda_codec_write(codec, hp_pin, 0,
++                          AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
++
++      alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual 
mode */
++      alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop 
procedure start */
++
++      /* Wait for depop procedure finish  */
++      val = alc_read_coefex_idx(codec, 0x58, 0x01);
++      for (i = 0; i < 20 && val & 0x0080; i++) {
++              msleep(50);
++              val = alc_read_coefex_idx(codec, 0x58, 0x01);
++      }
++      /* Set HP depop to auto mode */
++      alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
++      msleep(50);
++}
++
++static void alc294_init(struct hda_codec *codec)
++{
++      struct alc_spec *spec = codec->spec;
++
++      if (!spec->done_hp_init) {
++              alc294_hp_init(codec);
++              spec->done_hp_init = true;
++      }
++      alc_default_init(codec);
++}
++
+ static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
+                            unsigned int val)
+ {
+@@ -7288,37 +7331,6 @@ static void alc269_fill_coef(struct hda_codec *codec)
+       alc_update_coef_idx(codec, 0x4, 0, 1<<11);
+ }
+ 
+-static void alc294_hp_init(struct hda_codec *codec)
+-{
+-      struct alc_spec *spec = codec->spec;
+-      hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+-      int i, val;
+-
+-      if (!hp_pin)
+-              return;
+-
+-      snd_hda_codec_write(codec, hp_pin, 0,
+-                          AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+-
+-      msleep(100);
+-
+-      snd_hda_codec_write(codec, hp_pin, 0,
+-                          AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+-
+-      alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual 
mode */
+-      alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop 
procedure start */
+-
+-      /* Wait for depop procedure finish  */
+-      val = alc_read_coefex_idx(codec, 0x58, 0x01);
+-      for (i = 0; i < 20 && val & 0x0080; i++) {
+-              msleep(50);
+-              val = alc_read_coefex_idx(codec, 0x58, 0x01);
+-      }
+-      /* Set HP depop to auto mode */
+-      alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
+-      msleep(50);
+-}
+-
+ /*
+  */
+ static int patch_alc269(struct hda_codec *codec)
+@@ -7444,7 +7456,7 @@ static int patch_alc269(struct hda_codec *codec)
+               spec->codec_variant = ALC269_TYPE_ALC294;
+               spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback 
mixer path */
+               alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* 
UAJ MIC Vref control by verb */
+-              alc294_hp_init(codec);
++              spec->init_hook = alc294_init;
+               break;
+       case 0x10ec0300:
+               spec->codec_variant = ALC269_TYPE_ALC300;
+@@ -7456,7 +7468,7 @@ static int patch_alc269(struct hda_codec *codec)
+               spec->codec_variant = ALC269_TYPE_ALC700;
+               spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback 
mixer path */
+               alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack 
auto trigger control */
+-              alc294_hp_init(codec);
++              spec->init_hook = alc294_init;
+               break;
+ 
+       }
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 6623cafc94f2..7e93686a430a 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1373,6 +1373,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct 
snd_usb_audio *chip,
+                       return SNDRV_PCM_FMTBIT_DSD_U32_BE;
+               break;
+ 
++      case USB_ID(0x10cb, 0x0103): /* The Bit Opus #3; with fp->dsd_raw */
+       case USB_ID(0x152a, 0x85de): /* SMSL D1 DAC */
+       case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
+       case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */
+diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c 
b/tools/testing/selftests/seccomp/seccomp_bpf.c
+index c9a2abf8be1b..0692d5dab729 100644
+--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
++++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
+@@ -1563,7 +1563,16 @@ TEST_F(TRACE_poke, getpid_runs_normally)
+ #ifdef SYSCALL_NUM_RET_SHARE_REG
+ # define EXPECT_SYSCALL_RETURN(val, action)   EXPECT_EQ(-1, action)
+ #else
+-# define EXPECT_SYSCALL_RETURN(val, action)   EXPECT_EQ(val, action)
++# define EXPECT_SYSCALL_RETURN(val, action)           \
++      do {                                            \
++              errno = 0;                              \
++              if (val < 0) {                          \
++                      EXPECT_EQ(-1, action);          \
++                      EXPECT_EQ(-(val), errno);       \
++              } else {                                \
++                      EXPECT_EQ(val, action);         \
++              }                                       \
++      } while (0)
+ #endif
+ 
+ /* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
+@@ -1602,7 +1611,7 @@ int get_syscall(struct __test_metadata *_metadata, pid_t 
tracee)
+ 
+ /* Architecture-specific syscall changing routine. */
+ void change_syscall(struct __test_metadata *_metadata,
+-                  pid_t tracee, int syscall)
++                  pid_t tracee, int syscall, int result)
+ {
+       int ret;
+       ARCH_REGS regs;
+@@ -1661,7 +1670,7 @@ void change_syscall(struct __test_metadata *_metadata,
+ #ifdef SYSCALL_NUM_RET_SHARE_REG
+               TH_LOG("Can't modify syscall return on this architecture");
+ #else
+-              regs.SYSCALL_RET = EPERM;
++              regs.SYSCALL_RET = result;
+ #endif
+ 
+ #ifdef HAVE_GETREGS
+@@ -1689,14 +1698,19 @@ void tracer_syscall(struct __test_metadata *_metadata, 
pid_t tracee,
+       case 0x1002:
+               /* change getpid to getppid. */
+               EXPECT_EQ(__NR_getpid, get_syscall(_metadata, tracee));
+-              change_syscall(_metadata, tracee, __NR_getppid);
++              change_syscall(_metadata, tracee, __NR_getppid, 0);
+               break;
+       case 0x1003:
+-              /* skip gettid. */
++              /* skip gettid with valid return code. */
+               EXPECT_EQ(__NR_gettid, get_syscall(_metadata, tracee));
+-              change_syscall(_metadata, tracee, -1);
++              change_syscall(_metadata, tracee, -1, 45000);
+               break;
+       case 0x1004:
++              /* skip openat with error. */
++              EXPECT_EQ(__NR_openat, get_syscall(_metadata, tracee));
++              change_syscall(_metadata, tracee, -1, -ESRCH);
++              break;
++      case 0x1005:
+               /* do nothing (allow getppid) */
+               EXPECT_EQ(__NR_getppid, get_syscall(_metadata, tracee));
+               break;
+@@ -1729,9 +1743,11 @@ void tracer_ptrace(struct __test_metadata *_metadata, 
pid_t tracee,
+       nr = get_syscall(_metadata, tracee);
+ 
+       if (nr == __NR_getpid)
+-              change_syscall(_metadata, tracee, __NR_getppid);
++              change_syscall(_metadata, tracee, __NR_getppid, 0);
++      if (nr == __NR_gettid)
++              change_syscall(_metadata, tracee, -1, 45000);
+       if (nr == __NR_openat)
+-              change_syscall(_metadata, tracee, -1);
++              change_syscall(_metadata, tracee, -1, -ESRCH);
+ }
+ 
+ FIXTURE_DATA(TRACE_syscall) {
+@@ -1748,8 +1764,10 @@ FIXTURE_SETUP(TRACE_syscall)
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1002),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_gettid, 0, 1),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1003),
+-              BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
++              BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_openat, 0, 1),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1004),
++              BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
++              BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1005),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+       };
+ 
+@@ -1797,15 +1815,26 @@ TEST_F(TRACE_syscall, ptrace_syscall_redirected)
+       EXPECT_NE(self->mypid, syscall(__NR_getpid));
+ }
+ 
+-TEST_F(TRACE_syscall, ptrace_syscall_dropped)
++TEST_F(TRACE_syscall, ptrace_syscall_errno)
++{
++      /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
++      teardown_trace_fixture(_metadata, self->tracer);
++      self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
++                                         true);
++
++      /* Tracer should skip the open syscall, resulting in ESRCH. */
++      EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
++}
++
++TEST_F(TRACE_syscall, ptrace_syscall_faked)
+ {
+       /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
+       teardown_trace_fixture(_metadata, self->tracer);
+       self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
+                                          true);
+ 
+-      /* Tracer should skip the open syscall, resulting in EPERM. */
+-      EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_openat));
++      /* Tracer should skip the gettid syscall, resulting fake pid. */
++      EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
+ }
+ 
+ TEST_F(TRACE_syscall, syscall_allowed)
+@@ -1838,7 +1867,21 @@ TEST_F(TRACE_syscall, syscall_redirected)
+       EXPECT_NE(self->mypid, syscall(__NR_getpid));
+ }
+ 
+-TEST_F(TRACE_syscall, syscall_dropped)
++TEST_F(TRACE_syscall, syscall_errno)
++{
++      long ret;
++
++      ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
++      ASSERT_EQ(0, ret);
++
++      ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
++      ASSERT_EQ(0, ret);
++
++      /* openat has been skipped and an errno return. */
++      EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
++}
++
++TEST_F(TRACE_syscall, syscall_faked)
+ {
+       long ret;
+ 
+@@ -1849,8 +1892,7 @@ TEST_F(TRACE_syscall, syscall_dropped)
+       ASSERT_EQ(0, ret);
+ 
+       /* gettid has been skipped and an altered return value stored. */
+-      EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_gettid));
+-      EXPECT_NE(self->mytid, syscall(__NR_gettid));
++      EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
+ }
+ 
+ TEST_F(TRACE_syscall, skip_after_RET_TRACE)

Reply via email to