commit:     6ae97f813849bf6707efc7a41ec1f990486b4d8b
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Tue May 30 12:58:10 2023 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Tue May 30 12:58:10 2023 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=6ae97f81

Linux patch 4.14.316

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

 0000_README               |    4 +
 1315_linux-4.14.316.patch | 3880 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 3884 insertions(+)

diff --git a/0000_README b/0000_README
index 3386c191..21cbbeae 100644
--- a/0000_README
+++ b/0000_README
@@ -1303,6 +1303,10 @@ Patch:  1314_linux-4.14.315.patch
 From:   https://www.kernel.org
 Desc:   Linux 4.14.315
 
+Patch:  1315_linux-4.14.316.patch
+From:   https://www.kernel.org
+Desc:   Linux 4.14.316
+
 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/1315_linux-4.14.316.patch b/1315_linux-4.14.316.patch
new file mode 100644
index 00000000..ffa8fd54
--- /dev/null
+++ b/1315_linux-4.14.316.patch
@@ -0,0 +1,3880 @@
+diff --git a/Makefile b/Makefile
+index 78a88e76c2536..4962d14e36a90 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 4
+ PATCHLEVEL = 14
+-SUBLEVEL = 315
++SUBLEVEL = 316
+ EXTRAVERSION =
+ NAME = Petit Gorille
+ 
+diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
+index 20a3ff41d0d5a..2498dc17c14b9 100644
+--- a/arch/m68k/kernel/signal.c
++++ b/arch/m68k/kernel/signal.c
+@@ -819,11 +819,17 @@ static inline int rt_setup_ucontext(struct ucontext 
__user *uc, struct pt_regs *
+ }
+ 
+ static inline void __user *
+-get_sigframe(struct ksignal *ksig, size_t frame_size)
++get_sigframe(struct ksignal *ksig, struct pt_regs *tregs, size_t frame_size)
+ {
+       unsigned long usp = sigsp(rdusp(), ksig);
++      unsigned long gap = 0;
+ 
+-      return (void __user *)((usp - frame_size) & -8UL);
++      if (CPU_IS_020_OR_030 && tregs->format == 0xb) {
++              /* USP is unreliable so use worst-case value */
++              gap = 256;
++      }
++
++      return (void __user *)((usp - gap - frame_size) & -8UL);
+ }
+ 
+ static int setup_frame(struct ksignal *ksig, sigset_t *set,
+@@ -841,7 +847,7 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
+               return -EFAULT;
+       }
+ 
+-      frame = get_sigframe(ksig, sizeof(*frame) + fsize);
++      frame = get_sigframe(ksig, tregs, sizeof(*frame) + fsize);
+ 
+       if (fsize)
+               err |= copy_to_user (frame + 1, regs + 1, fsize);
+@@ -912,7 +918,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t 
*set,
+               return -EFAULT;
+       }
+ 
+-      frame = get_sigframe(ksig, sizeof(*frame));
++      frame = get_sigframe(ksig, tregs, sizeof(*frame));
+ 
+       if (fsize)
+               err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
+diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
+index 77650dc808307..12b38a3bcd736 100644
+--- a/arch/parisc/kernel/process.c
++++ b/arch/parisc/kernel/process.c
+@@ -142,13 +142,18 @@ void machine_power_off(void)
+       /* It seems we have no way to power the system off via
+        * software. The user has to press the button himself. */
+ 
+-      printk(KERN_EMERG "System shut down completed.\n"
+-             "Please power this system off now.");
++      printk("Power off or press RETURN to reboot.\n");
+ 
+       /* prevent soft lockup/stalled CPU messages for endless loop. */
+       rcu_sysrq_start();
+       lockup_detector_soft_poweroff();
+-      for (;;);
++      while (1) {
++              /* reboot if user presses RETURN key */
++              if (pdc_iodc_getc() == 13) {
++                      printk("Rebooting...\n");
++                      machine_restart(NULL);
++              }
++      }
+ }
+ 
+ void (*pm_power_off)(void) = machine_power_off;
+diff --git a/arch/x86/include/asm/intel-family.h 
b/arch/x86/include/asm/intel-family.h
+index 7811d42e78ef7..436ab2c3a4371 100644
+--- a/arch/x86/include/asm/intel-family.h
++++ b/arch/x86/include/asm/intel-family.h
+@@ -73,6 +73,11 @@
+ #define       INTEL_FAM6_LAKEFIELD            0x8A
+ #define INTEL_FAM6_ALDERLAKE          0x97
+ #define INTEL_FAM6_ALDERLAKE_L                0x9A
++#define INTEL_FAM6_ALDERLAKE_N                0xBE
++
++#define INTEL_FAM6_RAPTORLAKE         0xB7
++#define INTEL_FAM6_RAPTORLAKE_P               0xBA
++#define INTEL_FAM6_RAPTORLAKE_S               0xBF
+ 
+ #define INTEL_FAM6_TIGERLAKE_L                0x8C
+ #define INTEL_FAM6_TIGERLAKE          0x8D
+diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
+index 92585a755410b..8c766aa56f0ae 100644
+--- a/arch/x86/kernel/dumpstack.c
++++ b/arch/x86/kernel/dumpstack.c
+@@ -115,7 +115,6 @@ void show_trace_log_lvl(struct task_struct *task, struct 
pt_regs *regs,
+       printk("%sCall Trace:\n", log_lvl);
+ 
+       unwind_start(&state, task, regs, stack);
+-      stack = stack ? : get_stack_pointer(task, regs);
+       regs = unwind_get_entry_regs(&state, &partial);
+ 
+       /*
+@@ -134,9 +133,13 @@ void show_trace_log_lvl(struct task_struct *task, struct 
pt_regs *regs,
+        * - hardirq stack
+        * - entry stack
+        */
+-      for ( ; stack; stack = PTR_ALIGN(stack_info.next_sp, sizeof(long))) {
++      for (stack = stack ?: get_stack_pointer(task, regs);
++           stack;
++           stack = stack_info.next_sp) {
+               const char *stack_name;
+ 
++              stack = PTR_ALIGN(stack, sizeof(long));
++
+               if (get_stack_info(stack, task, &stack_info, &visit_mask)) {
+                       /*
+                        * We weren't on a valid stack.  It's possible that
+diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
+index 8039a951db8f5..579f48ee03be2 100644
+--- a/arch/x86/mm/init.c
++++ b/arch/x86/mm/init.c
+@@ -8,6 +8,7 @@
+ #include <linux/swapops.h>
+ 
+ #include <asm/set_memory.h>
++#include <asm/cpu_device_id.h>
+ #include <asm/e820/api.h>
+ #include <asm/init.h>
+ #include <asm/page.h>
+@@ -199,6 +200,24 @@ static void __init probe_page_size_mask(void)
+       }
+ }
+ 
++#define INTEL_MATCH(_model) { .vendor  = X86_VENDOR_INTEL,    \
++                            .family  = 6,                     \
++                            .model = _model,                  \
++                          }
++/*
++ * INVLPG may not properly flush Global entries
++ * on these CPUs when PCIDs are enabled.
++ */
++static const struct x86_cpu_id invlpg_miss_ids[] = {
++      INTEL_MATCH(INTEL_FAM6_ALDERLAKE   ),
++      INTEL_MATCH(INTEL_FAM6_ALDERLAKE_L ),
++      INTEL_MATCH(INTEL_FAM6_ALDERLAKE_N ),
++      INTEL_MATCH(INTEL_FAM6_RAPTORLAKE  ),
++      INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_P),
++      INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_S),
++      {}
++};
++
+ static void setup_pcid(void)
+ {
+       if (!IS_ENABLED(CONFIG_X86_64))
+@@ -207,6 +226,12 @@ static void setup_pcid(void)
+       if (!boot_cpu_has(X86_FEATURE_PCID))
+               return;
+ 
++      if (x86_match_cpu(invlpg_miss_ids)) {
++              pr_info("Incomplete global flushes, disabling PCID");
++              setup_clear_cpu_cap(X86_FEATURE_PCID);
++              return;
++      }
++
+       if (boot_cpu_has(X86_FEATURE_PGE)) {
+               /*
+                * This can't be cr4_set_bits_and_update_boot() -- the
+diff --git a/drivers/acpi/acpica/dbnames.c b/drivers/acpi/acpica/dbnames.c
+index 8c207c7725179..658fd7cfbd6cd 100644
+--- a/drivers/acpi/acpica/dbnames.c
++++ b/drivers/acpi/acpica/dbnames.c
+@@ -600,6 +600,9 @@ acpi_status acpi_db_display_objects(char *obj_type_arg, 
char *display_count_arg)
+               object_info =
+                   ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_object_info));
+ 
++              if (!object_info)
++                      return (AE_NO_MEMORY);
++
+               /* Walk the namespace from the root */
+ 
+               (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c
+index da111a1f5bfbc..6eaf2a01034ea 100644
+--- a/drivers/acpi/acpica/dswstate.c
++++ b/drivers/acpi/acpica/dswstate.c
+@@ -610,9 +610,14 @@ acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
+       ACPI_FUNCTION_TRACE(ds_init_aml_walk);
+ 
+       walk_state->parser_state.aml =
+-          walk_state->parser_state.aml_start = aml_start;
+-      walk_state->parser_state.aml_end =
+-          walk_state->parser_state.pkg_end = aml_start + aml_length;
++          walk_state->parser_state.aml_start =
++          walk_state->parser_state.aml_end =
++          walk_state->parser_state.pkg_end = aml_start;
++      /* Avoid undefined behavior: applying zero offset to null pointer */
++      if (aml_length != 0) {
++              walk_state->parser_state.aml_end += aml_length;
++              walk_state->parser_state.pkg_end += aml_length;
++      }
+ 
+       /* The next_op of the next_walk will be the beginning of the method */
+ 
+diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
+index f8fc30be68711..1dedab328c464 100644
+--- a/drivers/acpi/ec.c
++++ b/drivers/acpi/ec.c
+@@ -1135,6 +1135,7 @@ static void acpi_ec_remove_query_handlers(struct acpi_ec 
*ec,
+ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
+ {
+       acpi_ec_remove_query_handlers(ec, false, query_bit);
++      flush_workqueue(ec_query_wq);
+ }
+ EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
+ 
+diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
+index 773560348337f..b78e4b6e2c9da 100644
+--- a/drivers/base/regmap/regcache.c
++++ b/drivers/base/regmap/regcache.c
+@@ -347,6 +347,9 @@ int regcache_sync(struct regmap *map)
+       const char *name;
+       bool bypass;
+ 
++      if (WARN_ON(map->cache_type == REGCACHE_NONE))
++              return -EINVAL;
++
+       BUG_ON(!map->cache_ops);
+ 
+       map->lock(map->lock_arg);
+@@ -416,6 +419,9 @@ int regcache_sync_region(struct regmap *map, unsigned int 
min,
+       const char *name;
+       bool bypass;
+ 
++      if (WARN_ON(map->cache_type == REGCACHE_NONE))
++              return -EINVAL;
++
+       BUG_ON(!map->cache_ops);
+ 
+       map->lock(map->lock_arg);
+diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
+index 4c9038e738886..a660adaa4920f 100644
+--- a/drivers/clk/tegra/clk-tegra20.c
++++ b/drivers/clk/tegra/clk-tegra20.c
+@@ -27,24 +27,24 @@
+ #include "clk-id.h"
+ 
+ #define OSC_CTRL 0x50
+-#define OSC_CTRL_OSC_FREQ_MASK (3<<30)
+-#define OSC_CTRL_OSC_FREQ_13MHZ (0<<30)
+-#define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30)
+-#define OSC_CTRL_OSC_FREQ_12MHZ (2<<30)
+-#define OSC_CTRL_OSC_FREQ_26MHZ (3<<30)
+-#define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
+-
+-#define OSC_CTRL_PLL_REF_DIV_MASK (3<<28)
+-#define OSC_CTRL_PLL_REF_DIV_1                (0<<28)
+-#define OSC_CTRL_PLL_REF_DIV_2                (1<<28)
+-#define OSC_CTRL_PLL_REF_DIV_4                (2<<28)
++#define OSC_CTRL_OSC_FREQ_MASK (3u<<30)
++#define OSC_CTRL_OSC_FREQ_13MHZ (0u<<30)
++#define OSC_CTRL_OSC_FREQ_19_2MHZ (1u<<30)
++#define OSC_CTRL_OSC_FREQ_12MHZ (2u<<30)
++#define OSC_CTRL_OSC_FREQ_26MHZ (3u<<30)
++#define OSC_CTRL_MASK (0x3f2u | OSC_CTRL_OSC_FREQ_MASK)
++
++#define OSC_CTRL_PLL_REF_DIV_MASK     (3u<<28)
++#define OSC_CTRL_PLL_REF_DIV_1                (0u<<28)
++#define OSC_CTRL_PLL_REF_DIV_2                (1u<<28)
++#define OSC_CTRL_PLL_REF_DIV_4                (2u<<28)
+ 
+ #define OSC_FREQ_DET 0x58
+-#define OSC_FREQ_DET_TRIG (1<<31)
++#define OSC_FREQ_DET_TRIG (1u<<31)
+ 
+ #define OSC_FREQ_DET_STATUS 0x5c
+-#define OSC_FREQ_DET_BUSY (1<<31)
+-#define OSC_FREQ_DET_CNT_MASK 0xFFFF
++#define OSC_FREQ_DET_BUSYu (1<<31)
++#define OSC_FREQ_DET_CNT_MASK 0xFFFFu
+ 
+ #define TEGRA20_CLK_PERIPH_BANKS      3
+ 
+diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
+index 352ae52be3418..76451c8bfb46b 100644
+--- a/drivers/gpu/drm/tegra/sor.c
++++ b/drivers/gpu/drm/tegra/sor.c
+@@ -709,7 +709,7 @@ static int tegra_sor_compute_config(struct tegra_sor *sor,
+                                   struct drm_dp_link *link)
+ {
+       const u64 f = 100000, link_rate = link->rate * 1000;
+-      const u64 pclk = mode->clock * 1000;
++      const u64 pclk = (u64)mode->clock * 1000;
+       u64 input, output, watermark, num;
+       struct tegra_sor_params params;
+       u32 num_syms_per_line;
+diff --git a/drivers/hid/hid-logitech-hidpp.c 
b/drivers/hid/hid-logitech-hidpp.c
+index 6ad776b4711b7..1588508b3e7b7 100644
+--- a/drivers/hid/hid-logitech-hidpp.c
++++ b/drivers/hid/hid-logitech-hidpp.c
+@@ -675,8 +675,7 @@ static int hidpp_unifying_init(struct hidpp_device *hidpp)
+       if (ret)
+               return ret;
+ 
+-      snprintf(hdev->uniq, sizeof(hdev->uniq), "%04x-%4phD",
+-               hdev->product, &serial);
++      snprintf(hdev->uniq, sizeof(hdev->uniq), "%4phD", &serial);
+       dbg_hid("HID++ Unifying: Got serial: %s\n", hdev->uniq);
+ 
+       name = hidpp_unifying_get_name(hidpp);
+@@ -777,6 +776,54 @@ static bool hidpp_is_connected(struct hidpp_device *hidpp)
+       return ret == 0;
+ }
+ 
++/* -------------------------------------------------------------------------- 
*/
++/* 0x0003: Device Information                                                 
*/
++/* -------------------------------------------------------------------------- 
*/
++
++#define HIDPP_PAGE_DEVICE_INFORMATION                 0x0003
++
++#define CMD_GET_DEVICE_INFO                           0x00
++
++static int hidpp_get_serial(struct hidpp_device *hidpp, u32 *serial)
++{
++      struct hidpp_report response;
++      u8 feature_type;
++      u8 feature_index;
++      int ret;
++
++      ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_DEVICE_INFORMATION,
++                                   &feature_index,
++                                   &feature_type);
++      if (ret)
++              return ret;
++
++      ret = hidpp_send_fap_command_sync(hidpp, feature_index,
++                                        CMD_GET_DEVICE_INFO,
++                                        NULL, 0, &response);
++      if (ret)
++              return ret;
++
++      /* See hidpp_unifying_get_serial() */
++      *serial = *((u32 *)&response.rap.params[1]);
++      return 0;
++}
++
++static int hidpp_serial_init(struct hidpp_device *hidpp)
++{
++      struct hid_device *hdev = hidpp->hid_dev;
++      u32 serial;
++      int ret;
++
++      ret = hidpp_get_serial(hidpp, &serial);
++      if (ret)
++              return ret;
++
++      snprintf(hdev->uniq, sizeof(hdev->uniq), "%4phD", &serial);
++      dbg_hid("HID++ DeviceInformation: Got serial: %s\n", hdev->uniq);
++
++      return 0;
++}
++
+ /* -------------------------------------------------------------------------- 
*/
+ /* 0x0005: GetDeviceNameType                                                  
*/
+ /* -------------------------------------------------------------------------- 
*/
+@@ -3039,6 +3086,8 @@ static int hidpp_probe(struct hid_device *hdev, const 
struct hid_device_id *id)
+ 
+       if (hidpp->quirks & HIDPP_QUIRK_UNIFYING)
+               hidpp_unifying_init(hidpp);
++      else if (hid_is_usb(hidpp->hid_dev))
++              hidpp_serial_init(hidpp);
+ 
+       connected = hidpp_is_connected(hidpp);
+       atomic_set(&hidpp->connected, connected);
+diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
+index 921d5184196d2..1b0161c2cd7a6 100644
+--- a/drivers/hid/wacom_wac.c
++++ b/drivers/hid/wacom_wac.c
+@@ -1782,18 +1782,7 @@ static void wacom_map_usage(struct input_dev *input, 
struct hid_usage *usage,
+ static void wacom_wac_battery_usage_mapping(struct hid_device *hdev,
+               struct hid_field *field, struct hid_usage *usage)
+ {
+-      struct wacom *wacom = hid_get_drvdata(hdev);
+-      struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+-      struct wacom_features *features = &wacom_wac->features;
+-      unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
+-
+-      switch (equivalent_usage) {
+-      case HID_DG_BATTERYSTRENGTH:
+-      case WACOM_HID_WD_BATTERY_LEVEL:
+-      case WACOM_HID_WD_BATTERY_CHARGING:
+-              features->quirks |= WACOM_QUIRK_BATTERY;
+-              break;
+-      }
++      return;
+ }
+ 
+ static void wacom_wac_battery_event(struct hid_device *hdev, struct hid_field 
*field,
+@@ -1814,18 +1803,21 @@ static void wacom_wac_battery_event(struct hid_device 
*hdev, struct hid_field *f
+                       wacom_wac->hid_data.bat_connected = 1;
+                       wacom_wac->hid_data.bat_status = 
WACOM_POWER_SUPPLY_STATUS_AUTO;
+               }
++              wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY;
+               break;
+       case WACOM_HID_WD_BATTERY_LEVEL:
+               value = value * 100 / (field->logical_maximum - 
field->logical_minimum);
+               wacom_wac->hid_data.battery_capacity = value;
+               wacom_wac->hid_data.bat_connected = 1;
+               wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
++              wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY;
+               break;
+       case WACOM_HID_WD_BATTERY_CHARGING:
+               wacom_wac->hid_data.bat_charging = value;
+               wacom_wac->hid_data.ps_connected = value;
+               wacom_wac->hid_data.bat_connected = 1;
+               wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
++              wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY;
+               break;
+       }
+ }
+@@ -1841,18 +1833,15 @@ static void wacom_wac_battery_report(struct hid_device 
*hdev,
+ {
+       struct wacom *wacom = hid_get_drvdata(hdev);
+       struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+-      struct wacom_features *features = &wacom_wac->features;
+ 
+-      if (features->quirks & WACOM_QUIRK_BATTERY) {
+-              int status = wacom_wac->hid_data.bat_status;
+-              int capacity = wacom_wac->hid_data.battery_capacity;
+-              bool charging = wacom_wac->hid_data.bat_charging;
+-              bool connected = wacom_wac->hid_data.bat_connected;
+-              bool powered = wacom_wac->hid_data.ps_connected;
++      int status = wacom_wac->hid_data.bat_status;
++      int capacity = wacom_wac->hid_data.battery_capacity;
++      bool charging = wacom_wac->hid_data.bat_charging;
++      bool connected = wacom_wac->hid_data.bat_connected;
++      bool powered = wacom_wac->hid_data.ps_connected;
+ 
+-              wacom_notify_battery(wacom_wac, status, capacity, charging,
+-                                   connected, powered);
+-      }
++      wacom_notify_battery(wacom_wac, status, capacity, charging,
++                           connected, powered);
+ }
+ 
+ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
+diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
+index 1a12f95227301..f1c2bc108fd76 100644
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -506,6 +506,9 @@ struct xboxone_init_packet {
+       }
+ 
+ 
++#define GIP_WIRED_INTF_DATA 0
++#define GIP_WIRED_INTF_AUDIO 1
++
+ /*
+  * This packet is required for all Xbox One pads with 2015
+  * or later firmware installed (or present from the factory).
+@@ -1830,7 +1833,7 @@ static int xpad_probe(struct usb_interface *intf, const 
struct usb_device_id *id
+       }
+ 
+       if (xpad->xtype == XTYPE_XBOXONE &&
+-          intf->cur_altsetting->desc.bInterfaceNumber != 0) {
++          intf->cur_altsetting->desc.bInterfaceNumber != GIP_WIRED_INTF_DATA) 
{
+               /*
+                * The Xbox One controller lists three interfaces all with the
+                * same interface class, subclass and protocol. Differentiate by
+diff --git a/drivers/mcb/mcb-pci.c b/drivers/mcb/mcb-pci.c
+index af4d2f26f1c62..b0ec3bbf1b76d 100644
+--- a/drivers/mcb/mcb-pci.c
++++ b/drivers/mcb/mcb-pci.c
+@@ -34,7 +34,7 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct 
pci_device_id *id)
+ {
+       struct resource *res;
+       struct priv *priv;
+-      int ret;
++      int ret, table_size;
+       unsigned long flags;
+ 
+       priv = devm_kzalloc(&pdev->dev, sizeof(struct priv), GFP_KERNEL);
+@@ -93,7 +93,30 @@ static int mcb_pci_probe(struct pci_dev *pdev, const struct 
pci_device_id *id)
+       if (ret < 0)
+               goto out_mcb_bus;
+ 
+-      dev_dbg(&pdev->dev, "Found %d cells\n", ret);
++      table_size = ret;
++
++      if (table_size < CHAM_HEADER_SIZE) {
++              /* Release the previous resources */
++              devm_iounmap(&pdev->dev, priv->base);
++              devm_release_mem_region(&pdev->dev, priv->mapbase, 
CHAM_HEADER_SIZE);
++
++              /* Then, allocate it again with the actual chameleon table size 
*/
++              res = devm_request_mem_region(&pdev->dev, priv->mapbase,
++                                              table_size,
++                                              KBUILD_MODNAME);
++              if (!res) {
++                      dev_err(&pdev->dev, "Failed to request PCI memory\n");
++                      ret = -EBUSY;
++                      goto out_mcb_bus;
++              }
++
++              priv->base = devm_ioremap(&pdev->dev, priv->mapbase, 
table_size);
++              if (!priv->base) {
++                      dev_err(&pdev->dev, "Cannot ioremap\n");
++                      ret = -ENOMEM;
++                      goto out_mcb_bus;
++              }
++      }
+ 
+       mcb_bus_add_devices(priv->bus);
+ 
+diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c 
b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
+index 03239fba87bf2..4f2ea0f035ae5 100644
+--- a/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
++++ b/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
+@@ -707,7 +707,7 @@ static void netup_unidvb_dma_fini(struct netup_unidvb_dev 
*ndev, int num)
+       netup_unidvb_dma_enable(dma, 0);
+       msleep(50);
+       cancel_work_sync(&dma->work);
+-      del_timer(&dma->timeout);
++      del_timer_sync(&dma->timeout);
+ }
+ 
+ static int netup_unidvb_dma_setup(struct netup_unidvb_dev *ndev)
+diff --git a/drivers/media/radio/radio-shark.c 
b/drivers/media/radio/radio-shark.c
+index 22f3466af2b18..5275180aed0b7 100644
+--- a/drivers/media/radio/radio-shark.c
++++ b/drivers/media/radio/radio-shark.c
+@@ -316,6 +316,16 @@ static int usb_shark_probe(struct usb_interface *intf,
+ {
+       struct shark_device *shark;
+       int retval = -ENOMEM;
++      static const u8 ep_addresses[] = {
++              SHARK_IN_EP | USB_DIR_IN,
++              SHARK_OUT_EP | USB_DIR_OUT,
++              0};
++
++      /* Are the expected endpoints present? */
++      if (!usb_check_int_endpoints(intf, ep_addresses)) {
++              dev_err(&intf->dev, "Invalid radioSHARK device\n");
++              return -EINVAL;
++      }
+ 
+       shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);
+       if (!shark)
+diff --git a/drivers/media/radio/radio-shark2.c 
b/drivers/media/radio/radio-shark2.c
+index 4d1a4b3d669cf..5356941f54aef 100644
+--- a/drivers/media/radio/radio-shark2.c
++++ b/drivers/media/radio/radio-shark2.c
+@@ -282,6 +282,16 @@ static int usb_shark_probe(struct usb_interface *intf,
+ {
+       struct shark_device *shark;
+       int retval = -ENOMEM;
++      static const u8 ep_addresses[] = {
++              SHARK_IN_EP | USB_DIR_IN,
++              SHARK_OUT_EP | USB_DIR_OUT,
++              0};
++
++      /* Are the expected endpoints present? */
++      if (!usb_check_int_endpoints(intf, ep_addresses)) {
++              dev_err(&intf->dev, "Invalid radioSHARK2 device\n");
++              return -EINVAL;
++      }
+ 
+       shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);
+       if (!shark)
+diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c
+index 256634ec58b63..d52c89b2a1d58 100644
+--- a/drivers/memstick/host/r592.c
++++ b/drivers/memstick/host/r592.c
+@@ -832,7 +832,7 @@ static void r592_remove(struct pci_dev *pdev)
+       /* Stop the processing thread.
+       That ensures that we won't take any more requests */
+       kthread_stop(dev->io_thread);
+-
++      del_timer_sync(&dev->detect_timer);
+       r592_enable_device(dev, false);
+ 
+       while (!error && dev->req) {
+diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
+index 55dd71bbdc2aa..74d0ae00b0827 100644
+--- a/drivers/message/fusion/mptlan.c
++++ b/drivers/message/fusion/mptlan.c
+@@ -1429,7 +1429,9 @@ mptlan_remove(struct pci_dev *pdev)
+ {
+       MPT_ADAPTER             *ioc = pci_get_drvdata(pdev);
+       struct net_device       *dev = ioc->netdev;
++      struct mpt_lan_priv *priv = netdev_priv(dev);
+ 
++      cancel_delayed_work_sync(&priv->post_buckets_task);
+       if(dev != NULL) {
+               unregister_netdev(dev);
+               free_netdev(dev);
+diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c
+index 97a69cd6f1278..a0ad99ca495fd 100644
+--- a/drivers/mfd/dln2.c
++++ b/drivers/mfd/dln2.c
+@@ -804,6 +804,7 @@ out_stop_rx:
+       dln2_stop_rx_urbs(dln2);
+ 
+ out_free:
++      usb_put_dev(dln2->usb_dev);
+       dln2_free(dln2);
+ 
+       return ret;
+diff --git a/drivers/net/ethernet/3com/3c589_cs.c 
b/drivers/net/ethernet/3com/3c589_cs.c
+index e28254a005997..0c0bc3c178abe 100644
+--- a/drivers/net/ethernet/3com/3c589_cs.c
++++ b/drivers/net/ethernet/3com/3c589_cs.c
+@@ -196,6 +196,7 @@ static int tc589_probe(struct pcmcia_device *link)
+ {
+       struct el3_private *lp;
+       struct net_device *dev;
++      int ret;
+ 
+       dev_dbg(&link->dev, "3c589_attach()\n");
+ 
+@@ -219,7 +220,15 @@ static int tc589_probe(struct pcmcia_device *link)
+ 
+       dev->ethtool_ops = &netdev_ethtool_ops;
+ 
+-      return tc589_config(link);
++      ret = tc589_config(link);
++      if (ret)
++              goto err_free_netdev;
++
++      return 0;
++
++err_free_netdev:
++      free_netdev(dev);
++      return ret;
+ }
+ 
+ static void tc589_detach(struct pcmcia_device *link)
+diff --git a/drivers/net/ethernet/freescale/fec_main.c 
b/drivers/net/ethernet/freescale/fec_main.c
+index c6fc77a211ea6..1085f1d721b02 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -3569,7 +3569,9 @@ fec_drv_remove(struct platform_device *pdev)
+ 
+       ret = pm_runtime_get_sync(&pdev->dev);
+       if (ret < 0)
+-              return ret;
++              dev_err(&pdev->dev,
++                      "Failed to resume device in remove callback (%pe)\n",
++                      ERR_PTR(ret));
+ 
+       cancel_work_sync(&fep->tx_timeout_work);
+       fec_ptp_stop(pdev);
+@@ -3582,8 +3584,13 @@ fec_drv_remove(struct platform_device *pdev)
+               of_phy_deregister_fixed_link(np);
+       of_node_put(fep->phy_node);
+ 
+-      clk_disable_unprepare(fep->clk_ahb);
+-      clk_disable_unprepare(fep->clk_ipg);
++      /* After pm_runtime_get_sync() failed, the clks are still off, so skip
++       * disabling them again.
++       */
++      if (ret >= 0) {
++              clk_disable_unprepare(fep->clk_ahb);
++              clk_disable_unprepare(fep->clk_ipg);
++      }
+       pm_runtime_put_noidle(&pdev->dev);
+       pm_runtime_disable(&pdev->dev);
+ 
+diff --git a/drivers/net/ethernet/intel/igb/e1000_mac.c 
b/drivers/net/ethernet/intel/igb/e1000_mac.c
+index 5eff82678f0ba..1db5d2edecbc1 100644
+--- a/drivers/net/ethernet/intel/igb/e1000_mac.c
++++ b/drivers/net/ethernet/intel/igb/e1000_mac.c
+@@ -445,7 +445,7 @@ void igb_mta_set(struct e1000_hw *hw, u32 hash_value)
+ static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
+ {
+       u32 hash_value, hash_mask;
+-      u8 bit_shift = 0;
++      u8 bit_shift = 1;
+ 
+       /* Register count multiplied by bits per register */
+       hash_mask = (hw->mac.mta_reg_count * 32) - 1;
+@@ -453,7 +453,7 @@ static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 
*mc_addr)
+       /* For a mc_filter_type of 0, bit_shift is the number of left-shifts
+        * where 0xFF would still fall within the hash mask.
+        */
+-      while (hash_mask >> bit_shift != 0xFF)
++      while (hash_mask >> bit_shift != 0xFF && bit_shift < 4)
+               bit_shift++;
+ 
+       /* The portion of the address that is used for the hash table
+diff --git a/drivers/net/ethernet/nvidia/forcedeth.c 
b/drivers/net/ethernet/nvidia/forcedeth.c
+index 994a83a1f0a5c..3e8477e697c52 100644
+--- a/drivers/net/ethernet/nvidia/forcedeth.c
++++ b/drivers/net/ethernet/nvidia/forcedeth.c
+@@ -6020,6 +6020,7 @@ static int nv_probe(struct pci_dev *pci_dev, const 
struct pci_device_id *id)
+       return 0;
+ 
+ out_error:
++      nv_mgmt_release_sema(dev);
+       if (phystate_orig)
+               writel(phystate|NVREG_ADAPTCTL_RUNNING, base + 
NvRegAdapterControl);
+ out_freering:
+diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c 
b/drivers/net/ethernet/pasemi/pasemi_mac.c
+index 6ccdce21ca9b5..c891ee70099a7 100644
+--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
++++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
+@@ -1436,7 +1436,7 @@ static void pasemi_mac_queue_csdesc(const struct sk_buff 
*skb,
+       write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), 2);
+ }
+ 
+-static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
++static netdev_tx_t pasemi_mac_start_tx(struct sk_buff *skb, struct net_device 
*dev)
+ {
+       struct pasemi_mac * const mac = netdev_priv(dev);
+       struct pasemi_mac_txring * const txring = tx_ring(mac);
+diff --git a/drivers/net/ethernet/sun/cassini.c 
b/drivers/net/ethernet/sun/cassini.c
+index 7e5c0f182770d..ba546f993fb53 100644
+--- a/drivers/net/ethernet/sun/cassini.c
++++ b/drivers/net/ethernet/sun/cassini.c
+@@ -5152,6 +5152,8 @@ err_out_iounmap:
+               cas_shutdown(cp);
+       mutex_unlock(&cp->pm_mutex);
+ 
++      vfree(cp->fw_data);
++
+       pci_iounmap(pdev, cp->regs);
+ 
+ 
+diff --git a/drivers/net/ipvlan/ipvlan_core.c 
b/drivers/net/ipvlan/ipvlan_core.c
+index 71fd45137ee44..6283cbc9f6ed1 100644
+--- a/drivers/net/ipvlan/ipvlan_core.c
++++ b/drivers/net/ipvlan/ipvlan_core.c
+@@ -394,6 +394,9 @@ static int ipvlan_process_v4_outbound(struct sk_buff *skb)
+               goto err;
+       }
+       skb_dst_set(skb, &rt->dst);
++
++      memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
++
+       err = ip_local_out(net, skb->sk, skb);
+       if (unlikely(net_xmit_eval(err)))
+               dev->stats.tx_errors++;
+@@ -431,6 +434,9 @@ static int ipvlan_process_v6_outbound(struct sk_buff *skb)
+               goto err;
+       }
+       skb_dst_set(skb, dst);
++
++      memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
++
+       err = ip6_local_out(net, skb->sk, skb);
+       if (unlikely(net_xmit_eval(err)))
+               dev->stats.tx_errors++;
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c 
b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+index df0e48e4cf5b3..4abb948f607fa 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -1349,13 +1349,14 @@ static u16 brcmf_map_fw_linkdown_reason(const struct 
brcmf_event_msg *e)
+ static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 
pmk_len)
+ {
+       struct brcmf_wsec_pmk_le pmk;
+-      int i, err;
++      int err;
++
++      memset(&pmk, 0, sizeof(pmk));
+ 
+-      /* convert to firmware key format */
+-      pmk.key_len = cpu_to_le16(pmk_len << 1);
+-      pmk.flags = cpu_to_le16(BRCMF_WSEC_PASSPHRASE);
+-      for (i = 0; i < pmk_len; i++)
+-              snprintf(&pmk.key[2 * i], 3, "%02x", pmk_data[i]);
++      /* pass pmk directly */
++      pmk.key_len = cpu_to_le16(pmk_len);
++      pmk.flags = cpu_to_le16(0);
++      memcpy(pmk.key, pmk_data, pmk_len);
+ 
+       /* store psk in firmware */
+       err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_WSEC_PMK,
+diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/sta.c 
b/drivers/net/wireless/intel/iwlwifi/dvm/sta.c
+index de6ec9b7ace45..f30bac02d32ce 100644
+--- a/drivers/net/wireless/intel/iwlwifi/dvm/sta.c
++++ b/drivers/net/wireless/intel/iwlwifi/dvm/sta.c
+@@ -1101,6 +1101,7 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv,
+ {
+       __le16 key_flags;
+       struct iwl_addsta_cmd sta_cmd;
++      size_t to_copy;
+       int i;
+ 
+       spin_lock_bh(&priv->sta_lock);
+@@ -1120,7 +1121,9 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv,
+               sta_cmd.key.tkip_rx_tsc_byte2 = tkip_iv32;
+               for (i = 0; i < 5; i++)
+                       sta_cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
+-              memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen);
++              /* keyconf may contain MIC rx/tx keys which iwl does not use */
++              to_copy = min_t(size_t, sizeof(sta_cmd.key.key), 
keyconf->keylen);
++              memcpy(sta_cmd.key.key, keyconf->key, to_copy);
+               break;
+       case WLAN_CIPHER_SUITE_WEP104:
+               key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
+diff --git a/drivers/phy/st/phy-miphy28lp.c b/drivers/phy/st/phy-miphy28lp.c
+index 213e2e15339c4..fe23432e5b1a6 100644
+--- a/drivers/phy/st/phy-miphy28lp.c
++++ b/drivers/phy/st/phy-miphy28lp.c
+@@ -13,6 +13,7 @@
+ 
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
++#include <linux/iopoll.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
+@@ -488,19 +489,11 @@ static inline void miphy28lp_pcie_config_gen(struct 
miphy28lp_phy *miphy_phy)
+ 
+ static inline int miphy28lp_wait_compensation(struct miphy28lp_phy *miphy_phy)
+ {
+-      unsigned long finish = jiffies + 5 * HZ;
+       u8 val;
+ 
+       /* Waiting for Compensation to complete */
+-      do {
+-              val = readb_relaxed(miphy_phy->base + MIPHY_COMP_FSM_6);
+-
+-              if (time_after_eq(jiffies, finish))
+-                      return -EBUSY;
+-              cpu_relax();
+-      } while (!(val & COMP_DONE));
+-
+-      return 0;
++      return readb_relaxed_poll_timeout(miphy_phy->base + MIPHY_COMP_FSM_6,
++                                        val, val & COMP_DONE, 1, 5 * 
USEC_PER_SEC);
+ }
+ 
+ 
+@@ -809,7 +802,6 @@ static inline void miphy28lp_configure_usb3(struct 
miphy28lp_phy *miphy_phy)
+ 
+ static inline int miphy_is_ready(struct miphy28lp_phy *miphy_phy)
+ {
+-      unsigned long finish = jiffies + 5 * HZ;
+       u8 mask = HFC_PLL | HFC_RDY;
+       u8 val;
+ 
+@@ -820,21 +812,14 @@ static inline int miphy_is_ready(struct miphy28lp_phy 
*miphy_phy)
+       if (miphy_phy->type == PHY_TYPE_SATA)
+               mask |= PHY_RDY;
+ 
+-      do {
+-              val = readb_relaxed(miphy_phy->base + MIPHY_STATUS_1);
+-              if ((val & mask) != mask)
+-                      cpu_relax();
+-              else
+-                      return 0;
+-      } while (!time_after_eq(jiffies, finish));
+-
+-      return -EBUSY;
++      return readb_relaxed_poll_timeout(miphy_phy->base + MIPHY_STATUS_1,
++                                        val, (val & mask) == mask, 1,
++                                        5 * USEC_PER_SEC);
+ }
+ 
+ static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy)
+ {
+       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+-      unsigned long finish = jiffies + 5 * HZ;
+       u32 val;
+ 
+       if (!miphy_phy->osc_rdy)
+@@ -843,17 +828,10 @@ static int miphy_osc_is_ready(struct miphy28lp_phy 
*miphy_phy)
+       if (!miphy_phy->syscfg_reg[SYSCFG_STATUS])
+               return -EINVAL;
+ 
+-      do {
+-              regmap_read(miphy_dev->regmap,
+-                              miphy_phy->syscfg_reg[SYSCFG_STATUS], &val);
+-
+-              if ((val & MIPHY_OSC_RDY) != MIPHY_OSC_RDY)
+-                      cpu_relax();
+-              else
+-                      return 0;
+-      } while (!time_after_eq(jiffies, finish));
+-
+-      return -EBUSY;
++      return regmap_read_poll_timeout(miphy_dev->regmap,
++                                      miphy_phy->syscfg_reg[SYSCFG_STATUS],
++                                      val, val & MIPHY_OSC_RDY, 1,
++                                      5 * USEC_PER_SEC);
+ }
+ 
+ static int miphy28lp_get_resource_byname(struct device_node *child,
+diff --git a/drivers/power/supply/bq27xxx_battery.c 
b/drivers/power/supply/bq27xxx_battery.c
+index 3e8466064bb2c..37b5743ce35e4 100644
+--- a/drivers/power/supply/bq27xxx_battery.c
++++ b/drivers/power/supply/bq27xxx_battery.c
+@@ -1506,7 +1506,7 @@ static int bq27xxx_battery_read_health(struct 
bq27xxx_device_info *di)
+       return POWER_SUPPLY_HEALTH_GOOD;
+ }
+ 
+-void bq27xxx_battery_update(struct bq27xxx_device_info *di)
++static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
+ {
+       struct bq27xxx_reg_cache cache = {0, };
+       bool has_ci_flag = di->opts & BQ27XXX_O_ZERO;
+@@ -1554,6 +1554,16 @@ void bq27xxx_battery_update(struct bq27xxx_device_info 
*di)
+               di->cache = cache;
+ 
+       di->last_update = jiffies;
++
++      if (!di->removed && poll_interval > 0)
++              mod_delayed_work(system_wq, &di->work, poll_interval * HZ);
++}
++
++void bq27xxx_battery_update(struct bq27xxx_device_info *di)
++{
++      mutex_lock(&di->lock);
++      bq27xxx_battery_update_unlocked(di);
++      mutex_unlock(&di->lock);
+ }
+ EXPORT_SYMBOL_GPL(bq27xxx_battery_update);
+ 
+@@ -1564,9 +1574,6 @@ static void bq27xxx_battery_poll(struct work_struct 
*work)
+                                    work.work);
+ 
+       bq27xxx_battery_update(di);
+-
+-      if (poll_interval > 0)
+-              schedule_delayed_work(&di->work, poll_interval * HZ);
+ }
+ 
+ /*
+@@ -1725,10 +1732,8 @@ static int bq27xxx_battery_get_property(struct 
power_supply *psy,
+       struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
+ 
+       mutex_lock(&di->lock);
+-      if (time_is_before_jiffies(di->last_update + 5 * HZ)) {
+-              cancel_delayed_work_sync(&di->work);
+-              bq27xxx_battery_poll(&di->work.work);
+-      }
++      if (time_is_before_jiffies(di->last_update + 5 * HZ))
++              bq27xxx_battery_update_unlocked(di);
+       mutex_unlock(&di->lock);
+ 
+       if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
+@@ -1865,22 +1870,18 @@ EXPORT_SYMBOL_GPL(bq27xxx_battery_setup);
+ 
+ void bq27xxx_battery_teardown(struct bq27xxx_device_info *di)
+ {
+-      /*
+-       * power_supply_unregister call bq27xxx_battery_get_property which
+-       * call bq27xxx_battery_poll.
+-       * Make sure that bq27xxx_battery_poll will not call
+-       * schedule_delayed_work again after unregister (which cause OOPS).
+-       */
+-      poll_interval = 0;
+-
+-      cancel_delayed_work_sync(&di->work);
+-
+-      power_supply_unregister(di->bat);
+-
+       mutex_lock(&bq27xxx_list_lock);
+       list_del(&di->list);
+       mutex_unlock(&bq27xxx_list_lock);
+ 
++      /* Set removed to avoid bq27xxx_battery_update() re-queuing the work */
++      mutex_lock(&di->lock);
++      di->removed = true;
++      mutex_unlock(&di->lock);
++
++      cancel_delayed_work_sync(&di->work);
++
++      power_supply_unregister(di->bat);
+       mutex_destroy(&di->lock);
+ }
+ EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown);
+diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c 
b/drivers/power/supply/bq27xxx_battery_i2c.c
+index 12ffe62caa17b..426ce81333a54 100644
+--- a/drivers/power/supply/bq27xxx_battery_i2c.c
++++ b/drivers/power/supply/bq27xxx_battery_i2c.c
+@@ -187,7 +187,7 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client 
*client,
+       i2c_set_clientdata(client, di);
+ 
+       if (client->irq) {
+-              ret = devm_request_threaded_irq(&client->dev, client->irq,
++              ret = request_threaded_irq(client->irq,
+                               NULL, bq27xxx_battery_irq_handler_thread,
+                               IRQF_ONESHOT,
+                               di->name, di);
+@@ -217,6 +217,7 @@ static int bq27xxx_battery_i2c_remove(struct i2c_client 
*client)
+ {
+       struct bq27xxx_device_info *di = i2c_get_clientdata(client);
+ 
++      free_irq(client->irq, di);
+       bq27xxx_battery_teardown(di);
+ 
+       mutex_lock(&battery_mutex);
+diff --git a/drivers/power/supply/power_supply_leds.c 
b/drivers/power/supply/power_supply_leds.c
+index 2277ad9c2f682..9188b7ccdd4c7 100644
+--- a/drivers/power/supply/power_supply_leds.c
++++ b/drivers/power/supply/power_supply_leds.c
+@@ -35,8 +35,9 @@ static void power_supply_update_bat_leds(struct power_supply 
*psy)
+               led_trigger_event(psy->charging_full_trig, LED_FULL);
+               led_trigger_event(psy->charging_trig, LED_OFF);
+               led_trigger_event(psy->full_trig, LED_FULL);
+-              led_trigger_event(psy->charging_blink_full_solid_trig,
+-                      LED_FULL);
++              /* Going from blink to LED on requires a LED_OFF event to stop 
blink */
++              led_trigger_event(psy->charging_blink_full_solid_trig, LED_OFF);
++              led_trigger_event(psy->charging_blink_full_solid_trig, 
LED_FULL);
+               break;
+       case POWER_SUPPLY_STATUS_CHARGING:
+               led_trigger_event(psy->charging_full_trig, LED_FULL);
+diff --git a/drivers/power/supply/sbs-charger.c 
b/drivers/power/supply/sbs-charger.c
+index 15947dbb511e3..0f9cc82d81618 100644
+--- a/drivers/power/supply/sbs-charger.c
++++ b/drivers/power/supply/sbs-charger.c
+@@ -29,7 +29,7 @@
+ #define SBS_CHARGER_REG_STATUS                        0x13
+ #define SBS_CHARGER_REG_ALARM_WARNING         0x16
+ 
+-#define SBS_CHARGER_STATUS_CHARGE_INHIBITED   BIT(1)
++#define SBS_CHARGER_STATUS_CHARGE_INHIBITED   BIT(0)
+ #define SBS_CHARGER_STATUS_RES_COLD           BIT(9)
+ #define SBS_CHARGER_STATUS_RES_HOT            BIT(10)
+ #define SBS_CHARGER_STATUS_BATTERY_PRESENT    BIT(14)
+diff --git a/drivers/spi/spi-fsl-cpm.c b/drivers/spi/spi-fsl-cpm.c
+index 8f7b26ec181e2..0485593dc2f5b 100644
+--- a/drivers/spi/spi-fsl-cpm.c
++++ b/drivers/spi/spi-fsl-cpm.c
+@@ -25,6 +25,7 @@
+ #include <linux/spi/spi.h>
+ #include <linux/types.h>
+ #include <linux/platform_device.h>
++#include <linux/byteorder/generic.h>
+ 
+ #include "spi-fsl-cpm.h"
+ #include "spi-fsl-lib.h"
+@@ -124,6 +125,21 @@ int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
+               mspi->rx_dma = mspi->dma_dummy_rx;
+               mspi->map_rx_dma = 0;
+       }
++      if (t->bits_per_word == 16 && t->tx_buf) {
++              const u16 *src = t->tx_buf;
++              u16 *dst;
++              int i;
++
++              dst = kmalloc(t->len, GFP_KERNEL);
++              if (!dst)
++                      return -ENOMEM;
++
++              for (i = 0; i < t->len >> 1; i++)
++                      dst[i] = cpu_to_le16p(src + i);
++
++              mspi->tx = dst;
++              mspi->map_tx_dma = 1;
++      }
+ 
+       if (mspi->map_tx_dma) {
+               void *nonconst_tx = (void *)mspi->tx; /* shut up gcc */
+@@ -177,6 +193,13 @@ void fsl_spi_cpm_bufs_complete(struct mpc8xxx_spi *mspi)
+       if (mspi->map_rx_dma)
+               dma_unmap_single(dev, mspi->rx_dma, t->len, DMA_FROM_DEVICE);
+       mspi->xfer_in_progress = NULL;
++
++      if (t->bits_per_word == 16 && t->rx_buf) {
++              int i;
++
++              for (i = 0; i < t->len; i += 2)
++                      le16_to_cpus(t->rx_buf + i);
++      }
+ }
+ EXPORT_SYMBOL_GPL(fsl_spi_cpm_bufs_complete);
+ 
+diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
+index 479d10dc6cb84..5e49fed487f8a 100644
+--- a/drivers/spi/spi-fsl-spi.c
++++ b/drivers/spi/spi-fsl-spi.c
+@@ -201,26 +201,6 @@ static int mspi_apply_cpu_mode_quirks(struct 
spi_mpc8xxx_cs *cs,
+       return bits_per_word;
+ }
+ 
+-static int mspi_apply_qe_mode_quirks(struct spi_mpc8xxx_cs *cs,
+-                              struct spi_device *spi,
+-                              int bits_per_word)
+-{
+-      /* CPM/QE uses Little Endian for words > 8
+-       * so transform 16 and 32 bits words into 8 bits
+-       * Unfortnatly that doesn't work for LSB so
+-       * reject these for now */
+-      /* Note: 32 bits word, LSB works iff
+-       * tfcr/rfcr is set to CPMFCR_GBL */
+-      if (spi->mode & SPI_LSB_FIRST &&
+-          bits_per_word > 8)
+-              return -EINVAL;
+-      if (bits_per_word <= 8)
+-              return bits_per_word;
+-      if (bits_per_word == 16 || bits_per_word == 32)
+-              return 8; /* pretend its 8 bits */
+-      return -EINVAL;
+-}
+-
+ static int fsl_spi_setup_transfer(struct spi_device *spi,
+                                       struct spi_transfer *t)
+ {
+@@ -248,9 +228,6 @@ static int fsl_spi_setup_transfer(struct spi_device *spi,
+               bits_per_word = mspi_apply_cpu_mode_quirks(cs, spi,
+                                                          mpc8xxx_spi,
+                                                          bits_per_word);
+-      else
+-              bits_per_word = mspi_apply_qe_mode_quirks(cs, spi,
+-                                                        bits_per_word);
+ 
+       if (bits_per_word < 0)
+               return bits_per_word;
+@@ -357,12 +334,44 @@ static int fsl_spi_bufs(struct spi_device *spi, struct 
spi_transfer *t,
+ static int fsl_spi_do_one_msg(struct spi_master *master,
+                             struct spi_message *m)
+ {
++      struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
+       struct spi_device *spi = m->spi;
+       struct spi_transfer *t, *first;
+       unsigned int cs_change;
+       const int nsecs = 50;
+       int status;
+ 
++      /*
++       * In CPU mode, optimize large byte transfers to use larger
++       * bits_per_word values to reduce number of interrupts taken.
++       */
++      list_for_each_entry(t, &m->transfers, transfer_list) {
++              if (!(mpc8xxx_spi->flags & SPI_CPM_MODE)) {
++                      if (t->len < 256 || t->bits_per_word != 8)
++                              continue;
++                      if ((t->len & 3) == 0)
++                              t->bits_per_word = 32;
++                      else if ((t->len & 1) == 0)
++                              t->bits_per_word = 16;
++              } else {
++                      /*
++                       * CPM/QE uses Little Endian for words > 8
++                       * so transform 16 and 32 bits words into 8 bits
++                       * Unfortnatly that doesn't work for LSB so
++                       * reject these for now
++                       * Note: 32 bits word, LSB works iff
++                       * tfcr/rfcr is set to CPMFCR_GBL
++                       */
++                      if (m->spi->mode & SPI_LSB_FIRST && t->bits_per_word > 
8)
++                              return -EINVAL;
++                      if (t->bits_per_word == 16 || t->bits_per_word == 32)
++                              t->bits_per_word = 8; /* pretend its 8 bits */
++                      if (t->bits_per_word == 8 && t->len >= 256 &&
++                          (mpc8xxx_spi->flags & SPI_CPM1))
++                              t->bits_per_word = 16;
++              }
++      }
++
+       /* Don't allow changes if CS is active */
+       first = list_first_entry(&m->transfers, struct spi_transfer,
+                       transfer_list);
+@@ -642,8 +651,14 @@ static struct spi_master * fsl_spi_probe(struct device 
*dev,
+       if (mpc8xxx_spi->type == TYPE_GRLIB)
+               fsl_spi_grlib_probe(dev);
+ 
+-      master->bits_per_word_mask =
+-              (SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32)) &
++      if (mpc8xxx_spi->flags & SPI_CPM_MODE)
++              master->bits_per_word_mask =
++                      (SPI_BPW_RANGE_MASK(4, 8) | SPI_BPW_MASK(16) | 
SPI_BPW_MASK(32));
++      else
++              master->bits_per_word_mask =
++                      (SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32));
++
++      master->bits_per_word_mask &=
+               SPI_BPW_RANGE_MASK(1, mpc8xxx_spi->max_bits_per_word);
+ 
+       if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE)
+diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
+index df18d07d544d5..e306de7009295 100644
+--- a/drivers/spi/spi-imx.c
++++ b/drivers/spi/spi-imx.c
+@@ -241,6 +241,18 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
+       return true;
+ }
+ 
++/*
++ * Note the number of natively supported chip selects for MX51 is 4. Some
++ * devices may have less actual SS pins but the register map supports 4. When
++ * using gpio chip selects the cs values passed into the macros below can go
++ * outside the range 0 - 3. We therefore need to limit the cs value to avoid
++ * corrupting bits outside the allocated locations.
++ *
++ * The simplest way to do this is to just mask the cs bits to 2 bits. This
++ * still allows all 4 native chip selects to work as well as gpio chip selects
++ * (which can use any of the 4 chip select configurations).
++ */
++
+ #define MX51_ECSPI_CTRL               0x08
+ #define MX51_ECSPI_CTRL_ENABLE                (1 <<  0)
+ #define MX51_ECSPI_CTRL_XCH           (1 <<  2)
+@@ -249,16 +261,16 @@ static bool spi_imx_can_dma(struct spi_master *master, 
struct spi_device *spi,
+ #define MX51_ECSPI_CTRL_DRCTL(drctl)  ((drctl) << 16)
+ #define MX51_ECSPI_CTRL_POSTDIV_OFFSET        8
+ #define MX51_ECSPI_CTRL_PREDIV_OFFSET 12
+-#define MX51_ECSPI_CTRL_CS(cs)                ((cs) << 18)
++#define MX51_ECSPI_CTRL_CS(cs)                ((cs & 3) << 18)
+ #define MX51_ECSPI_CTRL_BL_OFFSET     20
+ #define MX51_ECSPI_CTRL_BL_MASK               (0xfff << 20)
+ 
+ #define MX51_ECSPI_CONFIG     0x0c
+-#define MX51_ECSPI_CONFIG_SCLKPHA(cs) (1 << ((cs) +  0))
+-#define MX51_ECSPI_CONFIG_SCLKPOL(cs) (1 << ((cs) +  4))
+-#define MX51_ECSPI_CONFIG_SBBCTRL(cs) (1 << ((cs) +  8))
+-#define MX51_ECSPI_CONFIG_SSBPOL(cs)  (1 << ((cs) + 12))
+-#define MX51_ECSPI_CONFIG_SCLKCTL(cs) (1 << ((cs) + 20))
++#define MX51_ECSPI_CONFIG_SCLKPHA(cs) (1 << ((cs & 3) +  0))
++#define MX51_ECSPI_CONFIG_SCLKPOL(cs) (1 << ((cs & 3) +  4))
++#define MX51_ECSPI_CONFIG_SBBCTRL(cs) (1 << ((cs & 3) +  8))
++#define MX51_ECSPI_CONFIG_SSBPOL(cs)  (1 << ((cs & 3) + 12))
++#define MX51_ECSPI_CONFIG_SCLKCTL(cs) (1 << ((cs & 3) + 20))
+ 
+ #define MX51_ECSPI_INT                0x10
+ #define MX51_ECSPI_INT_TEEN           (1 <<  0)
+diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c 
b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+index 8420bdae1a5cc..8bccaf9ea7009 100644
+--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
++++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+@@ -61,9 +61,9 @@ static const struct rtl819x_ops rtl819xp_ops = {
+ };
+ 
+ static struct pci_device_id rtl8192_pci_id_tbl[] = {
+-      {RTL_PCI_DEVICE(0x10ec, 0x8192, rtl819xp_ops)},
+-      {RTL_PCI_DEVICE(0x07aa, 0x0044, rtl819xp_ops)},
+-      {RTL_PCI_DEVICE(0x07aa, 0x0047, rtl819xp_ops)},
++      {PCI_DEVICE(0x10ec, 0x8192)},
++      {PCI_DEVICE(0x07aa, 0x0044)},
++      {PCI_DEVICE(0x07aa, 0x0047)},
+       {}
+ };
+ 
+diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h 
b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
+index 9d3089cb6a5af..ff9b544edf875 100644
+--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
++++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
+@@ -67,11 +67,6 @@
+ #define IS_HARDWARE_TYPE_8192SE(_priv)                \
+       (((struct r8192_priv *)rtllib_priv(dev))->card_8192 == NIC_8192SE)
+ 
+-#define RTL_PCI_DEVICE(vend, dev, cfg) \
+-      .vendor = (vend), .device = (dev), \
+-      .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, \
+-      .driver_data = (kernel_ulong_t)&(cfg)
+-
+ #define TOTAL_CAM_ENTRY               32
+ #define CAM_CONTENT_COUNT     8
+ 
+diff --git a/drivers/tty/serial/8250/8250_core.c 
b/drivers/tty/serial/8250/8250_core.c
+index 8d46bd612888f..3cc3fab510912 100644
+--- a/drivers/tty/serial/8250/8250_core.c
++++ b/drivers/tty/serial/8250/8250_core.c
+@@ -1128,6 +1128,7 @@ void serial8250_unregister_port(int line)
+               uart->port.type = PORT_UNKNOWN;
+               uart->port.dev = &serial8250_isa_devs->dev;
+               uart->capabilities = 0;
++              serial8250_init_port(uart);
+               serial8250_apply_quirks(uart);
+               uart_add_one_port(&serial8250_reg, &uart->port);
+       } else {
+diff --git a/drivers/tty/serial/8250/8250_pci.c 
b/drivers/tty/serial/8250/8250_pci.c
+index a22a0ed905d74..e80d742932447 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -1651,6 +1651,8 @@ pci_wch_ch38x_setup(struct serial_private *priv,
+ #define PCI_SUBDEVICE_ID_SIIG_DUAL_30 0x2530
+ #define PCI_VENDOR_ID_ADVANTECH               0x13fe
+ #define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66
++#define PCI_DEVICE_ID_ADVANTECH_PCI1600       0x1600
++#define PCI_DEVICE_ID_ADVANTECH_PCI1600_1611  0x1611
+ #define PCI_DEVICE_ID_ADVANTECH_PCI3620       0x3620
+ #define PCI_DEVICE_ID_ADVANTECH_PCI3618       0x3618
+ #define PCI_DEVICE_ID_ADVANTECH_PCIf618       0xf618
+@@ -3851,6 +3853,9 @@ static SIMPLE_DEV_PM_OPS(pciserial_pm_ops, 
pciserial_suspend_one,
+                        pciserial_resume_one);
+ 
+ static const struct pci_device_id serial_pci_tbl[] = {
++      {       PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI1600,
++              PCI_DEVICE_ID_ADVANTECH_PCI1600_1611, PCI_ANY_ID, 0, 0,
++              pbn_b0_4_921600 },
+       /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 
'PCI_SUBVENDOR_ID' */
+       {       PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620,
+               PCI_DEVICE_ID_ADVANTECH_PCI3620, 0x0001, 0, 0,
+diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
+index 7a4e3da549fef..90c89411ea751 100644
+--- a/drivers/usb/core/usb.c
++++ b/drivers/usb/core/usb.c
+@@ -209,6 +209,82 @@ int usb_find_common_endpoints_reverse(struct 
usb_host_interface *alt,
+ }
+ EXPORT_SYMBOL_GPL(usb_find_common_endpoints_reverse);
+ 
++/**
++ * usb_find_endpoint() - Given an endpoint address, search for the endpoint's
++ * usb_host_endpoint structure in an interface's current altsetting.
++ * @intf: the interface whose current altsetting should be searched
++ * @ep_addr: the endpoint address (number and direction) to find
++ *
++ * Search the altsetting's list of endpoints for one with the specified 
address.
++ *
++ * Return: Pointer to the usb_host_endpoint if found, %NULL otherwise.
++ */
++static const struct usb_host_endpoint *usb_find_endpoint(
++              const struct usb_interface *intf, unsigned int ep_addr)
++{
++      int n;
++      const struct usb_host_endpoint *ep;
++
++      n = intf->cur_altsetting->desc.bNumEndpoints;
++      ep = intf->cur_altsetting->endpoint;
++      for (; n > 0; (--n, ++ep)) {
++              if (ep->desc.bEndpointAddress == ep_addr)
++                      return ep;
++      }
++      return NULL;
++}
++
++/**
++ * usb_check_bulk_endpoints - Check whether an interface's current altsetting
++ * contains a set of bulk endpoints with the given addresses.
++ * @intf: the interface whose current altsetting should be searched
++ * @ep_addrs: 0-terminated array of the endpoint addresses (number and
++ * direction) to look for
++ *
++ * Search for endpoints with the specified addresses and check their types.
++ *
++ * Return: %true if all the endpoints are found and are bulk, %false 
otherwise.
++ */
++bool usb_check_bulk_endpoints(
++              const struct usb_interface *intf, const u8 *ep_addrs)
++{
++      const struct usb_host_endpoint *ep;
++
++      for (; *ep_addrs; ++ep_addrs) {
++              ep = usb_find_endpoint(intf, *ep_addrs);
++              if (!ep || !usb_endpoint_xfer_bulk(&ep->desc))
++                      return false;
++      }
++      return true;
++}
++EXPORT_SYMBOL_GPL(usb_check_bulk_endpoints);
++
++/**
++ * usb_check_int_endpoints - Check whether an interface's current altsetting
++ * contains a set of interrupt endpoints with the given addresses.
++ * @intf: the interface whose current altsetting should be searched
++ * @ep_addrs: 0-terminated array of the endpoint addresses (number and
++ * direction) to look for
++ *
++ * Search for endpoints with the specified addresses and check their types.
++ *
++ * Return: %true if all the endpoints are found and are interrupt,
++ * %false otherwise.
++ */
++bool usb_check_int_endpoints(
++              const struct usb_interface *intf, const u8 *ep_addrs)
++{
++      const struct usb_host_endpoint *ep;
++
++      for (; *ep_addrs; ++ep_addrs) {
++              ep = usb_find_endpoint(intf, *ep_addrs);
++              if (!ep || !usb_endpoint_xfer_int(&ep->desc))
++                      return false;
++      }
++      return true;
++}
++EXPORT_SYMBOL_GPL(usb_check_int_endpoints);
++
+ /**
+  * usb_find_alt_setting() - Given a configuration, find the alternate setting
+  * for the given interface.
+diff --git a/drivers/usb/misc/sisusbvga/sisusb.c 
b/drivers/usb/misc/sisusbvga/sisusb.c
+index a020d5eafb4a5..ef10a9066267c 100644
+--- a/drivers/usb/misc/sisusbvga/sisusb.c
++++ b/drivers/usb/misc/sisusbvga/sisusb.c
+@@ -3015,6 +3015,20 @@ static int sisusb_probe(struct usb_interface *intf,
+       struct usb_device *dev = interface_to_usbdev(intf);
+       struct sisusb_usb_data *sisusb;
+       int retval = 0, i;
++      static const u8 ep_addresses[] = {
++              SISUSB_EP_GFX_IN | USB_DIR_IN,
++              SISUSB_EP_GFX_OUT | USB_DIR_OUT,
++              SISUSB_EP_GFX_BULK_OUT | USB_DIR_OUT,
++              SISUSB_EP_GFX_LBULK_OUT | USB_DIR_OUT,
++              SISUSB_EP_BRIDGE_IN | USB_DIR_IN,
++              SISUSB_EP_BRIDGE_OUT | USB_DIR_OUT,
++              0};
++
++      /* Are the expected endpoints present? */
++      if (!usb_check_bulk_endpoints(intf, ep_addresses)) {
++              dev_err(&intf->dev, "Invalid USB2VGA device\n");
++              return -EINVAL;
++      }
+ 
+       dev_info(&dev->dev, "USB2VGA dongle found at address %d\n",
+                       dev->devnum);
+diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
+index fd5398efce412..028523621f5c5 100644
+--- a/drivers/usb/storage/scsiglue.c
++++ b/drivers/usb/storage/scsiglue.c
+@@ -408,22 +408,25 @@ static DEF_SCSI_QCMD(queuecommand)
+  ***********************************************************************/
+ 
+ /* Command timeout and abort */
+-static int command_abort(struct scsi_cmnd *srb)
++static int command_abort_matching(struct us_data *us, struct scsi_cmnd 
*srb_match)
+ {
+-      struct us_data *us = host_to_us(srb->device->host);
+-
+-      usb_stor_dbg(us, "%s called\n", __func__);
+-
+       /*
+        * us->srb together with the TIMED_OUT, RESETTING, and ABORTING
+        * bits are protected by the host lock.
+        */
+       scsi_lock(us_to_host(us));
+ 
+-      /* Is this command still active? */
+-      if (us->srb != srb) {
++      /* is there any active pending command to abort ? */
++      if (!us->srb) {
+               scsi_unlock(us_to_host(us));
+               usb_stor_dbg(us, "-- nothing to abort\n");
++              return SUCCESS;
++      }
++
++      /* Does the command match the passed srb if any ? */
++      if (srb_match && us->srb != srb_match) {
++              scsi_unlock(us_to_host(us));
++              usb_stor_dbg(us, "-- pending command mismatch\n");
+               return FAILED;
+       }
+ 
+@@ -446,6 +449,14 @@ static int command_abort(struct scsi_cmnd *srb)
+       return SUCCESS;
+ }
+ 
++static int command_abort(struct scsi_cmnd *srb)
++{
++      struct us_data *us = host_to_us(srb->device->host);
++
++      usb_stor_dbg(us, "%s called\n", __func__);
++      return command_abort_matching(us, srb);
++}
++
+ /*
+  * This invokes the transport reset mechanism to reset the state of the
+  * device
+@@ -457,6 +468,9 @@ static int device_reset(struct scsi_cmnd *srb)
+ 
+       usb_stor_dbg(us, "%s called\n", __func__);
+ 
++      /* abort any pending command before reset */
++      command_abort_matching(us, NULL);
++
+       /* lock the device pointers and do the reset */
+       mutex_lock(&(us->dev_mutex));
+       result = us->transport_reset(us);
+diff --git a/drivers/xen/pvcalls-back.c b/drivers/xen/pvcalls-back.c
+index b13d03aba791a..e472ed057c175 100644
+--- a/drivers/xen/pvcalls-back.c
++++ b/drivers/xen/pvcalls-back.c
+@@ -338,8 +338,10 @@ static struct sock_mapping *pvcalls_new_active_socket(
+       void *page;
+ 
+       map = kzalloc(sizeof(*map), GFP_KERNEL);
+-      if (map == NULL)
++      if (map == NULL) {
++              sock_release(sock);
+               return NULL;
++      }
+ 
+       map->fedata = fedata;
+       map->sock = sock;
+@@ -431,10 +433,8 @@ static int pvcalls_back_connect(struct xenbus_device *dev,
+                                       req->u.connect.ref,
+                                       req->u.connect.evtchn,
+                                       sock);
+-      if (!map) {
++      if (!map)
+               ret = -EFAULT;
+-              sock_release(sock);
+-      }
+ 
+ out:
+       rsp = RING_GET_RESPONSE(&fedata->ring, fedata->ring.rsp_prod_pvt++);
+@@ -575,7 +575,6 @@ static void __pvcalls_back_accept(struct work_struct *work)
+                                       sock);
+       if (!map) {
+               ret = -EFAULT;
+-              sock_release(sock);
+               goto out_error;
+       }
+ 
+diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
+index 29ed1688a1d3a..e12fa3a723db5 100644
+--- a/fs/ceph/snap.c
++++ b/fs/ceph/snap.c
+@@ -959,6 +959,19 @@ skip_inode:
+                               continue;
+                       adjust_snap_realm_parent(mdsc, child, realm->ino);
+               }
++      } else {
++              /*
++               * In the non-split case both 'num_split_inos' and
++               * 'num_split_realms' should be 0, making this a no-op.
++               * However the MDS happens to populate 'split_realms' list
++               * in one of the UPDATE op cases by mistake.
++               *
++               * Skip both lists just in case to ensure that 'p' is
++               * positioned at the start of realm info, as expected by
++               * ceph_update_snap_trace().
++               */
++              p += sizeof(u64) * num_split_inos;
++              p += sizeof(u64) * num_split_realms;
+       }
+ 
+       /*
+diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
+index 032295e1d3865..b500fed96a692 100644
+--- a/fs/ext2/ext2.h
++++ b/fs/ext2/ext2.h
+@@ -177,6 +177,7 @@ static inline struct ext2_sb_info *EXT2_SB(struct 
super_block *sb)
+ #define EXT2_MIN_BLOCK_SIZE           1024
+ #define       EXT2_MAX_BLOCK_SIZE             4096
+ #define EXT2_MIN_BLOCK_LOG_SIZE                 10
++#define EXT2_MAX_BLOCK_LOG_SIZE                 16
+ #define EXT2_BLOCK_SIZE(s)            ((s)->s_blocksize)
+ #define       EXT2_ADDR_PER_BLOCK(s)          (EXT2_BLOCK_SIZE(s) / sizeof 
(__u32))
+ #define EXT2_BLOCK_SIZE_BITS(s)               ((s)->s_blocksize_bits)
+diff --git a/fs/ext2/super.c b/fs/ext2/super.c
+index 5f7079b65426c..7ca9fb0bfc324 100644
+--- a/fs/ext2/super.c
++++ b/fs/ext2/super.c
+@@ -965,6 +965,13 @@ static int ext2_fill_super(struct super_block *sb, void 
*data, int silent)
+               goto failed_mount;
+       }
+ 
++      if (le32_to_cpu(es->s_log_block_size) >
++          (EXT2_MAX_BLOCK_LOG_SIZE - BLOCK_SIZE_BITS)) {
++              ext2_msg(sb, KERN_ERR,
++                       "Invalid log block size: %u",
++                       le32_to_cpu(es->s_log_block_size));
++              goto failed_mount;
++      }
+       blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
+ 
+       if (sbi->s_mount_opt & EXT2_MOUNT_DAX) {
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index d9f2fde2e3e92..ce21da3f437f0 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -3116,6 +3116,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context 
*ac,
+                               struct ext4_allocation_request *ar)
+ {
+       struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb);
++      struct ext4_super_block *es = sbi->s_es;
+       int bsbits, max;
+       ext4_lblk_t end;
+       loff_t size, start_off;
+@@ -3296,18 +3297,21 @@ ext4_mb_normalize_request(struct 
ext4_allocation_context *ac,
+       ac->ac_g_ex.fe_len = EXT4_NUM_B2C(sbi, size);
+ 
+       /* define goal start in order to merge */
+-      if (ar->pright && (ar->lright == (start + size))) {
++      if (ar->pright && (ar->lright == (start + size)) &&
++          ar->pright >= size &&
++          ar->pright - size >= le32_to_cpu(es->s_first_data_block)) {
+               /* merge to the right */
+               ext4_get_group_no_and_offset(ac->ac_sb, ar->pright - size,
+-                                              &ac->ac_f_ex.fe_group,
+-                                              &ac->ac_f_ex.fe_start);
++                                              &ac->ac_g_ex.fe_group,
++                                              &ac->ac_g_ex.fe_start);
+               ac->ac_flags |= EXT4_MB_HINT_TRY_GOAL;
+       }
+-      if (ar->pleft && (ar->lleft + 1 == start)) {
++      if (ar->pleft && (ar->lleft + 1 == start) &&
++          ar->pleft + 1 < ext4_blocks_count(es)) {
+               /* merge to the left */
+               ext4_get_group_no_and_offset(ac->ac_sb, ar->pleft + 1,
+-                                              &ac->ac_f_ex.fe_group,
+-                                              &ac->ac_f_ex.fe_start);
++                                              &ac->ac_g_ex.fe_group,
++                                              &ac->ac_g_ex.fe_start);
+               ac->ac_flags |= EXT4_MB_HINT_TRY_GOAL;
+       }
+ 
+@@ -3399,6 +3403,7 @@ static void ext4_mb_use_inode_pa(struct 
ext4_allocation_context *ac,
+       BUG_ON(start < pa->pa_pstart);
+       BUG_ON(end > pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len));
+       BUG_ON(pa->pa_free < len);
++      BUG_ON(ac->ac_b_ex.fe_len <= 0);
+       pa->pa_free -= len;
+ 
+       mb_debug(1, "use %llu/%u from inode pa %p\n", start, len, pa);
+@@ -3703,10 +3708,8 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+               return -ENOMEM;
+ 
+       if (ac->ac_b_ex.fe_len < ac->ac_g_ex.fe_len) {
+-              int winl;
+-              int wins;
+-              int win;
+-              int offs;
++              int new_bex_start;
++              int new_bex_end;
+ 
+               /* we can't allocate as much as normalizer wants.
+                * so, found space must get proper lstart
+@@ -3714,26 +3717,40 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context 
*ac)
+               BUG_ON(ac->ac_g_ex.fe_logical > ac->ac_o_ex.fe_logical);
+               BUG_ON(ac->ac_g_ex.fe_len < ac->ac_o_ex.fe_len);
+ 
+-              /* we're limited by original request in that
+-               * logical block must be covered any way
+-               * winl is window we can move our chunk within */
+-              winl = ac->ac_o_ex.fe_logical - ac->ac_g_ex.fe_logical;
++              /*
++               * Use the below logic for adjusting best extent as it keeps
++               * fragmentation in check while ensuring logical range of best
++               * extent doesn't overflow out of goal extent:
++               *
++               * 1. Check if best ex can be kept at end of goal and still
++               *    cover original start
++               * 2. Else, check if best ex can be kept at start of goal and
++               *    still cover original start
++               * 3. Else, keep the best ex at start of original request.
++               */
++              new_bex_end = ac->ac_g_ex.fe_logical +
++                      EXT4_C2B(sbi, ac->ac_g_ex.fe_len);
++              new_bex_start = new_bex_end - EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
++              if (ac->ac_o_ex.fe_logical >= new_bex_start)
++                      goto adjust_bex;
+ 
+-              /* also, we should cover whole original request */
+-              wins = EXT4_C2B(sbi, ac->ac_b_ex.fe_len - ac->ac_o_ex.fe_len);
++              new_bex_start = ac->ac_g_ex.fe_logical;
++              new_bex_end =
++                      new_bex_start + EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
++              if (ac->ac_o_ex.fe_logical < new_bex_end)
++                      goto adjust_bex;
+ 
+-              /* the smallest one defines real window */
+-              win = min(winl, wins);
++              new_bex_start = ac->ac_o_ex.fe_logical;
++              new_bex_end =
++                      new_bex_start + EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
+ 
+-              offs = ac->ac_o_ex.fe_logical %
+-                      EXT4_C2B(sbi, ac->ac_b_ex.fe_len);
+-              if (offs && offs < win)
+-                      win = offs;
++adjust_bex:
++              ac->ac_b_ex.fe_logical = new_bex_start;
+ 
+-              ac->ac_b_ex.fe_logical = ac->ac_o_ex.fe_logical -
+-                      EXT4_NUM_B2C(sbi, win);
+               BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical);
+               BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len);
++              BUG_ON(new_bex_end > (ac->ac_g_ex.fe_logical +
++                                    EXT4_C2B(sbi, ac->ac_g_ex.fe_len)));
+       }
+ 
+       /* preallocation can change ac_b_ex, thus we store actually
+diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
+index f1844af4005b6..4838e26c06f74 100644
+--- a/fs/gfs2/glops.c
++++ b/fs/gfs2/glops.c
+@@ -333,6 +333,7 @@ static int inode_go_demote_ok(const struct gfs2_glock *gl)
+ 
+ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
+ {
++      struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+       const struct gfs2_dinode *str = buf;
+       struct timespec atime;
+       u16 height, depth;
+@@ -372,7 +373,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const 
void *buf)
+       /* i_diskflags and i_eattr must be set before gfs2_set_inode_flags() */
+       gfs2_set_inode_flags(&ip->i_inode);
+       height = be16_to_cpu(str->di_height);
+-      if (unlikely(height > GFS2_MAX_META_HEIGHT))
++      if (unlikely(height > sdp->sd_max_height))
+               goto corrupt;
+       ip->i_height = (u8)height;
+ 
+diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
+index ccb2a94c2032a..4924a489c8ac0 100644
+--- a/fs/hfsplus/inode.c
++++ b/fs/hfsplus/inode.c
+@@ -488,7 +488,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct 
hfs_find_data *fd)
+       if (type == HFSPLUS_FOLDER) {
+               struct hfsplus_cat_folder *folder = &entry.folder;
+ 
+-              WARN_ON(fd->entrylength < sizeof(struct hfsplus_cat_folder));
++              if (fd->entrylength < sizeof(struct hfsplus_cat_folder)) {
++                      pr_err("bad catalog folder entry\n");
++                      res = -EIO;
++                      goto out;
++              }
+               hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
+                                       sizeof(struct hfsplus_cat_folder));
+               hfsplus_get_perms(inode, &folder->permissions, 1);
+@@ -508,7 +512,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct 
hfs_find_data *fd)
+       } else if (type == HFSPLUS_FILE) {
+               struct hfsplus_cat_file *file = &entry.file;
+ 
+-              WARN_ON(fd->entrylength < sizeof(struct hfsplus_cat_file));
++              if (fd->entrylength < sizeof(struct hfsplus_cat_file)) {
++                      pr_err("bad catalog file entry\n");
++                      res = -EIO;
++                      goto out;
++              }
+               hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
+                                       sizeof(struct hfsplus_cat_file));
+ 
+@@ -539,6 +547,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct 
hfs_find_data *fd)
+               pr_err("bad catalog entry used to create inode\n");
+               res = -EIO;
+       }
++out:
+       return res;
+ }
+ 
+@@ -547,6 +556,7 @@ int hfsplus_cat_write_inode(struct inode *inode)
+       struct inode *main_inode = inode;
+       struct hfs_find_data fd;
+       hfsplus_cat_entry entry;
++      int res = 0;
+ 
+       if (HFSPLUS_IS_RSRC(inode))
+               main_inode = HFSPLUS_I(inode)->rsrc_inode;
+@@ -565,7 +575,11 @@ int hfsplus_cat_write_inode(struct inode *inode)
+       if (S_ISDIR(main_inode->i_mode)) {
+               struct hfsplus_cat_folder *folder = &entry.folder;
+ 
+-              WARN_ON(fd.entrylength < sizeof(struct hfsplus_cat_folder));
++              if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
++                      pr_err("bad catalog folder entry\n");
++                      res = -EIO;
++                      goto out;
++              }
+               hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
+                                       sizeof(struct hfsplus_cat_folder));
+               /* simple node checks? */
+@@ -590,7 +604,11 @@ int hfsplus_cat_write_inode(struct inode *inode)
+       } else {
+               struct hfsplus_cat_file *file = &entry.file;
+ 
+-              WARN_ON(fd.entrylength < sizeof(struct hfsplus_cat_file));
++              if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
++                      pr_err("bad catalog file entry\n");
++                      res = -EIO;
++                      goto out;
++              }
+               hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
+                                       sizeof(struct hfsplus_cat_file));
+               hfsplus_inode_write_fork(inode, &file->data_fork);
+@@ -611,5 +629,5 @@ int hfsplus_cat_write_inode(struct inode *inode)
+       set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
+ out:
+       hfs_find_exit(&fd);
+-      return 0;
++      return res;
+ }
+diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
+index 39ef2d336265e..9c7971c196c9c 100644
+--- a/fs/nilfs2/inode.c
++++ b/fs/nilfs2/inode.c
+@@ -939,6 +939,7 @@ void nilfs_evict_inode(struct inode *inode)
+       struct nilfs_transaction_info ti;
+       struct super_block *sb = inode->i_sb;
+       struct nilfs_inode_info *ii = NILFS_I(inode);
++      struct the_nilfs *nilfs;
+       int ret;
+ 
+       if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) {
+@@ -951,6 +952,23 @@ void nilfs_evict_inode(struct inode *inode)
+ 
+       truncate_inode_pages_final(&inode->i_data);
+ 
++      nilfs = sb->s_fs_info;
++      if (unlikely(sb_rdonly(sb) || !nilfs->ns_writer)) {
++              /*
++               * If this inode is about to be disposed after the file system
++               * has been degraded to read-only due to file system corruption
++               * or after the writer has been detached, do not make any
++               * changes that cause writes, just clear it.
++               * Do this check after read-locking ns_segctor_sem by
++               * nilfs_transaction_begin() in order to avoid a race with
++               * the writer detach operation.
++               */
++              clear_inode(inode);
++              nilfs_clear_inode(inode);
++              nilfs_transaction_abort(sb);
++              return;
++      }
++
+       /* TODO: some of the following operations may fail.  */
+       nilfs_truncate_bmap(ii, 0);
+       nilfs_mark_inode_dirty(inode);
+diff --git a/fs/statfs.c b/fs/statfs.c
+index ca1084cbe03cf..e6ceb3e8774f6 100644
+--- a/fs/statfs.c
++++ b/fs/statfs.c
+@@ -114,6 +114,7 @@ static int do_statfs_native(struct kstatfs *st, struct 
statfs __user *p)
+       if (sizeof(buf) == sizeof(*st))
+               memcpy(&buf, st, sizeof(*st));
+       else {
++              memset(&buf, 0, sizeof(buf));
+               if (sizeof buf.f_blocks == 4) {
+                       if ((st->f_blocks | st->f_bfree | st->f_bavail |
+                            st->f_bsize | st->f_frsize) &
+@@ -142,7 +143,6 @@ static int do_statfs_native(struct kstatfs *st, struct 
statfs __user *p)
+               buf.f_namelen = st->f_namelen;
+               buf.f_frsize = st->f_frsize;
+               buf.f_flags = st->f_flags;
+-              memset(buf.f_spare, 0, sizeof(buf.f_spare));
+       }
+       if (copy_to_user(p, &buf, sizeof(buf)))
+               return -EFAULT;
+@@ -155,6 +155,7 @@ static int do_statfs64(struct kstatfs *st, struct statfs64 
__user *p)
+       if (sizeof(buf) == sizeof(*st))
+               memcpy(&buf, st, sizeof(*st));
+       else {
++              memset(&buf, 0, sizeof(buf));
+               buf.f_type = st->f_type;
+               buf.f_bsize = st->f_bsize;
+               buf.f_blocks = st->f_blocks;
+@@ -166,7 +167,6 @@ static int do_statfs64(struct kstatfs *st, struct statfs64 
__user *p)
+               buf.f_namelen = st->f_namelen;
+               buf.f_frsize = st->f_frsize;
+               buf.f_flags = st->f_flags;
+-              memset(buf.f_spare, 0, sizeof(buf.f_spare));
+       }
+       if (copy_to_user(p, &buf, sizeof(buf)))
+               return -EFAULT;
+diff --git a/include/linux/power/bq27xxx_battery.h 
b/include/linux/power/bq27xxx_battery.h
+index 534a8080c6a3b..2fd8a204ab81b 100644
+--- a/include/linux/power/bq27xxx_battery.h
++++ b/include/linux/power/bq27xxx_battery.h
+@@ -61,6 +61,7 @@ struct bq27xxx_device_info {
+       struct bq27xxx_access_methods bus;
+       struct bq27xxx_reg_cache cache;
+       int charge_design_full;
++      bool removed;
+       unsigned long last_update;
+       struct delayed_work work;
+       struct power_supply *bat;
+diff --git a/include/linux/sched/task_stack.h 
b/include/linux/sched/task_stack.h
+index 3461beb89b040..62d1cd4db27af 100644
+--- a/include/linux/sched/task_stack.h
++++ b/include/linux/sched/task_stack.h
+@@ -23,7 +23,7 @@ static inline void *task_stack_page(const struct task_struct 
*task)
+ 
+ #define setup_thread_stack(new,old)   do { } while(0)
+ 
+-static inline unsigned long *end_of_stack(const struct task_struct *task)
++static __always_inline unsigned long *end_of_stack(const struct task_struct 
*task)
+ {
+ #ifdef CONFIG_STACK_GROWSUP
+       return (unsigned long *)((unsigned long)task->stack + THREAD_SIZE) - 1;
+diff --git a/include/linux/usb.h b/include/linux/usb.h
+index b2c35d3b83726..89f9865921cba 100644
+--- a/include/linux/usb.h
++++ b/include/linux/usb.h
+@@ -279,6 +279,11 @@ void usb_put_intf(struct usb_interface *intf);
+ #define USB_MAXINTERFACES     32
+ #define USB_MAXIADS           (USB_MAXINTERFACES/2)
+ 
++bool usb_check_bulk_endpoints(
++              const struct usb_interface *intf, const u8 *ep_addrs);
++bool usb_check_int_endpoints(
++              const struct usb_interface *intf, const u8 *ep_addrs);
++
+ /*
+  * USB Resume Timer: Every Host controller driver should drive the resume
+  * signalling on the bus for the amount of time defined by this macro.
+diff --git a/include/net/netfilter/nf_tables.h 
b/include/net/netfilter/nf_tables.h
+index 2db486e9724c6..0d625ff7841ad 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -195,14 +195,13 @@ static inline enum nft_registers nft_type_to_reg(enum 
nft_data_types type)
+ }
+ 
+ int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest);
+-unsigned int nft_parse_register(const struct nlattr *attr);
+ int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int 
reg);
+ 
+-int nft_validate_register_load(enum nft_registers reg, unsigned int len);
+-int nft_validate_register_store(const struct nft_ctx *ctx,
+-                              enum nft_registers reg,
+-                              const struct nft_data *data,
+-                              enum nft_data_types type, unsigned int len);
++int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len);
++int nft_parse_register_store(const struct nft_ctx *ctx,
++                           const struct nlattr *attr, u8 *dreg,
++                           const struct nft_data *data,
++                           enum nft_data_types type, unsigned int len);
+ 
+ /**
+  *    struct nft_userdata - user defined data associated with an object
+@@ -230,6 +229,10 @@ struct nft_set_elem {
+               u32             buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)];
+               struct nft_data val;
+       } key;
++      union {
++              u32             buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)];
++              struct nft_data val;
++      } data;
+       void                    *priv;
+ };
+ 
+@@ -378,6 +381,7 @@ void nft_unregister_set(struct nft_set_type *type);
+  *
+  *    @list: table set list node
+  *    @bindings: list of set bindings
++ *    @table: table this set belongs to
+  *    @name: name of the set
+  *    @ktype: key type (numeric type defined by userspace, not used in the 
kernel)
+  *    @dtype: data type (verdict or numeric type defined by userspace)
+@@ -401,6 +405,7 @@ void nft_unregister_set(struct nft_set_type *type);
+ struct nft_set {
+       struct list_head                list;
+       struct list_head                bindings;
++      struct nft_table                *table;
+       char                            *name;
+       u32                             ktype;
+       u32                             dtype;
+diff --git a/include/net/netfilter/nf_tables_core.h 
b/include/net/netfilter/nf_tables_core.h
+index ea5aab568be83..98bd13fbfa896 100644
+--- a/include/net/netfilter/nf_tables_core.h
++++ b/include/net/netfilter/nf_tables_core.h
+@@ -14,9 +14,17 @@ extern struct nft_expr_type nft_range_type;
+ int nf_tables_core_module_init(void);
+ void nf_tables_core_module_exit(void);
+ 
++struct nft_bitwise_fast_expr {
++      u32                     mask;
++      u32                     xor;
++      u8                      sreg;
++      u8                      dreg;
++};
++
+ struct nft_cmp_fast_expr {
+       u32                     data;
+-      enum nft_registers      sreg:8;
++      u32                     mask;
++      u8                      sreg;
+       u8                      len;
+ };
+ 
+@@ -36,14 +44,14 @@ struct nft_payload {
+       enum nft_payload_bases  base:8;
+       u8                      offset;
+       u8                      len;
+-      enum nft_registers      dreg:8;
++      u8                      dreg;
+ };
+ 
+ struct nft_payload_set {
+       enum nft_payload_bases  base:8;
+       u8                      offset;
+       u8                      len;
+-      enum nft_registers      sreg:8;
++      u8                      sreg;
+       u8                      csum_type;
+       u8                      csum_offset;
+       u8                      csum_flags;
+diff --git a/include/net/netfilter/nft_fib.h b/include/net/netfilter/nft_fib.h
+index a88f92737308d..1f87267395291 100644
+--- a/include/net/netfilter/nft_fib.h
++++ b/include/net/netfilter/nft_fib.h
+@@ -3,7 +3,7 @@
+ #define _NFT_FIB_H_
+ 
+ struct nft_fib {
+-      enum nft_registers      dreg:8;
++      u8                      dreg;
+       u8                      result;
+       u32                     flags;
+ };
+diff --git a/include/net/netfilter/nft_masq.h 
b/include/net/netfilter/nft_masq.h
+index e51ab3815797b..e69a8277b70b3 100644
+--- a/include/net/netfilter/nft_masq.h
++++ b/include/net/netfilter/nft_masq.h
+@@ -4,8 +4,8 @@
+ 
+ struct nft_masq {
+       u32                     flags;
+-      enum nft_registers      sreg_proto_min:8;
+-      enum nft_registers      sreg_proto_max:8;
++      u8                      sreg_proto_min;
++      u8                      sreg_proto_max;
+ };
+ 
+ extern const struct nla_policy nft_masq_policy[];
+diff --git a/include/net/netfilter/nft_meta.h 
b/include/net/netfilter/nft_meta.h
+index 5c69e9b093887..f64b8197c8074 100644
+--- a/include/net/netfilter/nft_meta.h
++++ b/include/net/netfilter/nft_meta.h
+@@ -5,8 +5,8 @@
+ struct nft_meta {
+       enum nft_meta_keys      key:8;
+       union {
+-              enum nft_registers      dreg:8;
+-              enum nft_registers      sreg:8;
++              u8              dreg;
++              u8              sreg;
+       };
+ };
+ 
+diff --git a/include/net/netfilter/nft_redir.h 
b/include/net/netfilter/nft_redir.h
+index 4a970737c03c8..2b4036c94cb3e 100644
+--- a/include/net/netfilter/nft_redir.h
++++ b/include/net/netfilter/nft_redir.h
+@@ -3,8 +3,8 @@
+ #define _NFT_REDIR_H_
+ 
+ struct nft_redir {
+-      enum nft_registers      sreg_proto_min:8;
+-      enum nft_registers      sreg_proto_max:8;
++      u8                      sreg_proto_min;
++      u8                      sreg_proto_max;
+       u16                     flags;
+ };
+ 
+diff --git a/include/net/sock.h b/include/net/sock.h
+index f6d0d96419b1e..ee1a2217a98c0 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -2317,7 +2317,7 @@ static inline void sock_recv_ts_and_drops(struct msghdr 
*msg, struct sock *sk,
+               __sock_recv_ts_and_drops(msg, sk, skb);
+       else if (unlikely(sock_flag(sk, SOCK_TIMESTAMP)))
+               sock_write_timestamp(sk, skb->tstamp);
+-      else if (unlikely(sk->sk_stamp == SK_DEFAULT_STAMP))
++      else if (unlikely(sock_read_timestamp(sk) == SK_DEFAULT_STAMP))
+               sock_write_timestamp(sk, 0);
+ }
+ 
+diff --git a/include/uapi/linux/netfilter/nf_tables.h 
b/include/uapi/linux/netfilter/nf_tables.h
+index 49b6997c32550..c7bb18ea49623 100644
+--- a/include/uapi/linux/netfilter/nf_tables.h
++++ b/include/uapi/linux/netfilter/nf_tables.h
+@@ -258,7 +258,7 @@ enum nft_rule_compat_attributes {
+  * @NFT_SET_INTERVAL: set contains intervals
+  * @NFT_SET_MAP: set is used as a dictionary
+  * @NFT_SET_TIMEOUT: set uses timeouts
+- * @NFT_SET_EVAL: set contains expressions for evaluation
++ * @NFT_SET_EVAL: set can be updated from the evaluation path
+  * @NFT_SET_OBJECT: set contains stateful objects
+  */
+ enum nft_set_flags {
+diff --git a/lib/cpu_rmap.c b/lib/cpu_rmap.c
+index f610b2a10b3ed..f52389054a24f 100644
+--- a/lib/cpu_rmap.c
++++ b/lib/cpu_rmap.c
+@@ -235,7 +235,8 @@ void free_irq_cpu_rmap(struct cpu_rmap *rmap)
+ 
+       for (index = 0; index < rmap->used; index++) {
+               glue = rmap->obj[index];
+-              irq_set_affinity_notifier(glue->notify.irq, NULL);
++              if (glue)
++                      irq_set_affinity_notifier(glue->notify.irq, NULL);
+       }
+ 
+       cpu_rmap_put(rmap);
+@@ -271,6 +272,7 @@ static void irq_cpu_rmap_release(struct kref *ref)
+               container_of(ref, struct irq_glue, notify.kref);
+ 
+       cpu_rmap_put(glue->rmap);
++      glue->rmap->obj[glue->index] = NULL;
+       kfree(glue);
+ }
+ 
+@@ -300,6 +302,7 @@ int irq_cpu_rmap_add(struct cpu_rmap *rmap, int irq)
+       rc = irq_set_affinity_notifier(irq, &glue->notify);
+       if (rc) {
+               cpu_rmap_put(glue->rmap);
++              rmap->obj[glue->index] = NULL;
+               kfree(glue);
+       }
+       return rc;
+diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
+index e871d3b27c479..c436c9973455b 100644
+--- a/net/8021q/vlan_dev.c
++++ b/net/8021q/vlan_dev.c
+@@ -115,8 +115,8 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff 
*skb,
+        * NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING
+        * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs...
+        */
+-      if (veth->h_vlan_proto != vlan->vlan_proto ||
+-          vlan->flags & VLAN_FLAG_REORDER_HDR) {
++      if (vlan->flags & VLAN_FLAG_REORDER_HDR ||
++          veth->h_vlan_proto != vlan->vlan_proto) {
+               u16 vlan_tci;
+               vlan_tci = vlan->vlan_id;
+               vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb->priority);
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 6f47cb69775d6..b0bb4cf52a7ee 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -4392,7 +4392,6 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn 
*conn,
+ 
+       chan = l2cap_get_chan_by_scid(conn, scid);
+       if (!chan) {
+-              mutex_unlock(&conn->chan_lock);
+               return 0;
+       }
+ 
+diff --git a/net/bridge/netfilter/nft_meta_bridge.c 
b/net/bridge/netfilter/nft_meta_bridge.c
+index bb63c9aed55d2..985ff136b674c 100644
+--- a/net/bridge/netfilter/nft_meta_bridge.c
++++ b/net/bridge/netfilter/nft_meta_bridge.c
+@@ -65,9 +65,8 @@ static int nft_meta_bridge_get_init(const struct nft_ctx 
*ctx,
+               return nft_meta_get_init(ctx, expr, tb);
+       }
+ 
+-      priv->dreg = nft_parse_register(tb[NFTA_META_DREG]);
+-      return nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                         NFT_DATA_VALUE, len);
++      return nft_parse_register_store(ctx, tb[NFTA_META_DREG], &priv->dreg,
++                                      NULL, NFT_DATA_VALUE, len);
+ }
+ 
+ static struct nft_expr_type nft_meta_bridge_type;
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 86f762a1cf7ac..a4d68da682322 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -2165,6 +2165,8 @@ int netif_set_xps_queue(struct net_device *dev, const 
struct cpumask *mask,
+       struct xps_map *map, *new_map;
+       bool active = false;
+ 
++      WARN_ON_ONCE(index >= dev->num_tx_queues);
++
+       if (dev->num_tc) {
+               num_tc = dev->num_tc;
+               tc = netdev_txq_to_tc(dev, index);
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 71827da47274c..6b6309ec7b1bb 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -4421,8 +4421,10 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
+       } else {
+               skb = skb_clone(orig_skb, GFP_ATOMIC);
+ 
+-              if (skb_orphan_frags_rx(skb, GFP_ATOMIC))
++              if (skb_orphan_frags_rx(skb, GFP_ATOMIC)) {
++                      kfree_skb(skb);
+                       return;
++              }
+       }
+       if (!skb)
+               return;
+diff --git a/net/ipv4/netfilter/nft_dup_ipv4.c 
b/net/ipv4/netfilter/nft_dup_ipv4.c
+index 0af3d8df70dd7..157bca240edce 100644
+--- a/net/ipv4/netfilter/nft_dup_ipv4.c
++++ b/net/ipv4/netfilter/nft_dup_ipv4.c
+@@ -16,8 +16,8 @@
+ #include <net/netfilter/ipv4/nf_dup_ipv4.h>
+ 
+ struct nft_dup_ipv4 {
+-      enum nft_registers      sreg_addr:8;
+-      enum nft_registers      sreg_dev:8;
++      u8      sreg_addr;
++      u8      sreg_dev;
+ };
+ 
+ static void nft_dup_ipv4_eval(const struct nft_expr *expr,
+@@ -43,16 +43,16 @@ static int nft_dup_ipv4_init(const struct nft_ctx *ctx,
+       if (tb[NFTA_DUP_SREG_ADDR] == NULL)
+               return -EINVAL;
+ 
+-      priv->sreg_addr = nft_parse_register(tb[NFTA_DUP_SREG_ADDR]);
+-      err = nft_validate_register_load(priv->sreg_addr, sizeof(struct 
in_addr));
++      err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr,
++                                    sizeof(struct in_addr));
+       if (err < 0)
+               return err;
+ 
+-      if (tb[NFTA_DUP_SREG_DEV] != NULL) {
+-              priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]);
+-              return nft_validate_register_load(priv->sreg_dev, sizeof(int));
+-      }
+-      return 0;
++      if (tb[NFTA_DUP_SREG_DEV])
++              err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV],
++                                            &priv->sreg_dev, sizeof(int));
++
++      return err;
+ }
+ 
+ static int nft_dup_ipv4_dump(struct sk_buff *skb, const struct nft_expr *expr)
+diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
+index 305e2ed730bf4..d57d62efa6bdd 100644
+--- a/net/ipv6/exthdrs_core.c
++++ b/net/ipv6/exthdrs_core.c
+@@ -142,6 +142,8 @@ int ipv6_find_tlv(const struct sk_buff *skb, int offset, 
int type)
+                       optlen = 1;
+                       break;
+               default:
++                      if (len < 2)
++                              goto bad;
+                       optlen = nh[offset + 1] + 2;
+                       if (optlen > len)
+                               goto bad;
+diff --git a/net/ipv6/netfilter/nft_dup_ipv6.c 
b/net/ipv6/netfilter/nft_dup_ipv6.c
+index d8b5b60b7d531..d8bb7c85287cb 100644
+--- a/net/ipv6/netfilter/nft_dup_ipv6.c
++++ b/net/ipv6/netfilter/nft_dup_ipv6.c
+@@ -16,8 +16,8 @@
+ #include <net/netfilter/ipv6/nf_dup_ipv6.h>
+ 
+ struct nft_dup_ipv6 {
+-      enum nft_registers      sreg_addr:8;
+-      enum nft_registers      sreg_dev:8;
++      u8      sreg_addr;
++      u8      sreg_dev;
+ };
+ 
+ static void nft_dup_ipv6_eval(const struct nft_expr *expr,
+@@ -41,16 +41,16 @@ static int nft_dup_ipv6_init(const struct nft_ctx *ctx,
+       if (tb[NFTA_DUP_SREG_ADDR] == NULL)
+               return -EINVAL;
+ 
+-      priv->sreg_addr = nft_parse_register(tb[NFTA_DUP_SREG_ADDR]);
+-      err = nft_validate_register_load(priv->sreg_addr, sizeof(struct 
in6_addr));
++      err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr,
++                                    sizeof(struct in6_addr));
+       if (err < 0)
+               return err;
+ 
+-      if (tb[NFTA_DUP_SREG_DEV] != NULL) {
+-              priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]);
+-              return nft_validate_register_load(priv->sreg_dev, sizeof(int));
+-      }
+-      return 0;
++      if (tb[NFTA_DUP_SREG_DEV])
++              err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV],
++                                            &priv->sreg_dev, sizeof(int));
++
++      return err;
+ }
+ 
+ static int nft_dup_ipv6_dump(struct sk_buff *skb, const struct nft_expr *expr)
+diff --git a/net/key/af_key.c b/net/key/af_key.c
+index 09a0ea651f577..49813e6d05ed7 100644
+--- a/net/key/af_key.c
++++ b/net/key/af_key.c
+@@ -1950,7 +1950,8 @@ static u32 gen_reqid(struct net *net)
+ }
+ 
+ static int
+-parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
++parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_policy *pol,
++                 struct sadb_x_ipsecrequest *rq)
+ {
+       struct net *net = xp_net(xp);
+       struct xfrm_tmpl *t = xp->xfrm_vec + xp->xfrm_nr;
+@@ -1968,9 +1969,12 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct 
sadb_x_ipsecrequest *rq)
+       if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0)
+               return -EINVAL;
+       t->mode = mode;
+-      if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE)
++      if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_USE) {
++              if ((mode == XFRM_MODE_TUNNEL || mode == XFRM_MODE_BEET) &&
++                  pol->sadb_x_policy_dir == IPSEC_DIR_OUTBOUND)
++                      return -EINVAL;
+               t->optional = 1;
+-      else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
++      } else if (rq->sadb_x_ipsecrequest_level == IPSEC_LEVEL_UNIQUE) {
+               t->reqid = rq->sadb_x_ipsecrequest_reqid;
+               if (t->reqid > IPSEC_MANUAL_REQID_MAX)
+                       t->reqid = 0;
+@@ -2012,7 +2016,7 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct 
sadb_x_policy *pol)
+                   rq->sadb_x_ipsecrequest_len < sizeof(*rq))
+                       return -EINVAL;
+ 
+-              if ((err = parse_ipsecrequest(xp, rq)) < 0)
++              if ((err = parse_ipsecrequest(xp, pol, rq)) < 0)
+                       return err;
+               len -= rq->sadb_x_ipsecrequest_len;
+               rq = (void*)((u8*)rq + rq->sadb_x_ipsecrequest_len);
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index c683a45b8ae53..241a3032d0e66 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -2475,6 +2475,7 @@ err1:
+ }
+ 
+ static struct nft_rule *nft_rule_lookup_byid(const struct net *net,
++                                           const struct nft_chain *chain,
+                                            const struct nlattr *nla)
+ {
+       u32 id = ntohl(nla_get_be32(nla));
+@@ -2484,6 +2485,7 @@ static struct nft_rule *nft_rule_lookup_byid(const 
struct net *net,
+               struct nft_rule *rule = nft_trans_rule(trans);
+ 
+               if (trans->msg_type == NFT_MSG_NEWRULE &&
++                  trans->ctx.chain == chain &&
+                   id == nft_trans_rule_id(trans))
+                       return rule;
+       }
+@@ -2530,7 +2532,7 @@ static int nf_tables_delrule(struct net *net, struct 
sock *nlsk,
+ 
+                       err = nft_delrule(&ctx, rule);
+               } else if (nla[NFTA_RULE_ID]) {
+-                      rule = nft_rule_lookup_byid(net, nla[NFTA_RULE_ID]);
++                      rule = nft_rule_lookup_byid(net, chain, 
nla[NFTA_RULE_ID]);
+                       if (IS_ERR(rule))
+                               return PTR_ERR(rule);
+ 
+@@ -2744,6 +2746,7 @@ static struct nft_set *nf_tables_set_lookup(const struct 
nft_table *table,
+ }
+ 
+ static struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
++                                               const struct nft_table *table,
+                                                const struct nlattr *nla,
+                                                u8 genmask)
+ {
+@@ -2755,6 +2758,7 @@ static struct nft_set *nf_tables_set_lookup_byid(const 
struct net *net,
+                       struct nft_set *set = nft_trans_set(trans);
+ 
+                       if (id == nft_trans_set_id(trans) &&
++                          set->table == table &&
+                           nft_active_genmask(set, genmask))
+                               return set;
+               }
+@@ -2775,7 +2779,7 @@ struct nft_set *nft_set_lookup(const struct net *net,
+               if (!nla_set_id)
+                       return set;
+ 
+-              set = nf_tables_set_lookup_byid(net, nla_set_id, genmask);
++              set = nf_tables_set_lookup_byid(net, table, nla_set_id, 
genmask);
+       }
+       return set;
+ }
+@@ -3270,6 +3274,7 @@ static int nf_tables_newset(struct net *net, struct sock 
*nlsk,
+       }
+ 
+       INIT_LIST_HEAD(&set->bindings);
++      set->table = table;
+       set->ops   = ops;
+       set->ktype = ktype;
+       set->klen  = desc.klen;
+@@ -3349,6 +3354,12 @@ static int nf_tables_delset(struct net *net, struct 
sock *nlsk,
+       return nft_delset(&ctx, set);
+ }
+ 
++static int nft_validate_register_store(const struct nft_ctx *ctx,
++                                     enum nft_registers reg,
++                                     const struct nft_data *data,
++                                     enum nft_data_types type,
++                                     unsigned int len);
++
+ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
+                                       struct nft_set *set,
+                                       const struct nft_set_iter *iter,
+@@ -3730,6 +3741,24 @@ static int nf_tables_dump_set_done(struct 
netlink_callback *cb)
+       return 0;
+ }
+ 
++static int nft_setelem_parse_key(struct nft_ctx *ctx, struct nft_set *set,
++                               struct nft_data *key, struct nlattr *attr)
++{
++      struct nft_data_desc desc;
++      int err;
++
++      err = nft_data_init(ctx, key, NFT_DATA_VALUE_MAXLEN, &desc, attr);
++      if (err < 0)
++              return err;
++
++      if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) {
++              nft_data_release(key, desc.type);
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
+ static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,
+                               struct sk_buff *skb, const struct nlmsghdr *nlh,
+                               const struct nlattr * const nla[],
+@@ -3930,19 +3959,44 @@ static int nft_setelem_parse_flags(const struct 
nft_set *set,
+       return 0;
+ }
+ 
++static int nft_setelem_parse_data(struct nft_ctx *ctx, struct nft_set *set,
++                                struct nft_data_desc *desc,
++                                struct nft_data *data,
++                                struct nlattr *attr)
++{
++      u32 dtype;
++      int err;
++
++      err = nft_data_init(ctx, data, NFT_DATA_VALUE_MAXLEN, desc, attr);
++      if (err < 0)
++              return err;
++
++      if (set->dtype == NFT_DATA_VERDICT)
++              dtype = NFT_DATA_VERDICT;
++      else
++              dtype = NFT_DATA_VALUE;
++
++      if (dtype != desc->type ||
++          set->dlen != desc->len) {
++              nft_data_release(data, desc->type);
++              return -EINVAL;
++      }
++
++      return 0;
++}
++
+ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
+                           const struct nlattr *attr, u32 nlmsg_flags)
+ {
+       struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
+       u8 genmask = nft_genmask_next(ctx->net);
+-      struct nft_data_desc d1, d2;
+       struct nft_set_ext_tmpl tmpl;
+       struct nft_set_ext *ext, *ext2;
+       struct nft_set_elem elem;
+       struct nft_set_binding *binding;
+       struct nft_object *obj = NULL;
+       struct nft_userdata *udata;
+-      struct nft_data data;
++      struct nft_data_desc desc;
+       enum nft_registers dreg;
+       struct nft_trans *trans;
+       u32 flags = 0;
+@@ -3994,15 +4048,12 @@ static int nft_add_set_elem(struct nft_ctx *ctx, 
struct nft_set *set,
+               timeout = set->timeout;
+       }
+ 
+-      err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &d1,
+-                          nla[NFTA_SET_ELEM_KEY]);
++      err = nft_setelem_parse_key(ctx, set, &elem.key.val,
++                                  nla[NFTA_SET_ELEM_KEY]);
+       if (err < 0)
+               goto err1;
+-      err = -EINVAL;
+-      if (d1.type != NFT_DATA_VALUE || d1.len != set->klen)
+-              goto err2;
+ 
+-      nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, d1.len);
++      nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, set->klen);
+       if (timeout > 0) {
+               nft_set_ext_add(&tmpl, NFT_SET_EXT_EXPIRATION);
+               if (timeout != set->timeout)
+@@ -4024,15 +4075,11 @@ static int nft_add_set_elem(struct nft_ctx *ctx, 
struct nft_set *set,
+       }
+ 
+       if (nla[NFTA_SET_ELEM_DATA] != NULL) {
+-              err = nft_data_init(ctx, &data, sizeof(data), &d2,
+-                                  nla[NFTA_SET_ELEM_DATA]);
++              err = nft_setelem_parse_data(ctx, set, &desc, &elem.data.val,
++                                           nla[NFTA_SET_ELEM_DATA]);
+               if (err < 0)
+                       goto err2;
+ 
+-              err = -EINVAL;
+-              if (set->dtype != NFT_DATA_VERDICT && d2.len != set->dlen)
+-                      goto err3;
+-
+               dreg = nft_type_to_reg(set->dtype);
+               list_for_each_entry(binding, &set->bindings, list) {
+                       struct nft_ctx bind_ctx = {
+@@ -4046,13 +4093,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, 
struct nft_set *set,
+                               continue;
+ 
+                       err = nft_validate_register_store(&bind_ctx, dreg,
+-                                                        &data,
+-                                                        d2.type, d2.len);
++                                                        &elem.data.val,
++                                                        desc.type, desc.len);
+                       if (err < 0)
+                               goto err3;
+               }
+ 
+-              nft_set_ext_add_length(&tmpl, NFT_SET_EXT_DATA, d2.len);
++              nft_set_ext_add_length(&tmpl, NFT_SET_EXT_DATA, desc.len);
+       }
+ 
+       /* The full maximum length of userdata can exceed the maximum
+@@ -4068,7 +4115,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct 
nft_set *set,
+       }
+ 
+       err = -ENOMEM;
+-      elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, data.data,
++      elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data,
++                                    elem.data.val.data,
+                                     timeout, GFP_KERNEL);
+       if (elem.priv == NULL)
+               goto err3;
+@@ -4135,9 +4183,9 @@ err4:
+       kfree(elem.priv);
+ err3:
+       if (nla[NFTA_SET_ELEM_DATA] != NULL)
+-              nft_data_release(&data, d2.type);
++              nft_data_release(&elem.data.val, desc.type);
+ err2:
+-      nft_data_release(&elem.key.val, d1.type);
++      nft_data_release(&elem.key.val, NFT_DATA_VALUE);
+ err1:
+       return err;
+ }
+@@ -4164,7 +4212,7 @@ static int nf_tables_newsetelem(struct net *net, struct 
sock *nlsk,
+                                  genmask);
+       if (IS_ERR(set)) {
+               if (nla[NFTA_SET_ELEM_LIST_SET_ID]) {
+-                      set = nf_tables_set_lookup_byid(net,
++                      set = nf_tables_set_lookup_byid(net, ctx.table,
+                                       nla[NFTA_SET_ELEM_LIST_SET_ID],
+                                       genmask);
+               }
+@@ -4235,7 +4283,6 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct 
nft_set *set,
+ {
+       struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
+       struct nft_set_ext_tmpl tmpl;
+-      struct nft_data_desc desc;
+       struct nft_set_elem elem;
+       struct nft_set_ext *ext;
+       struct nft_trans *trans;
+@@ -4246,11 +4293,10 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct 
nft_set *set,
+       err = nla_parse_nested(nla, NFTA_SET_ELEM_MAX, attr,
+                              nft_set_elem_policy, NULL);
+       if (err < 0)
+-              goto err1;
++              return err;
+ 
+-      err = -EINVAL;
+       if (nla[NFTA_SET_ELEM_KEY] == NULL)
+-              goto err1;
++              return -EINVAL;
+ 
+       nft_set_ext_prepare(&tmpl);
+ 
+@@ -4260,37 +4306,31 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct 
nft_set *set,
+       if (flags != 0)
+               nft_set_ext_add(&tmpl, NFT_SET_EXT_FLAGS);
+ 
+-      err = nft_data_init(ctx, &elem.key.val, sizeof(elem.key), &desc,
+-                          nla[NFTA_SET_ELEM_KEY]);
++      err = nft_setelem_parse_key(ctx, set, &elem.key.val,
++                                  nla[NFTA_SET_ELEM_KEY]);
+       if (err < 0)
+-              goto err1;
+-
+-      err = -EINVAL;
+-      if (desc.type != NFT_DATA_VALUE || desc.len != set->klen)
+-              goto err2;
++              return err;
+ 
+-      nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, desc.len);
++      nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, set->klen);
+ 
+       err = -ENOMEM;
+       elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data, NULL, 0,
+                                     GFP_KERNEL);
+       if (elem.priv == NULL)
+-              goto err2;
++              goto fail_elem;
+ 
+       ext = nft_set_elem_ext(set, elem.priv);
+       if (flags)
+               *nft_set_ext_flags(ext) = flags;
+ 
+       trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set);
+-      if (trans == NULL) {
+-              err = -ENOMEM;
+-              goto err3;
+-      }
++      if (trans == NULL)
++              goto fail_trans;
+ 
+       priv = set->ops->deactivate(ctx->net, set, &elem);
+       if (priv == NULL) {
+               err = -ENOENT;
+-              goto err4;
++              goto fail_ops;
+       }
+       kfree(elem.priv);
+       elem.priv = priv;
+@@ -4301,13 +4341,12 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct 
nft_set *set,
+       list_add_tail(&trans->list, &ctx->net->nft.commit_list);
+       return 0;
+ 
+-err4:
++fail_ops:
+       kfree(trans);
+-err3:
++fail_trans:
+       kfree(elem.priv);
+-err2:
+-      nft_data_release(&elem.key.val, desc.type);
+-err1:
++fail_elem:
++      nft_data_release(&elem.key.val, NFT_DATA_VALUE);
+       return err;
+ }
+ 
+@@ -5609,28 +5648,24 @@ int nft_parse_u32_check(const struct nlattr *attr, int 
max, u32 *dest)
+ }
+ EXPORT_SYMBOL_GPL(nft_parse_u32_check);
+ 
+-/**
+- *    nft_parse_register - parse a register value from a netlink attribute
+- *
+- *    @attr: netlink attribute
+- *
+- *    Parse and translate a register value from a netlink attribute.
+- *    Registers used to be 128 bit wide, these register numbers will be
+- *    mapped to the corresponding 32 bit register numbers.
+- */
+-unsigned int nft_parse_register(const struct nlattr *attr)
++static int nft_parse_register(const struct nlattr *attr, u32 *preg)
+ {
+       unsigned int reg;
+ 
+       reg = ntohl(nla_get_be32(attr));
+       switch (reg) {
+       case NFT_REG_VERDICT...NFT_REG_4:
+-              return reg * NFT_REG_SIZE / NFT_REG32_SIZE;
++              *preg = reg * NFT_REG_SIZE / NFT_REG32_SIZE;
++              break;
++      case NFT_REG32_00...NFT_REG32_15:
++              *preg = reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00;
++              break;
+       default:
+-              return reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00;
++              return -ERANGE;
+       }
++
++      return 0;
+ }
+-EXPORT_SYMBOL_GPL(nft_parse_register);
+ 
+ /**
+  *    nft_dump_register - dump a register value to a netlink attribute
+@@ -5663,7 +5698,7 @@ EXPORT_SYMBOL_GPL(nft_dump_register);
+  *    Validate that the input register is one of the general purpose
+  *    registers and that the length of the load is within the bounds.
+  */
+-int nft_validate_register_load(enum nft_registers reg, unsigned int len)
++static int nft_validate_register_load(enum nft_registers reg, unsigned int 
len)
+ {
+       if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE)
+               return -EINVAL;
+@@ -5674,7 +5709,24 @@ int nft_validate_register_load(enum nft_registers reg, 
unsigned int len)
+ 
+       return 0;
+ }
+-EXPORT_SYMBOL_GPL(nft_validate_register_load);
++
++int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len)
++{
++      u32 reg;
++      int err;
++
++      err = nft_parse_register(attr, &reg);
++      if (err < 0)
++              return err;
++
++      err = nft_validate_register_load(reg, len);
++      if (err < 0)
++              return err;
++
++      *sreg = reg;
++      return 0;
++}
++EXPORT_SYMBOL_GPL(nft_parse_register_load);
+ 
+ /**
+  *    nft_validate_register_store - validate an expressions' register store
+@@ -5690,10 +5742,11 @@ EXPORT_SYMBOL_GPL(nft_validate_register_load);
+  *    A value of NULL for the data means that its runtime gathered
+  *    data.
+  */
+-int nft_validate_register_store(const struct nft_ctx *ctx,
+-                              enum nft_registers reg,
+-                              const struct nft_data *data,
+-                              enum nft_data_types type, unsigned int len)
++static int nft_validate_register_store(const struct nft_ctx *ctx,
++                                     enum nft_registers reg,
++                                     const struct nft_data *data,
++                                     enum nft_data_types type,
++                                     unsigned int len)
+ {
+       int err;
+ 
+@@ -5732,7 +5785,27 @@ int nft_validate_register_store(const struct nft_ctx 
*ctx,
+               return 0;
+       }
+ }
+-EXPORT_SYMBOL_GPL(nft_validate_register_store);
++
++int nft_parse_register_store(const struct nft_ctx *ctx,
++                           const struct nlattr *attr, u8 *dreg,
++                           const struct nft_data *data,
++                           enum nft_data_types type, unsigned int len)
++{
++      int err;
++      u32 reg;
++
++      err = nft_parse_register(attr, &reg);
++      if (err < 0)
++              return err;
++
++      err = nft_validate_register_store(ctx, reg, data, type, len);
++      if (err < 0)
++              return err;
++
++      *dreg = reg;
++      return 0;
++}
++EXPORT_SYMBOL_GPL(nft_parse_register_store);
+ 
+ static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = {
+       [NFTA_VERDICT_CODE]     = { .type = NLA_U32 },
+@@ -6032,18 +6105,25 @@ static int __init nf_tables_module_init(void)
+               goto err1;
+       }
+ 
+-      err = nf_tables_core_module_init();
++      err = register_pernet_subsys(&nf_tables_net_ops);
+       if (err < 0)
+               goto err2;
+ 
+-      err = nfnetlink_subsys_register(&nf_tables_subsys);
++      err = nf_tables_core_module_init();
+       if (err < 0)
+               goto err3;
+ 
++      /* must be last */
++      err = nfnetlink_subsys_register(&nf_tables_subsys);
++      if (err < 0)
++              goto err4;
++
+       pr_info("nf_tables: (c) 2007-2009 Patrick McHardy <ka...@trash.net>\n");
+-      return register_pernet_subsys(&nf_tables_net_ops);
+-err3:
++      return err;
++err4:
+       nf_tables_core_module_exit();
++err3:
++      unregister_pernet_subsys(&nf_tables_net_ops);
+ err2:
+       kfree(info);
+ err1:
+diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c
+index fff8073e2a569..a89152cd60ecf 100644
+--- a/net/netfilter/nft_bitwise.c
++++ b/net/netfilter/nft_bitwise.c
+@@ -18,8 +18,8 @@
+ #include <net/netfilter/nf_tables.h>
+ 
+ struct nft_bitwise {
+-      enum nft_registers      sreg:8;
+-      enum nft_registers      dreg:8;
++      u8                      sreg;
++      u8                      dreg;
+       u8                      len;
+       struct nft_data         mask;
+       struct nft_data         xor;
+@@ -68,14 +68,14 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
+ 
+       priv->len = len;
+ 
+-      priv->sreg = nft_parse_register(tb[NFTA_BITWISE_SREG]);
+-      err = nft_validate_register_load(priv->sreg, priv->len);
++      err = nft_parse_register_load(tb[NFTA_BITWISE_SREG], &priv->sreg,
++                                    priv->len);
+       if (err < 0)
+               return err;
+ 
+-      priv->dreg = nft_parse_register(tb[NFTA_BITWISE_DREG]);
+-      err = nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                        NFT_DATA_VALUE, priv->len);
++      err = nft_parse_register_store(ctx, tb[NFTA_BITWISE_DREG],
++                                     &priv->dreg, NULL, NFT_DATA_VALUE,
++                                     priv->len);
+       if (err < 0)
+               return err;
+ 
+diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
+index 13d4e421a6b33..5e1fbdd7b2846 100644
+--- a/net/netfilter/nft_byteorder.c
++++ b/net/netfilter/nft_byteorder.c
+@@ -19,8 +19,8 @@
+ #include <net/netfilter/nf_tables.h>
+ 
+ struct nft_byteorder {
+-      enum nft_registers      sreg:8;
+-      enum nft_registers      dreg:8;
++      u8                      sreg;
++      u8                      dreg;
+       enum nft_byteorder_ops  op:8;
+       u8                      len;
+       u8                      size;
+@@ -133,20 +133,20 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
+               return -EINVAL;
+       }
+ 
+-      priv->sreg = nft_parse_register(tb[NFTA_BYTEORDER_SREG]);
+       err = nft_parse_u32_check(tb[NFTA_BYTEORDER_LEN], U8_MAX, &len);
+       if (err < 0)
+               return err;
+ 
+       priv->len = len;
+ 
+-      err = nft_validate_register_load(priv->sreg, priv->len);
++      err = nft_parse_register_load(tb[NFTA_BYTEORDER_SREG], &priv->sreg,
++                                    priv->len);
+       if (err < 0)
+               return err;
+ 
+-      priv->dreg = nft_parse_register(tb[NFTA_BYTEORDER_DREG]);
+-      return nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                         NFT_DATA_VALUE, priv->len);
++      return nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG],
++                                      &priv->dreg, NULL, NFT_DATA_VALUE,
++                                      priv->len);
+ }
+ 
+ static int nft_byteorder_dump(struct sk_buff *skb, const struct nft_expr 
*expr)
+diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c
+index c2945eb3397c8..ad7b300ed911c 100644
+--- a/net/netfilter/nft_cmp.c
++++ b/net/netfilter/nft_cmp.c
+@@ -19,7 +19,7 @@
+ 
+ struct nft_cmp_expr {
+       struct nft_data         data;
+-      enum nft_registers      sreg:8;
++      u8                      sreg;
+       u8                      len;
+       enum nft_cmp_ops        op:8;
+ };
+@@ -79,8 +79,7 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const 
struct nft_expr *expr,
+                           tb[NFTA_CMP_DATA]);
+       BUG_ON(err < 0);
+ 
+-      priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]);
+-      err = nft_validate_register_load(priv->sreg, desc.len);
++      err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len);
+       if (err < 0)
+               return err;
+ 
+@@ -129,8 +128,7 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx,
+                           tb[NFTA_CMP_DATA]);
+       BUG_ON(err < 0);
+ 
+-      priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]);
+-      err = nft_validate_register_load(priv->sreg, desc.len);
++      err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len);
+       if (err < 0)
+               return err;
+ 
+diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
+index 5e0d367a09882..2af2a10382711 100644
+--- a/net/netfilter/nft_ct.c
++++ b/net/netfilter/nft_ct.c
+@@ -27,8 +27,8 @@ struct nft_ct {
+       enum nft_ct_keys        key:8;
+       enum ip_conntrack_dir   dir:8;
+       union {
+-              enum nft_registers      dreg:8;
+-              enum nft_registers      sreg:8;
++              u8              dreg;
++              u8              sreg;
+       };
+ };
+ 
+@@ -483,9 +483,8 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
+               }
+       }
+ 
+-      priv->dreg = nft_parse_register(tb[NFTA_CT_DREG]);
+-      err = nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                        NFT_DATA_VALUE, len);
++      err = nft_parse_register_store(ctx, tb[NFTA_CT_DREG], &priv->dreg, NULL,
++                                     NFT_DATA_VALUE, len);
+       if (err < 0)
+               return err;
+ 
+@@ -578,8 +577,7 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
+               }
+       }
+ 
+-      priv->sreg = nft_parse_register(tb[NFTA_CT_SREG]);
+-      err = nft_validate_register_load(priv->sreg, len);
++      err = nft_parse_register_load(tb[NFTA_CT_SREG], &priv->sreg, len);
+       if (err < 0)
+               goto err1;
+ 
+diff --git a/net/netfilter/nft_dup_netdev.c b/net/netfilter/nft_dup_netdev.c
+index 2cc1e0ef56e88..e862f916efa09 100644
+--- a/net/netfilter/nft_dup_netdev.c
++++ b/net/netfilter/nft_dup_netdev.c
+@@ -16,7 +16,7 @@
+ #include <net/netfilter/nf_dup_netdev.h>
+ 
+ struct nft_dup_netdev {
+-      enum nft_registers      sreg_dev:8;
++      u8      sreg_dev;
+ };
+ 
+ static void nft_dup_netdev_eval(const struct nft_expr *expr,
+@@ -42,8 +42,8 @@ static int nft_dup_netdev_init(const struct nft_ctx *ctx,
+       if (tb[NFTA_DUP_SREG_DEV] == NULL)
+               return -EINVAL;
+ 
+-      priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]);
+-      return nft_validate_register_load(priv->sreg_dev, sizeof(int));
++      return nft_parse_register_load(tb[NFTA_DUP_SREG_DEV], &priv->sreg_dev,
++                                     sizeof(int));
+ }
+ 
+ static const struct nft_expr_ops nft_dup_netdev_ingress_ops;
+diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c
+index 74e8fdaa34321..d1dc5c8937a56 100644
+--- a/net/netfilter/nft_dynset.c
++++ b/net/netfilter/nft_dynset.c
+@@ -20,8 +20,8 @@ struct nft_dynset {
+       struct nft_set                  *set;
+       struct nft_set_ext_tmpl         tmpl;
+       enum nft_dynset_ops             op:8;
+-      enum nft_registers              sreg_key:8;
+-      enum nft_registers              sreg_data:8;
++      u8                              sreg_key;
++      u8                              sreg_data;
+       bool                            invert;
+       u64                             timeout;
+       struct nft_expr                 *expr;
+@@ -163,8 +163,8 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
+                                               tb[NFTA_DYNSET_TIMEOUT])));
+       }
+ 
+-      priv->sreg_key = nft_parse_register(tb[NFTA_DYNSET_SREG_KEY]);
+-      err = nft_validate_register_load(priv->sreg_key, set->klen);;
++      err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_KEY], &priv->sreg_key,
++                                    set->klen);
+       if (err < 0)
+               return err;
+ 
+@@ -174,8 +174,8 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
+               if (set->dtype == NFT_DATA_VERDICT)
+                       return -EOPNOTSUPP;
+ 
+-              priv->sreg_data = nft_parse_register(tb[NFTA_DYNSET_SREG_DATA]);
+-              err = nft_validate_register_load(priv->sreg_data, set->dlen);
++              err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_DATA],
++                                            &priv->sreg_data, set->dlen);
+               if (err < 0)
+                       return err;
+       } else if (set->flags & NFT_SET_MAP)
+@@ -190,9 +190,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
+               priv->expr = nft_expr_init(ctx, tb[NFTA_DYNSET_EXPR]);
+               if (IS_ERR(priv->expr))
+                       return PTR_ERR(priv->expr);
+-
+-      } else if (set->flags & NFT_SET_EVAL)
+-              return -EINVAL;
++      }
+ 
+       nft_set_ext_prepare(&priv->tmpl);
+       nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_KEY, set->klen);
+diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c
+index e73a1503e8d7c..9f1e801ae34f9 100644
+--- a/net/netfilter/nft_exthdr.c
++++ b/net/netfilter/nft_exthdr.c
+@@ -23,8 +23,8 @@ struct nft_exthdr {
+       u8                      offset;
+       u8                      len;
+       u8                      op;
+-      enum nft_registers      dreg:8;
+-      enum nft_registers      sreg:8;
++      u8                      dreg;
++      u8                      sreg;
+       u8                      flags;
+ };
+ 
+@@ -257,12 +257,12 @@ static int nft_exthdr_init(const struct nft_ctx *ctx,
+       priv->type   = nla_get_u8(tb[NFTA_EXTHDR_TYPE]);
+       priv->offset = offset;
+       priv->len    = len;
+-      priv->dreg   = nft_parse_register(tb[NFTA_EXTHDR_DREG]);
+       priv->flags  = flags;
+       priv->op     = op;
+ 
+-      return nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                         NFT_DATA_VALUE, priv->len);
++      return nft_parse_register_store(ctx, tb[NFTA_EXTHDR_DREG],
++                                      &priv->dreg, NULL, NFT_DATA_VALUE,
++                                      priv->len);
+ }
+ 
+ static int nft_exthdr_tcp_set_init(const struct nft_ctx *ctx,
+@@ -307,11 +307,11 @@ static int nft_exthdr_tcp_set_init(const struct nft_ctx 
*ctx,
+       priv->type   = nla_get_u8(tb[NFTA_EXTHDR_TYPE]);
+       priv->offset = offset;
+       priv->len    = len;
+-      priv->sreg   = nft_parse_register(tb[NFTA_EXTHDR_SREG]);
+       priv->flags  = flags;
+       priv->op     = op;
+ 
+-      return nft_validate_register_load(priv->sreg, priv->len);
++      return nft_parse_register_load(tb[NFTA_EXTHDR_SREG], &priv->sreg,
++                                     priv->len);
+ }
+ 
+ static int nft_exthdr_dump_common(struct sk_buff *skb, const struct 
nft_exthdr *priv)
+diff --git a/net/netfilter/nft_fib.c b/net/netfilter/nft_fib.c
+index 21df8cccea658..ce6891337304d 100644
+--- a/net/netfilter/nft_fib.c
++++ b/net/netfilter/nft_fib.c
+@@ -88,7 +88,6 @@ int nft_fib_init(const struct nft_ctx *ctx, const struct 
nft_expr *expr,
+               return -EINVAL;
+ 
+       priv->result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT]));
+-      priv->dreg = nft_parse_register(tb[NFTA_FIB_DREG]);
+ 
+       switch (priv->result) {
+       case NFT_FIB_RESULT_OIF:
+@@ -108,8 +107,8 @@ int nft_fib_init(const struct nft_ctx *ctx, const struct 
nft_expr *expr,
+               return -EINVAL;
+       }
+ 
+-      err = nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                        NFT_DATA_VALUE, len);
++      err = nft_parse_register_store(ctx, tb[NFTA_FIB_DREG], &priv->dreg,
++                                     NULL, NFT_DATA_VALUE, len);
+       if (err < 0)
+               return err;
+ 
+diff --git a/net/netfilter/nft_fwd_netdev.c b/net/netfilter/nft_fwd_netdev.c
+index ee190fa4dc347..c717e3a442472 100644
+--- a/net/netfilter/nft_fwd_netdev.c
++++ b/net/netfilter/nft_fwd_netdev.c
+@@ -16,7 +16,7 @@
+ #include <net/netfilter/nf_dup_netdev.h>
+ 
+ struct nft_fwd_netdev {
+-      enum nft_registers      sreg_dev:8;
++      u8      sreg_dev;
+ };
+ 
+ static void nft_fwd_netdev_eval(const struct nft_expr *expr,
+@@ -43,8 +43,8 @@ static int nft_fwd_netdev_init(const struct nft_ctx *ctx,
+       if (tb[NFTA_FWD_SREG_DEV] == NULL)
+               return -EINVAL;
+ 
+-      priv->sreg_dev = nft_parse_register(tb[NFTA_FWD_SREG_DEV]);
+-      return nft_validate_register_load(priv->sreg_dev, sizeof(int));
++      return nft_parse_register_load(tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev,
++                                     sizeof(int));
+ }
+ 
+ static const struct nft_expr_ops nft_fwd_netdev_ingress_ops;
+diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c
+index 010a565b40001..5d067ca294465 100644
+--- a/net/netfilter/nft_hash.c
++++ b/net/netfilter/nft_hash.c
+@@ -18,8 +18,8 @@
+ #include <linux/jhash.h>
+ 
+ struct nft_jhash {
+-      enum nft_registers      sreg:8;
+-      enum nft_registers      dreg:8;
++      u8                      sreg;
++      u8                      dreg;
+       u8                      len;
+       bool                    autogen_seed:1;
+       u32                     modulus;
+@@ -40,7 +40,7 @@ static void nft_jhash_eval(const struct nft_expr *expr,
+ }
+ 
+ struct nft_symhash {
+-      enum nft_registers      dreg:8;
++      u8                      dreg;
+       u32                     modulus;
+       u32                     offset;
+ };
+@@ -85,9 +85,6 @@ static int nft_jhash_init(const struct nft_ctx *ctx,
+       if (tb[NFTA_HASH_OFFSET])
+               priv->offset = ntohl(nla_get_be32(tb[NFTA_HASH_OFFSET]));
+ 
+-      priv->sreg = nft_parse_register(tb[NFTA_HASH_SREG]);
+-      priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]);
+-
+       err = nft_parse_u32_check(tb[NFTA_HASH_LEN], U8_MAX, &len);
+       if (err < 0)
+               return err;
+@@ -96,6 +93,10 @@ static int nft_jhash_init(const struct nft_ctx *ctx,
+ 
+       priv->len = len;
+ 
++      err = nft_parse_register_load(tb[NFTA_HASH_SREG], &priv->sreg, len);
++      if (err < 0)
++              return err;
++
+       priv->modulus = ntohl(nla_get_be32(tb[NFTA_HASH_MODULUS]));
+       if (priv->modulus <= 1)
+               return -ERANGE;
+@@ -110,9 +111,8 @@ static int nft_jhash_init(const struct nft_ctx *ctx,
+               get_random_bytes(&priv->seed, sizeof(priv->seed));
+       }
+ 
+-      return nft_validate_register_load(priv->sreg, len) &&
+-             nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                         NFT_DATA_VALUE, sizeof(u32));
++      return nft_parse_register_store(ctx, tb[NFTA_HASH_DREG], &priv->dreg,
++                                      NULL, NFT_DATA_VALUE, sizeof(u32));
+ }
+ 
+ static int nft_symhash_init(const struct nft_ctx *ctx,
+@@ -128,8 +128,6 @@ static int nft_symhash_init(const struct nft_ctx *ctx,
+       if (tb[NFTA_HASH_OFFSET])
+               priv->offset = ntohl(nla_get_be32(tb[NFTA_HASH_OFFSET]));
+ 
+-      priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]);
+-
+       priv->modulus = ntohl(nla_get_be32(tb[NFTA_HASH_MODULUS]));
+       if (priv->modulus < 1)
+               return -ERANGE;
+@@ -137,8 +135,9 @@ static int nft_symhash_init(const struct nft_ctx *ctx,
+       if (priv->offset + priv->modulus - 1 < priv->offset)
+               return -EOVERFLOW;
+ 
+-      return nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                         NFT_DATA_VALUE, sizeof(u32));
++      return nft_parse_register_store(ctx, tb[NFTA_HASH_DREG],
++                                      &priv->dreg, NULL, NFT_DATA_VALUE,
++                                      sizeof(u32));
+ }
+ 
+ static int nft_jhash_dump(struct sk_buff *skb,
+diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c
+index 86fd35018b4a6..99f528e5f1542 100644
+--- a/net/netfilter/nft_immediate.c
++++ b/net/netfilter/nft_immediate.c
+@@ -19,7 +19,7 @@
+ 
+ struct nft_immediate_expr {
+       struct nft_data         data;
+-      enum nft_registers      dreg:8;
++      u8                      dreg;
+       u8                      dlen;
+ };
+ 
+@@ -56,9 +56,9 @@ static int nft_immediate_init(const struct nft_ctx *ctx,
+ 
+       priv->dlen = desc.len;
+ 
+-      priv->dreg = nft_parse_register(tb[NFTA_IMMEDIATE_DREG]);
+-      err = nft_validate_register_store(ctx, priv->dreg, &priv->data,
+-                                        desc.type, desc.len);
++      err = nft_parse_register_store(ctx, tb[NFTA_IMMEDIATE_DREG],
++                                     &priv->dreg, &priv->data, desc.type,
++                                     desc.len);
+       if (err < 0)
+               goto err1;
+ 
+diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c
+index 4fcbe51e88c76..7577a486635ae 100644
+--- a/net/netfilter/nft_lookup.c
++++ b/net/netfilter/nft_lookup.c
+@@ -20,8 +20,8 @@
+ 
+ struct nft_lookup {
+       struct nft_set                  *set;
+-      enum nft_registers              sreg:8;
+-      enum nft_registers              dreg:8;
++      u8                              sreg;
++      u8                              dreg;
+       bool                            invert;
+       struct nft_set_binding          binding;
+ };
+@@ -76,8 +76,8 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
+       if (IS_ERR(set))
+               return PTR_ERR(set);
+ 
+-      priv->sreg = nft_parse_register(tb[NFTA_LOOKUP_SREG]);
+-      err = nft_validate_register_load(priv->sreg, set->klen);
++      err = nft_parse_register_load(tb[NFTA_LOOKUP_SREG], &priv->sreg,
++                                    set->klen);
+       if (err < 0)
+               return err;
+ 
+@@ -100,9 +100,9 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
+               if (!(set->flags & NFT_SET_MAP))
+                       return -EINVAL;
+ 
+-              priv->dreg = nft_parse_register(tb[NFTA_LOOKUP_DREG]);
+-              err = nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                                set->dtype, set->dlen);
++              err = nft_parse_register_store(ctx, tb[NFTA_LOOKUP_DREG],
++                                             &priv->dreg, NULL, set->dtype,
++                                             set->dlen);
+               if (err < 0)
+                       return err;
+       } else if (set->flags & NFT_SET_MAP)
+diff --git a/net/netfilter/nft_masq.c b/net/netfilter/nft_masq.c
+index 6ac03d4266c90..712a187983e6e 100644
+--- a/net/netfilter/nft_masq.c
++++ b/net/netfilter/nft_masq.c
+@@ -53,19 +53,15 @@ int nft_masq_init(const struct nft_ctx *ctx,
+       }
+ 
+       if (tb[NFTA_MASQ_REG_PROTO_MIN]) {
+-              priv->sreg_proto_min =
+-                      nft_parse_register(tb[NFTA_MASQ_REG_PROTO_MIN]);
+-
+-              err = nft_validate_register_load(priv->sreg_proto_min, plen);
++              err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MIN],
++                                            &priv->sreg_proto_min, plen);
+               if (err < 0)
+                       return err;
+ 
+               if (tb[NFTA_MASQ_REG_PROTO_MAX]) {
+-                      priv->sreg_proto_max =
+-                              nft_parse_register(tb[NFTA_MASQ_REG_PROTO_MAX]);
+-
+-                      err = nft_validate_register_load(priv->sreg_proto_max,
+-                                                       plen);
++                      err = 
nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MAX],
++                                                    &priv->sreg_proto_max,
++                                                    plen);
+                       if (err < 0)
+                               return err;
+               } else {
+diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
+index c71184d4eac1b..c9bf2b17b7bdd 100644
+--- a/net/netfilter/nft_meta.c
++++ b/net/netfilter/nft_meta.c
+@@ -314,9 +314,8 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
+               return -EOPNOTSUPP;
+       }
+ 
+-      priv->dreg = nft_parse_register(tb[NFTA_META_DREG]);
+-      return nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                         NFT_DATA_VALUE, len);
++      return nft_parse_register_store(ctx, tb[NFTA_META_DREG], &priv->dreg,
++                                      NULL, NFT_DATA_VALUE, len);
+ }
+ EXPORT_SYMBOL_GPL(nft_meta_get_init);
+ 
+@@ -374,8 +373,7 @@ int nft_meta_set_init(const struct nft_ctx *ctx,
+               return -EOPNOTSUPP;
+       }
+ 
+-      priv->sreg = nft_parse_register(tb[NFTA_META_SREG]);
+-      err = nft_validate_register_load(priv->sreg, len);
++      err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len);
+       if (err < 0)
+               return err;
+ 
+diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c
+index 04dd813ed7755..c3f6c41823ec0 100644
+--- a/net/netfilter/nft_nat.c
++++ b/net/netfilter/nft_nat.c
+@@ -27,10 +27,10 @@
+ #include <net/ip.h>
+ 
+ struct nft_nat {
+-      enum nft_registers      sreg_addr_min:8;
+-      enum nft_registers      sreg_addr_max:8;
+-      enum nft_registers      sreg_proto_min:8;
+-      enum nft_registers      sreg_proto_max:8;
++      u8                      sreg_addr_min;
++      u8                      sreg_addr_max;
++      u8                      sreg_proto_min;
++      u8                      sreg_proto_max;
+       enum nf_nat_manip_type  type:8;
+       u8                      family;
+       u16                     flags;
+@@ -160,18 +160,15 @@ static int nft_nat_init(const struct nft_ctx *ctx, const 
struct nft_expr *expr,
+       priv->family = family;
+ 
+       if (tb[NFTA_NAT_REG_ADDR_MIN]) {
+-              priv->sreg_addr_min =
+-                      nft_parse_register(tb[NFTA_NAT_REG_ADDR_MIN]);
+-              err = nft_validate_register_load(priv->sreg_addr_min, alen);
++              err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MIN],
++                                            &priv->sreg_addr_min, alen);
+               if (err < 0)
+                       return err;
+ 
+               if (tb[NFTA_NAT_REG_ADDR_MAX]) {
+-                      priv->sreg_addr_max =
+-                              nft_parse_register(tb[NFTA_NAT_REG_ADDR_MAX]);
+-
+-                      err = nft_validate_register_load(priv->sreg_addr_max,
+-                                                       alen);
++                      err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MAX],
++                                                    &priv->sreg_addr_max,
++                                                    alen);
+                       if (err < 0)
+                               return err;
+               } else {
+@@ -181,19 +178,15 @@ static int nft_nat_init(const struct nft_ctx *ctx, const 
struct nft_expr *expr,
+ 
+       plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);
+       if (tb[NFTA_NAT_REG_PROTO_MIN]) {
+-              priv->sreg_proto_min =
+-                      nft_parse_register(tb[NFTA_NAT_REG_PROTO_MIN]);
+-
+-              err = nft_validate_register_load(priv->sreg_proto_min, plen);
++              err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MIN],
++                                            &priv->sreg_proto_min, plen);
+               if (err < 0)
+                       return err;
+ 
+               if (tb[NFTA_NAT_REG_PROTO_MAX]) {
+-                      priv->sreg_proto_max =
+-                              nft_parse_register(tb[NFTA_NAT_REG_PROTO_MAX]);
+-
+-                      err = nft_validate_register_load(priv->sreg_proto_max,
+-                                                       plen);
++                      err = 
nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MAX],
++                                                    &priv->sreg_proto_max,
++                                                    plen);
+                       if (err < 0)
+                               return err;
+               } else {
+diff --git a/net/netfilter/nft_numgen.c b/net/netfilter/nft_numgen.c
+index 5a3a52c71545a..befc715cb06fb 100644
+--- a/net/netfilter/nft_numgen.c
++++ b/net/netfilter/nft_numgen.c
+@@ -20,7 +20,7 @@
+ static DEFINE_PER_CPU(struct rnd_state, nft_numgen_prandom_state);
+ 
+ struct nft_ng_inc {
+-      enum nft_registers      dreg:8;
++      u8                      dreg;
+       u32                     modulus;
+       atomic_t                counter;
+       u32                     offset;
+@@ -64,11 +64,10 @@ static int nft_ng_inc_init(const struct nft_ctx *ctx,
+       if (priv->offset + priv->modulus - 1 < priv->offset)
+               return -EOVERFLOW;
+ 
+-      priv->dreg = nft_parse_register(tb[NFTA_NG_DREG]);
+       atomic_set(&priv->counter, priv->modulus - 1);
+ 
+-      return nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                         NFT_DATA_VALUE, sizeof(u32));
++      return nft_parse_register_store(ctx, tb[NFTA_NG_DREG], &priv->dreg,
++                                      NULL, NFT_DATA_VALUE, sizeof(u32));
+ }
+ 
+ static int nft_ng_dump(struct sk_buff *skb, enum nft_registers dreg,
+@@ -98,7 +97,7 @@ static int nft_ng_inc_dump(struct sk_buff *skb, const struct 
nft_expr *expr)
+ }
+ 
+ struct nft_ng_random {
+-      enum nft_registers      dreg:8;
++      u8                      dreg;
+       u32                     modulus;
+       u32                     offset;
+ };
+@@ -133,10 +132,8 @@ static int nft_ng_random_init(const struct nft_ctx *ctx,
+ 
+       prandom_init_once(&nft_numgen_prandom_state);
+ 
+-      priv->dreg = nft_parse_register(tb[NFTA_NG_DREG]);
+-
+-      return nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                         NFT_DATA_VALUE, sizeof(u32));
++      return nft_parse_register_store(ctx, tb[NFTA_NG_DREG], &priv->dreg,
++                                      NULL, NFT_DATA_VALUE, sizeof(u32));
+ }
+ 
+ static int nft_ng_random_dump(struct sk_buff *skb, const struct nft_expr 
*expr)
+diff --git a/net/netfilter/nft_objref.c b/net/netfilter/nft_objref.c
+index 49a067a67e723..8ad0be6c53fd3 100644
+--- a/net/netfilter/nft_objref.c
++++ b/net/netfilter/nft_objref.c
+@@ -64,27 +64,40 @@ nla_put_failure:
+       return -1;
+ }
+ 
+-static void nft_objref_destroy(const struct nft_ctx *ctx,
+-                             const struct nft_expr *expr)
++static void nft_objref_deactivate(const struct nft_ctx *ctx,
++                                const struct nft_expr *expr,
++                                enum nft_trans_phase phase)
+ {
+       struct nft_object *obj = nft_objref_priv(expr);
+ 
++      if (phase == NFT_TRANS_COMMIT)
++              return;
++
+       obj->use--;
+ }
+ 
++static void nft_objref_activate(const struct nft_ctx *ctx,
++                              const struct nft_expr *expr)
++{
++      struct nft_object *obj = nft_objref_priv(expr);
++
++      obj->use++;
++}
++
+ static struct nft_expr_type nft_objref_type;
+ static const struct nft_expr_ops nft_objref_ops = {
+       .type           = &nft_objref_type,
+       .size           = NFT_EXPR_SIZE(sizeof(struct nft_object *)),
+       .eval           = nft_objref_eval,
+       .init           = nft_objref_init,
+-      .destroy        = nft_objref_destroy,
++      .activate       = nft_objref_activate,
++      .deactivate     = nft_objref_deactivate,
+       .dump           = nft_objref_dump,
+ };
+ 
+ struct nft_objref_map {
+       struct nft_set          *set;
+-      enum nft_registers      sreg:8;
++      u8                      sreg;
+       struct nft_set_binding  binding;
+ };
+ 
+@@ -125,8 +138,8 @@ static int nft_objref_map_init(const struct nft_ctx *ctx,
+       if (!(set->flags & NFT_SET_OBJECT))
+               return -EINVAL;
+ 
+-      priv->sreg = nft_parse_register(tb[NFTA_OBJREF_SET_SREG]);
+-      err = nft_validate_register_load(priv->sreg, set->klen);
++      err = nft_parse_register_load(tb[NFTA_OBJREF_SET_SREG], &priv->sreg,
++                                    set->klen);
+       if (err < 0)
+               return err;
+ 
+diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
+index 5732b32ab9320..77cfd5182784f 100644
+--- a/net/netfilter/nft_payload.c
++++ b/net/netfilter/nft_payload.c
+@@ -135,10 +135,10 @@ static int nft_payload_init(const struct nft_ctx *ctx,
+       priv->base   = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
+       priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
+       priv->len    = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
+-      priv->dreg   = nft_parse_register(tb[NFTA_PAYLOAD_DREG]);
+ 
+-      return nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                         NFT_DATA_VALUE, priv->len);
++      return nft_parse_register_store(ctx, tb[NFTA_PAYLOAD_DREG],
++                                      &priv->dreg, NULL, NFT_DATA_VALUE,
++                                      priv->len);
+ }
+ 
+ static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr)
+@@ -338,7 +338,6 @@ static int nft_payload_set_init(const struct nft_ctx *ctx,
+       priv->base        = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
+       priv->offset      = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
+       priv->len         = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
+-      priv->sreg        = nft_parse_register(tb[NFTA_PAYLOAD_SREG]);
+ 
+       if (tb[NFTA_PAYLOAD_CSUM_TYPE])
+               csum_type = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_TYPE]));
+@@ -369,7 +368,8 @@ static int nft_payload_set_init(const struct nft_ctx *ctx,
+       }
+       priv->csum_type = csum_type;
+ 
+-      return nft_validate_register_load(priv->sreg, priv->len);
++      return nft_parse_register_load(tb[NFTA_PAYLOAD_SREG], &priv->sreg,
++                                     priv->len);
+ }
+ 
+ static int nft_payload_set_dump(struct sk_buff *skb, const struct nft_expr 
*expr)
+diff --git a/net/netfilter/nft_queue.c b/net/netfilter/nft_queue.c
+index 98613658d4ac5..de5f1bda9d6f1 100644
+--- a/net/netfilter/nft_queue.c
++++ b/net/netfilter/nft_queue.c
+@@ -22,10 +22,10 @@
+ static u32 jhash_initval __read_mostly;
+ 
+ struct nft_queue {
+-      enum nft_registers      sreg_qnum:8;
+-      u16                     queuenum;
+-      u16                     queues_total;
+-      u16                     flags;
++      u8      sreg_qnum;
++      u16     queuenum;
++      u16     queues_total;
++      u16     flags;
+ };
+ 
+ static void nft_queue_eval(const struct nft_expr *expr,
+@@ -114,8 +114,8 @@ static int nft_queue_sreg_init(const struct nft_ctx *ctx,
+       struct nft_queue *priv = nft_expr_priv(expr);
+       int err;
+ 
+-      priv->sreg_qnum = nft_parse_register(tb[NFTA_QUEUE_SREG_QNUM]);
+-      err = nft_validate_register_load(priv->sreg_qnum, sizeof(u32));
++      err = nft_parse_register_load(tb[NFTA_QUEUE_SREG_QNUM],
++                                    &priv->sreg_qnum, sizeof(u32));
+       if (err < 0)
+               return err;
+ 
+diff --git a/net/netfilter/nft_range.c b/net/netfilter/nft_range.c
+index cedb96c3619fa..658d68522013e 100644
+--- a/net/netfilter/nft_range.c
++++ b/net/netfilter/nft_range.c
+@@ -18,7 +18,7 @@
+ struct nft_range_expr {
+       struct nft_data         data_from;
+       struct nft_data         data_to;
+-      enum nft_registers      sreg:8;
++      u8                      sreg;
+       u8                      len;
+       enum nft_range_ops      op:8;
+ };
+@@ -80,8 +80,8 @@ static int nft_range_init(const struct nft_ctx *ctx, const 
struct nft_expr *expr
+               goto err2;
+       }
+ 
+-      priv->sreg = nft_parse_register(tb[NFTA_RANGE_SREG]);
+-      err = nft_validate_register_load(priv->sreg, desc_from.len);
++      err = nft_parse_register_load(tb[NFTA_RANGE_SREG], &priv->sreg,
++                                    desc_from.len);
+       if (err < 0)
+               goto err2;
+ 
+diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c
+index 1e66538bf0ff2..723e07a5640c2 100644
+--- a/net/netfilter/nft_redir.c
++++ b/net/netfilter/nft_redir.c
+@@ -49,19 +49,15 @@ int nft_redir_init(const struct nft_ctx *ctx,
+ 
+       plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);
+       if (tb[NFTA_REDIR_REG_PROTO_MIN]) {
+-              priv->sreg_proto_min =
+-                      nft_parse_register(tb[NFTA_REDIR_REG_PROTO_MIN]);
+-
+-              err = nft_validate_register_load(priv->sreg_proto_min, plen);
++              err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MIN],
++                                            &priv->sreg_proto_min, plen);
+               if (err < 0)
+                       return err;
+ 
+               if (tb[NFTA_REDIR_REG_PROTO_MAX]) {
+-                      priv->sreg_proto_max =
+-                              
nft_parse_register(tb[NFTA_REDIR_REG_PROTO_MAX]);
+-
+-                      err = nft_validate_register_load(priv->sreg_proto_max,
+-                                                       plen);
++                      err = 
nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MAX],
++                                                    &priv->sreg_proto_max,
++                                                    plen);
+                       if (err < 0)
+                               return err;
+               } else {
+diff --git a/net/netfilter/nft_rt.c b/net/netfilter/nft_rt.c
+index a6b7d05aeacf4..60d3f86a1fd91 100644
+--- a/net/netfilter/nft_rt.c
++++ b/net/netfilter/nft_rt.c
+@@ -20,7 +20,7 @@
+ 
+ struct nft_rt {
+       enum nft_rt_keys        key:8;
+-      enum nft_registers      dreg:8;
++      u8                      dreg;
+ };
+ 
+ static u16 get_tcpmss(const struct nft_pktinfo *pkt, const struct dst_entry 
*skbdst)
+@@ -141,9 +141,8 @@ static int nft_rt_get_init(const struct nft_ctx *ctx,
+               return -EOPNOTSUPP;
+       }
+ 
+-      priv->dreg = nft_parse_register(tb[NFTA_RT_DREG]);
+-      return nft_validate_register_store(ctx, priv->dreg, NULL,
+-                                         NFT_DATA_VALUE, len);
++      return nft_parse_register_store(ctx, tb[NFTA_RT_DREG], &priv->dreg,
++                                      NULL, NFT_DATA_VALUE, len);
+ }
+ 
+ static int nft_rt_get_dump(struct sk_buff *skb,
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index d7b0a7aa29a83..4b40edb51b9e5 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1977,7 +1977,7 @@ static int netlink_recvmsg(struct socket *sock, struct 
msghdr *msg, size_t len,
+ 
+       skb_free_datagram(sk, skb);
+ 
+-      if (nlk->cb_running &&
++      if (READ_ONCE(nlk->cb_running) &&
+           atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) {
+               ret = netlink_dump(sk);
+               if (ret) {
+@@ -2259,7 +2259,7 @@ static int netlink_dump(struct sock *sk)
+       if (cb->done)
+               cb->done(cb);
+ 
+-      nlk->cb_running = false;
++      WRITE_ONCE(nlk->cb_running, false);
+       module = cb->module;
+       skb = cb->skb;
+       mutex_unlock(nlk->cb_mutex);
+@@ -2320,7 +2320,7 @@ int __netlink_dump_start(struct sock *ssk, struct 
sk_buff *skb,
+                       goto error_put;
+       }
+ 
+-      nlk->cb_running = true;
++      WRITE_ONCE(nlk->cb_running, true);
+       nlk->dump_done_errno = INT_MAX;
+ 
+       mutex_unlock(nlk->cb_mutex);
+@@ -2633,7 +2633,7 @@ static int netlink_seq_show(struct seq_file *seq, void 
*v)
+                          nlk->groups ? (u32)nlk->groups[0] : 0,
+                          sk_rmem_alloc_get(s),
+                          sk_wmem_alloc_get(s),
+-                         nlk->cb_running,
++                         READ_ONCE(nlk->cb_running),
+                          refcount_read(&s->sk_refcnt),
+                          atomic_read(&s->sk_drops),
+                          sock_i_ino(s)
+diff --git a/net/nsh/nsh.c b/net/nsh/nsh.c
+index 5647905c88d66..f8eeef85ffa6e 100644
+--- a/net/nsh/nsh.c
++++ b/net/nsh/nsh.c
+@@ -18,13 +18,12 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
+                                      netdev_features_t features)
+ {
+       struct sk_buff *segs = ERR_PTR(-EINVAL);
++      u16 mac_offset = skb->mac_header;
+       unsigned int nsh_len, mac_len;
+       __be16 proto;
+-      int nhoff;
+ 
+       skb_reset_network_header(skb);
+ 
+-      nhoff = skb->network_header - skb->mac_header;
+       mac_len = skb->mac_len;
+ 
+       if (unlikely(!pskb_may_pull(skb, NSH_BASE_HDR_LEN)))
+@@ -49,15 +48,14 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
+       segs = skb_mac_gso_segment(skb, features);
+       if (IS_ERR_OR_NULL(segs)) {
+               skb_gso_error_unwind(skb, htons(ETH_P_NSH), nsh_len,
+-                                   skb->network_header - nhoff,
+-                                   mac_len);
++                                   mac_offset, mac_len);
+               goto out;
+       }
+ 
+       for (skb = segs; skb; skb = skb->next) {
+               skb->protocol = htons(ETH_P_NSH);
+               __skb_push(skb, nsh_len);
+-              skb_set_mac_header(skb, -nhoff);
++              skb->mac_header = mac_offset;
+               skb->network_header = skb->mac_header + mac_len;
+               skb->mac_len = mac_len;
+       }
+diff --git a/net/socket.c b/net/socket.c
+index 7bcd7053e61f2..e59b114e16ba7 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -2383,7 +2383,7 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, 
unsigned int vlen,
+                * error to return on the next call or if the
+                * app asks about it using getsockopt(SO_ERROR).
+                */
+-              sock->sk->sk_err = -err;
++              WRITE_ONCE(sock->sk->sk_err, -err);
+       }
+ out_put:
+       fput_light(sock->file, fput_needed);
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index 0e494902fadaa..375d4e20efd6b 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -1236,7 +1236,7 @@ static long unix_wait_for_peer(struct sock *other, long 
timeo)
+ 
+       sched = !sock_flag(other, SOCK_DEAD) &&
+               !(other->sk_shutdown & RCV_SHUTDOWN) &&
+-              unix_recvq_full(other);
++              unix_recvq_full_lockless(other);
+ 
+       unix_state_unlock(other);
+ 
+diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
+index 2ec4359d7321d..356f5525a0028 100644
+--- a/net/vmw_vsock/af_vsock.c
++++ b/net/vmw_vsock/af_vsock.c
+@@ -1247,7 +1247,7 @@ static int vsock_stream_connect(struct socket *sock, 
struct sockaddr *addr,
+                       vsock_transport_cancel_pkt(vsk);
+                       vsock_remove_connected(vsk);
+                       goto out_wait;
+-              } else if (timeout == 0) {
++              } else if ((sk->sk_state != TCP_ESTABLISHED) && (timeout == 0)) 
{
+                       err = -ETIMEDOUT;
+                       sk->sk_state = TCP_CLOSE;
+                       sock->state = SS_UNCONNECTED;
+diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
+index 9012e33ae22f8..731600de03893 100644
+--- a/scripts/recordmcount.c
++++ b/scripts/recordmcount.c
+@@ -146,6 +146,7 @@ uwrite(int const fd, void const *const buf, size_t const 
count)
+ {
+       size_t cnt = count;
+       off_t idx = 0;
++      void *p = NULL;
+ 
+       file_updated = 1;
+ 
+@@ -153,7 +154,10 @@ uwrite(int const fd, void const *const buf, size_t const 
count)
+               off_t aoffset = (file_ptr + count) - file_end;
+ 
+               if (aoffset > file_append_size) {
+-                      file_append = realloc(file_append, aoffset);
++                      p = realloc(file_append, aoffset);
++                      if (!p)
++                              free(file_append);
++                      file_append = p;
+                       file_append_size = aoffset;
+               }
+               if (!file_append) {
+diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
+index cf406f22f406f..383c3d7fa5d70 100644
+--- a/sound/pci/hda/hda_generic.c
++++ b/sound/pci/hda/hda_generic.c
+@@ -1157,8 +1157,8 @@ static bool path_has_mixer(struct hda_codec *codec, int 
path_idx, int ctl_type)
+       return path && path->ctls[ctl_type];
+ }
+ 
+-static const char * const channel_name[4] = {
+-      "Front", "Surround", "CLFE", "Side"
++static const char * const channel_name[] = {
++      "Front", "Surround", "CLFE", "Side", "Back",
+ };
+ 
+ /* give some appropriate ctl name prefix for the given line out channel */
+@@ -1184,7 +1184,7 @@ static const char *get_line_out_pfx(struct hda_codec 
*codec, int ch,
+ 
+       /* multi-io channels */
+       if (ch >= cfg->line_outs)
+-              return channel_name[ch];
++              goto fixed_name;
+ 
+       switch (cfg->line_out_type) {
+       case AUTO_PIN_SPEAKER_OUT:
+@@ -1236,6 +1236,7 @@ static const char *get_line_out_pfx(struct hda_codec 
*codec, int ch,
+       if (cfg->line_outs == 1 && !spec->multi_ios)
+               return "Line Out";
+ 
++ fixed_name:
+       if (ch >= ARRAY_SIZE(channel_name)) {
+               snd_BUG();
+               return "PCM";
+diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
+index d89c0a9982d16..a86100fb56cef 100644
+--- a/sound/pci/hda/patch_hdmi.c
++++ b/sound/pci/hda/patch_hdmi.c
+@@ -3889,6 +3889,11 @@ HDA_CODEC_ENTRY(0x10de009d, "GPU 9d HDMI/DP",   
patch_nvhdmi),
+ HDA_CODEC_ENTRY(0x10de009e, "GPU 9e HDMI/DP", patch_nvhdmi),
+ HDA_CODEC_ENTRY(0x10de009f, "GPU 9f HDMI/DP", patch_nvhdmi),
+ HDA_CODEC_ENTRY(0x10de00a0, "GPU a0 HDMI/DP", patch_nvhdmi),
++HDA_CODEC_ENTRY(0x10de00a3, "GPU a3 HDMI/DP", patch_nvhdmi),
++HDA_CODEC_ENTRY(0x10de00a4, "GPU a4 HDMI/DP", patch_nvhdmi),
++HDA_CODEC_ENTRY(0x10de00a5, "GPU a5 HDMI/DP", patch_nvhdmi),
++HDA_CODEC_ENTRY(0x10de00a6, "GPU a6 HDMI/DP", patch_nvhdmi),
++HDA_CODEC_ENTRY(0x10de00a7, "GPU a7 HDMI/DP", patch_nvhdmi),
+ HDA_CODEC_ENTRY(0x10de8001, "MCP73 HDMI",     patch_nvhdmi_2ch),
+ HDA_CODEC_ENTRY(0x10de8067, "MCP67/68 HDMI",  patch_nvhdmi_2ch),
+ HDA_CODEC_ENTRY(0x11069f80, "VX900 HDMI/DP",  patch_via_hdmi),
+diff --git a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c 
b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
+index d7c2a6d13dea1..2221e43c63ce0 100644
+--- a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
++++ b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
+@@ -67,8 +67,8 @@ static int max_freq_mode;
+  */
+ static unsigned long max_frequency;
+ 
+-static unsigned long long tsc_at_measure_start;
+-static unsigned long long tsc_at_measure_end;
++static unsigned long long *tsc_at_measure_start;
++static unsigned long long *tsc_at_measure_end;
+ static unsigned long long *mperf_previous_count;
+ static unsigned long long *aperf_previous_count;
+ static unsigned long long *mperf_current_count;
+@@ -131,7 +131,7 @@ static int mperf_get_count_percent(unsigned int id, double 
*percent,
+       aperf_diff = aperf_current_count[cpu] - aperf_previous_count[cpu];
+ 
+       if (max_freq_mode == MAX_FREQ_TSC_REF) {
+-              tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
++              tsc_diff = tsc_at_measure_end[cpu] - tsc_at_measure_start[cpu];
+               *percent = 100.0 * mperf_diff / tsc_diff;
+               dprint("%s: TSC Ref - mperf_diff: %llu, tsc_diff: %llu\n",
+                      mperf_cstates[id].name, mperf_diff, tsc_diff);
+@@ -168,7 +168,7 @@ static int mperf_get_count_freq(unsigned int id, unsigned 
long long *count,
+ 
+       if (max_freq_mode == MAX_FREQ_TSC_REF) {
+               /* Calculate max_freq from TSC count */
+-              tsc_diff = tsc_at_measure_end - tsc_at_measure_start;
++              tsc_diff = tsc_at_measure_end[cpu] - tsc_at_measure_start[cpu];
+               time_diff = timespec_diff_us(time_start, time_end);
+               max_frequency = tsc_diff / time_diff;
+       }
+@@ -187,33 +187,27 @@ static int mperf_get_count_freq(unsigned int id, 
unsigned long long *count,
+ static int mperf_start(void)
+ {
+       int cpu;
+-      unsigned long long dbg;
+ 
+       clock_gettime(CLOCK_REALTIME, &time_start);
+-      mperf_get_tsc(&tsc_at_measure_start);
+ 
+-      for (cpu = 0; cpu < cpu_count; cpu++)
++      for (cpu = 0; cpu < cpu_count; cpu++) {
++              mperf_get_tsc(&tsc_at_measure_start[cpu]);
+               mperf_init_stats(cpu);
++      }
+ 
+-      mperf_get_tsc(&dbg);
+-      dprint("TSC diff: %llu\n", dbg - tsc_at_measure_start);
+       return 0;
+ }
+ 
+ static int mperf_stop(void)
+ {
+-      unsigned long long dbg;
+       int cpu;
+ 
+-      for (cpu = 0; cpu < cpu_count; cpu++)
++      for (cpu = 0; cpu < cpu_count; cpu++) {
+               mperf_measure_stats(cpu);
++              mperf_get_tsc(&tsc_at_measure_end[cpu]);
++      }
+ 
+-      mperf_get_tsc(&tsc_at_measure_end);
+       clock_gettime(CLOCK_REALTIME, &time_end);
+-
+-      mperf_get_tsc(&dbg);
+-      dprint("TSC diff: %llu\n", dbg - tsc_at_measure_end);
+-
+       return 0;
+ }
+ 
+@@ -311,7 +305,8 @@ struct cpuidle_monitor *mperf_register(void)
+       aperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
+       mperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
+       aperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
+-
++      tsc_at_measure_start = calloc(cpu_count, sizeof(unsigned long long));
++      tsc_at_measure_end = calloc(cpu_count, sizeof(unsigned long long));
+       mperf_monitor.name_len = strlen(mperf_monitor.name);
+       return &mperf_monitor;
+ }
+@@ -322,6 +317,8 @@ void mperf_unregister(void)
+       free(aperf_previous_count);
+       free(mperf_current_count);
+       free(aperf_current_count);
++      free(tsc_at_measure_start);
++      free(tsc_at_measure_end);
+       free(is_valid);
+ }
+ 
+diff --git a/tools/testing/selftests/memfd/fuse_test.c 
b/tools/testing/selftests/memfd/fuse_test.c
+index 1ccb7a3eb14bf..179946f8346e1 100644
+--- a/tools/testing/selftests/memfd/fuse_test.c
++++ b/tools/testing/selftests/memfd/fuse_test.c
+@@ -22,6 +22,7 @@
+ #include <linux/falloc.h>
+ #include <linux/fcntl.h>
+ #include <linux/memfd.h>
++#include <linux/types.h>
+ #include <sched.h>
+ #include <stdio.h>
+ #include <stdlib.h>

Reply via email to