commit:     c25f4b52eeb6d16c5291a77e8e382fbddce0c5b4
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Mon Jun  5 11:47:44 2023 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Mon Jun  5 11:47:44 2023 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=c25f4b52

Linux patch 6.3.6

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

 0000_README            |    4 +
 1005_linux-6.3.6.patch | 2266 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 2270 insertions(+)

diff --git a/0000_README b/0000_README
index 66dc0900..210d6768 100644
--- a/0000_README
+++ b/0000_README
@@ -63,6 +63,10 @@ Patch:  1004_linux-6.3.5.patch
 From:   https://www.kernel.org
 Desc:   Linux 6.3.5
 
+Patch:  1005_linux-6.3.6.patch
+From:   https://www.kernel.org
+Desc:   Linux 6.3.6
+
 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/1005_linux-6.3.6.patch b/1005_linux-6.3.6.patch
new file mode 100644
index 00000000..b9df57e3
--- /dev/null
+++ b/1005_linux-6.3.6.patch
@@ -0,0 +1,2266 @@
+diff --git a/Makefile b/Makefile
+index d710ff6a3d566..1dffadbf1f87f 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 3
+-SUBLEVEL = 5
++SUBLEVEL = 6
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+ 
+diff --git a/arch/arm/boot/dts/imx6ull-dhcor-som.dtsi 
b/arch/arm/boot/dts/imx6ull-dhcor-som.dtsi
+index 5882c7565f649..32a6022625d97 100644
+--- a/arch/arm/boot/dts/imx6ull-dhcor-som.dtsi
++++ b/arch/arm/boot/dts/imx6ull-dhcor-som.dtsi
+@@ -8,6 +8,7 @@
+ #include <dt-bindings/input/input.h>
+ #include <dt-bindings/leds/common.h>
+ #include <dt-bindings/pwm/pwm.h>
++#include <dt-bindings/regulator/dlg,da9063-regulator.h>
+ #include "imx6ull.dtsi"
+ 
+ / {
+@@ -84,16 +85,20 @@
+ 
+               regulators {
+                       vdd_soc_in_1v4: buck1 {
++                              regulator-allowed-modes = 
<DA9063_BUCK_MODE_SLEEP>; /* PFM */
+                               regulator-always-on;
+                               regulator-boot-on;
++                              regulator-initial-mode = 
<DA9063_BUCK_MODE_SLEEP>;
+                               regulator-max-microvolt = <1400000>;
+                               regulator-min-microvolt = <1400000>;
+                               regulator-name = "vdd_soc_in_1v4";
+                       };
+ 
+                       vcc_3v3: buck2 {
++                              regulator-allowed-modes = 
<DA9063_BUCK_MODE_SYNC>; /* PWM */
+                               regulator-always-on;
+                               regulator-boot-on;
++                              regulator-initial-mode = 
<DA9063_BUCK_MODE_SYNC>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-name = "vcc_3v3";
+@@ -106,8 +111,10 @@
+                        * the voltage is set to 1.5V.
+                        */
+                       vcc_ddr_1v35: buck3 {
++                              regulator-allowed-modes = 
<DA9063_BUCK_MODE_SYNC>; /* PWM */
+                               regulator-always-on;
+                               regulator-boot-on;
++                              regulator-initial-mode = 
<DA9063_BUCK_MODE_SYNC>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-min-microvolt = <1500000>;
+                               regulator-name = "vcc_ddr_1v35";
+diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c
+index 9eb968e14d31f..a80d7c62bdfe6 100644
+--- a/block/blk-mq-tag.c
++++ b/block/blk-mq-tag.c
+@@ -41,16 +41,20 @@ void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx)
+ {
+       unsigned int users;
+ 
++      /*
++       * calling test_bit() prior to test_and_set_bit() is intentional,
++       * it avoids dirtying the cacheline if the queue is already active.
++       */
+       if (blk_mq_is_shared_tags(hctx->flags)) {
+               struct request_queue *q = hctx->queue;
+ 
+-              if (test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags))
++              if (test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags) ||
++                  test_and_set_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags))
+                       return;
+-              set_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags);
+       } else {
+-              if (test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state))
++              if (test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state) ||
++                  test_and_set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state))
+                       return;
+-              set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state);
+       }
+ 
+       users = atomic_inc_return(&hctx->tags->active_queues);
+diff --git a/block/blk-wbt.c b/block/blk-wbt.c
+index e49a486845327..9ec2a2f1eda38 100644
+--- a/block/blk-wbt.c
++++ b/block/blk-wbt.c
+@@ -730,14 +730,16 @@ void wbt_enable_default(struct gendisk *disk)
+ {
+       struct request_queue *q = disk->queue;
+       struct rq_qos *rqos;
+-      bool disable_flag = q->elevator &&
+-                  test_bit(ELEVATOR_FLAG_DISABLE_WBT, &q->elevator->flags);
++      bool enable = IS_ENABLED(CONFIG_BLK_WBT_MQ);
++
++      if (q->elevator &&
++          test_bit(ELEVATOR_FLAG_DISABLE_WBT, &q->elevator->flags))
++              enable = false;
+ 
+       /* Throttling already enabled? */
+       rqos = wbt_rq_qos(q);
+       if (rqos) {
+-              if (!disable_flag &&
+-                  RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT)
++              if (enable && RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT)
+                       RQWB(rqos)->enable_state = WBT_STATE_ON_DEFAULT;
+               return;
+       }
+@@ -746,7 +748,7 @@ void wbt_enable_default(struct gendisk *disk)
+       if (!blk_queue_registered(q))
+               return;
+ 
+-      if (queue_is_mq(q) && !disable_flag)
++      if (queue_is_mq(q) && enable)
+               wbt_init(disk);
+ }
+ EXPORT_SYMBOL_GPL(wbt_enable_default);
+diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
+index 8dd46fad151eb..a7eb25066c274 100644
+--- a/drivers/cpufreq/amd-pstate.c
++++ b/drivers/cpufreq/amd-pstate.c
+@@ -422,9 +422,8 @@ static int amd_pstate_verify(struct cpufreq_policy_data 
*policy)
+       return 0;
+ }
+ 
+-static int amd_pstate_target(struct cpufreq_policy *policy,
+-                           unsigned int target_freq,
+-                           unsigned int relation)
++static int amd_pstate_update_freq(struct cpufreq_policy *policy,
++                                unsigned int target_freq, bool fast_switch)
+ {
+       struct cpufreq_freqs freqs;
+       struct amd_cpudata *cpudata = policy->driver_data;
+@@ -443,26 +442,50 @@ static int amd_pstate_target(struct cpufreq_policy 
*policy,
+       des_perf = DIV_ROUND_CLOSEST(target_freq * cap_perf,
+                                    cpudata->max_freq);
+ 
+-      cpufreq_freq_transition_begin(policy, &freqs);
+-      amd_pstate_update(cpudata, min_perf, des_perf,
+-                        max_perf, false);
+-      cpufreq_freq_transition_end(policy, &freqs, false);
++      WARN_ON(fast_switch && !policy->fast_switch_enabled);
++      /*
++       * If fast_switch is desired, then there aren't any registered
++       * transition notifiers. See comment for
++       * cpufreq_enable_fast_switch().
++       */
++      if (!fast_switch)
++              cpufreq_freq_transition_begin(policy, &freqs);
++
++      amd_pstate_update(cpudata, min_perf, des_perf, max_perf, fast_switch);
++
++      if (!fast_switch)
++              cpufreq_freq_transition_end(policy, &freqs, false);
+ 
+       return 0;
+ }
+ 
++static int amd_pstate_target(struct cpufreq_policy *policy,
++                           unsigned int target_freq,
++                           unsigned int relation)
++{
++      return amd_pstate_update_freq(policy, target_freq, false);
++}
++
++static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
++                                unsigned int target_freq)
++{
++      return amd_pstate_update_freq(policy, target_freq, true);
++}
++
+ static void amd_pstate_adjust_perf(unsigned int cpu,
+                                  unsigned long _min_perf,
+                                  unsigned long target_perf,
+                                  unsigned long capacity)
+ {
+       unsigned long max_perf, min_perf, des_perf,
+-                    cap_perf, lowest_nonlinear_perf;
++                    cap_perf, lowest_nonlinear_perf, max_freq;
+       struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+       struct amd_cpudata *cpudata = policy->driver_data;
++      unsigned int target_freq;
+ 
+       cap_perf = READ_ONCE(cpudata->highest_perf);
+       lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
++      max_freq = READ_ONCE(cpudata->max_freq);
+ 
+       des_perf = cap_perf;
+       if (target_perf < capacity)
+@@ -479,6 +502,10 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
+       if (max_perf < min_perf)
+               max_perf = min_perf;
+ 
++      des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
++      target_freq = div_u64(des_perf * max_freq, max_perf);
++      policy->cur = target_freq;
++
+       amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true);
+       cpufreq_cpu_put(policy);
+ }
+@@ -692,6 +719,7 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy 
*policy)
+ 
+       freq_qos_remove_request(&cpudata->req[1]);
+       freq_qos_remove_request(&cpudata->req[0]);
++      policy->fast_switch_possible = false;
+       kfree(cpudata);
+ 
+       return 0;
+@@ -996,7 +1024,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy 
*policy)
+       policy->policy = CPUFREQ_POLICY_POWERSAVE;
+ 
+       if (boot_cpu_has(X86_FEATURE_CPPC)) {
+-              policy->fast_switch_possible = true;
+               ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value);
+               if (ret)
+                       return ret;
+@@ -1019,7 +1046,6 @@ free_cpudata1:
+ static int amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
+ {
+       pr_debug("CPU %d exiting\n", policy->cpu);
+-      policy->fast_switch_possible = false;
+       return 0;
+ }
+ 
+@@ -1226,6 +1252,7 @@ static struct cpufreq_driver amd_pstate_driver = {
+       .flags          = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
+       .verify         = amd_pstate_verify,
+       .target         = amd_pstate_target,
++      .fast_switch    = amd_pstate_fast_switch,
+       .init           = amd_pstate_cpu_init,
+       .exit           = amd_pstate_cpu_exit,
+       .suspend        = amd_pstate_cpu_suspend,
+diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
+index 4d1f9c5b5029a..27cbf457416d2 100644
+--- a/drivers/cxl/core/port.c
++++ b/drivers/cxl/core/port.c
+@@ -751,11 +751,10 @@ struct cxl_port *devm_cxl_add_port(struct device *host, 
struct device *uport,
+ 
+       parent_port = parent_dport ? parent_dport->port : NULL;
+       if (IS_ERR(port)) {
+-              dev_dbg(uport, "Failed to add %s%s%s%s: %ld\n",
+-                      dev_name(&port->dev),
+-                      parent_port ? " to " : "",
++              dev_dbg(uport, "Failed to add%s%s%s: %ld\n",
++                      parent_port ? " port to " : "",
+                       parent_port ? dev_name(&parent_port->dev) : "",
+-                      parent_port ? "" : " (root port)",
++                      parent_port ? "" : " root port",
+                       PTR_ERR(port));
+       } else {
+               dev_dbg(uport, "%s added%s%s%s\n",
+diff --git a/drivers/firmware/arm_ffa/driver.c 
b/drivers/firmware/arm_ffa/driver.c
+index 02774baa90078..e234091386671 100644
+--- a/drivers/firmware/arm_ffa/driver.c
++++ b/drivers/firmware/arm_ffa/driver.c
+@@ -193,7 +193,8 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, 
u32 uuid3,
+       int idx, count, flags = 0, sz, buf_sz;
+       ffa_value_t partition_info;
+ 
+-      if (!buffer || !num_partitions) /* Just get the count for now */
++      if (drv_info->version > FFA_VERSION_1_0 &&
++          (!buffer || !num_partitions)) /* Just get the count for now */
+               flags = PARTITION_INFO_GET_RETURN_COUNT_ONLY;
+ 
+       mutex_lock(&drv_info->rx_lock);
+diff --git a/drivers/firmware/arm_scmi/raw_mode.c 
b/drivers/firmware/arm_scmi/raw_mode.c
+index d40df099fd515..6971dcf72fb99 100644
+--- a/drivers/firmware/arm_scmi/raw_mode.c
++++ b/drivers/firmware/arm_scmi/raw_mode.c
+@@ -1066,7 +1066,7 @@ static int scmi_xfer_raw_worker_init(struct 
scmi_raw_mode_info *raw)
+ 
+       raw->wait_wq = alloc_workqueue("scmi-raw-wait-wq-%d",
+                                      WQ_UNBOUND | WQ_FREEZABLE |
+-                                     WQ_HIGHPRI, WQ_SYSFS, raw->id);
++                                     WQ_HIGHPRI | WQ_SYSFS, 0, raw->id);
+       if (!raw->wait_wq)
+               return -ENOMEM;
+ 
+diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
+index badbe05823180..14b655411aa0a 100644
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -879,7 +879,7 @@ config GPIO_F7188X
+       help
+         This option enables support for GPIOs found on Fintek Super-I/O
+         chips F71869, F71869A, F71882FG, F71889F and F81866.
+-        As well as Nuvoton Super-I/O chip NCT6116D.
++        As well as Nuvoton Super-I/O chip NCT6126D.
+ 
+         To compile this driver as a module, choose M here: the module will
+         be called f7188x-gpio.
+diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c
+index 9effa7769bef5..f54ca5a1775ea 100644
+--- a/drivers/gpio/gpio-f7188x.c
++++ b/drivers/gpio/gpio-f7188x.c
+@@ -48,7 +48,7 @@
+ /*
+  * Nuvoton devices.
+  */
+-#define SIO_NCT6116D_ID               0xD283  /* NCT6116D chipset ID */
++#define SIO_NCT6126D_ID               0xD283  /* NCT6126D chipset ID */
+ 
+ #define SIO_LD_GPIO_NUVOTON   0x07    /* GPIO logical device */
+ 
+@@ -62,7 +62,7 @@ enum chips {
+       f81866,
+       f81804,
+       f81865,
+-      nct6116d,
++      nct6126d,
+ };
+ 
+ static const char * const f7188x_names[] = {
+@@ -74,7 +74,7 @@ static const char * const f7188x_names[] = {
+       "f81866",
+       "f81804",
+       "f81865",
+-      "nct6116d",
++      "nct6126d",
+ };
+ 
+ struct f7188x_sio {
+@@ -187,8 +187,8 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, 
unsigned offset,
+ /* Output mode register (0:open drain 1:push-pull). */
+ #define f7188x_gpio_out_mode(base) ((base) + 3)
+ 
+-#define f7188x_gpio_dir_invert(type)  ((type) == nct6116d)
+-#define f7188x_gpio_data_single(type) ((type) == nct6116d)
++#define f7188x_gpio_dir_invert(type)  ((type) == nct6126d)
++#define f7188x_gpio_data_single(type) ((type) == nct6126d)
+ 
+ static struct f7188x_gpio_bank f71869_gpio_bank[] = {
+       F7188X_GPIO_BANK(0, 6, 0xF0, DRVNAME "-0"),
+@@ -274,7 +274,7 @@ static struct f7188x_gpio_bank f81865_gpio_bank[] = {
+       F7188X_GPIO_BANK(60, 5, 0x90, DRVNAME "-6"),
+ };
+ 
+-static struct f7188x_gpio_bank nct6116d_gpio_bank[] = {
++static struct f7188x_gpio_bank nct6126d_gpio_bank[] = {
+       F7188X_GPIO_BANK(0, 8, 0xE0, DRVNAME "-0"),
+       F7188X_GPIO_BANK(10, 8, 0xE4, DRVNAME "-1"),
+       F7188X_GPIO_BANK(20, 8, 0xE8, DRVNAME "-2"),
+@@ -282,7 +282,7 @@ static struct f7188x_gpio_bank nct6116d_gpio_bank[] = {
+       F7188X_GPIO_BANK(40, 8, 0xF0, DRVNAME "-4"),
+       F7188X_GPIO_BANK(50, 8, 0xF4, DRVNAME "-5"),
+       F7188X_GPIO_BANK(60, 8, 0xF8, DRVNAME "-6"),
+-      F7188X_GPIO_BANK(70, 1, 0xFC, DRVNAME "-7"),
++      F7188X_GPIO_BANK(70, 8, 0xFC, DRVNAME "-7"),
+ };
+ 
+ static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+@@ -490,9 +490,9 @@ static int f7188x_gpio_probe(struct platform_device *pdev)
+               data->nr_bank = ARRAY_SIZE(f81865_gpio_bank);
+               data->bank = f81865_gpio_bank;
+               break;
+-      case nct6116d:
+-              data->nr_bank = ARRAY_SIZE(nct6116d_gpio_bank);
+-              data->bank = nct6116d_gpio_bank;
++      case nct6126d:
++              data->nr_bank = ARRAY_SIZE(nct6126d_gpio_bank);
++              data->bank = nct6126d_gpio_bank;
+               break;
+       default:
+               return -ENODEV;
+@@ -559,9 +559,9 @@ static int __init f7188x_find(int addr, struct f7188x_sio 
*sio)
+       case SIO_F81865_ID:
+               sio->type = f81865;
+               break;
+-      case SIO_NCT6116D_ID:
++      case SIO_NCT6126D_ID:
+               sio->device = SIO_LD_GPIO_NUVOTON;
+-              sio->type = nct6116d;
++              sio->type = nct6126d;
+               break;
+       default:
+               pr_info("Unsupported Fintek device 0x%04x\n", devid);
+@@ -569,7 +569,7 @@ static int __init f7188x_find(int addr, struct f7188x_sio 
*sio)
+       }
+ 
+       /* double check manufacturer where possible */
+-      if (sio->type != nct6116d) {
++      if (sio->type != nct6126d) {
+               manid = superio_inw(addr, SIO_FINTEK_MANID);
+               if (manid != SIO_FINTEK_ID) {
+                       pr_debug("Not a Fintek device at 0x%08x\n", addr);
+@@ -581,7 +581,7 @@ static int __init f7188x_find(int addr, struct f7188x_sio 
*sio)
+       err = 0;
+ 
+       pr_info("Found %s at %#x\n", f7188x_names[sio->type], (unsigned 
int)addr);
+-      if (sio->type != nct6116d)
++      if (sio->type != nct6126d)
+               pr_info("   revision %d\n", superio_inb(addr, 
SIO_FINTEK_DEVREV));
+ 
+ err:
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index 19bd23044b017..4472214fcd43a 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -193,6 +193,8 @@ static int gpiochip_find_base(int ngpio)
+                       break;
+               /* nope, check the space right after the chip */
+               base = gdev->base + gdev->ngpio;
++              if (base < GPIO_DYNAMIC_BASE)
++                      base = GPIO_DYNAMIC_BASE;
+       }
+ 
+       if (gpio_is_valid(base)) {
+diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c 
b/drivers/gpu/drm/i915/display/intel_ddi.c
+index 254559abedfba..379050d228941 100644
+--- a/drivers/gpu/drm/i915/display/intel_ddi.c
++++ b/drivers/gpu/drm/i915/display/intel_ddi.c
+@@ -2731,9 +2731,6 @@ static void intel_ddi_post_disable(struct 
intel_atomic_state *state,
+                                  const struct drm_connector_state 
*old_conn_state)
+ {
+       struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+-      struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
+-      enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
+-      bool is_tc_port = intel_phy_is_tc(dev_priv, phy);
+       struct intel_crtc *slave_crtc;
+ 
+       if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST)) {
+@@ -2783,6 +2780,17 @@ static void intel_ddi_post_disable(struct 
intel_atomic_state *state,
+       else
+               intel_ddi_post_disable_dp(state, encoder, old_crtc_state,
+                                         old_conn_state);
++}
++
++static void intel_ddi_post_pll_disable(struct intel_atomic_state *state,
++                                     struct intel_encoder *encoder,
++                                     const struct intel_crtc_state 
*old_crtc_state,
++                                     const struct drm_connector_state 
*old_conn_state)
++{
++      struct drm_i915_private *i915 = to_i915(encoder->base.dev);
++      struct intel_digital_port *dig_port = enc_to_dig_port(encoder);
++      enum phy phy = intel_port_to_phy(i915, encoder->port);
++      bool is_tc_port = intel_phy_is_tc(i915, phy);
+ 
+       main_link_aux_power_domain_put(dig_port, old_crtc_state);
+ 
+@@ -4381,6 +4389,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, 
enum port port)
+       encoder->pre_pll_enable = intel_ddi_pre_pll_enable;
+       encoder->pre_enable = intel_ddi_pre_enable;
+       encoder->disable = intel_disable_ddi;
++      encoder->post_pll_disable = intel_ddi_post_pll_disable;
+       encoder->post_disable = intel_ddi_post_disable;
+       encoder->update_pipe = intel_ddi_update_pipe;
+       encoder->get_hw_state = intel_ddi_get_hw_state;
+diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
+index 2bef50ab0ad19..c84b581c61c6b 100644
+--- a/drivers/gpu/drm/i915/display/intel_display.c
++++ b/drivers/gpu/drm/i915/display/intel_display.c
+@@ -2000,6 +2000,8 @@ static void ilk_crtc_disable(struct intel_atomic_state 
*state,
+ 
+       intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true);
+       intel_set_pch_fifo_underrun_reporting(dev_priv, pipe, true);
++
++      intel_disable_shared_dpll(old_crtc_state);
+ }
+ 
+ static void hsw_crtc_disable(struct intel_atomic_state *state,
+@@ -2018,7 +2020,19 @@ static void hsw_crtc_disable(struct intel_atomic_state 
*state,
+               intel_encoders_post_disable(state, crtc);
+       }
+ 
+-      intel_dmc_disable_pipe(i915, crtc->pipe);
++      intel_disable_shared_dpll(old_crtc_state);
++
++      if (!intel_crtc_is_bigjoiner_slave(old_crtc_state)) {
++              struct intel_crtc *slave_crtc;
++
++              intel_encoders_post_pll_disable(state, crtc);
++
++              intel_dmc_disable_pipe(i915, crtc->pipe);
++
++              for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc,
++                                               
intel_crtc_bigjoiner_slave_pipes(old_crtc_state))
++                      intel_dmc_disable_pipe(i915, slave_crtc->pipe);
++      }
+ }
+ 
+ static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state)
+@@ -7140,7 +7154,6 @@ static void intel_old_crtc_state_disables(struct 
intel_atomic_state *state,
+       dev_priv->display.funcs.display->crtc_disable(state, crtc);
+       crtc->active = false;
+       intel_fbc_disable(crtc);
+-      intel_disable_shared_dpll(old_crtc_state);
+ 
+       if (!new_crtc_state->hw.active)
+               intel_initial_watermarks(state, crtc);
+diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c 
b/drivers/gpu/drm/i915/display/intel_dp_mst.c
+index 7c9b328bc2d73..a93018ce0e312 100644
+--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
++++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
+@@ -623,6 +623,20 @@ static void intel_mst_post_disable_dp(struct 
intel_atomic_state *state,
+                   intel_dp->active_mst_links);
+ }
+ 
++static void intel_mst_post_pll_disable_dp(struct intel_atomic_state *state,
++                                        struct intel_encoder *encoder,
++                                        const struct intel_crtc_state 
*old_crtc_state,
++                                        const struct drm_connector_state 
*old_conn_state)
++{
++      struct intel_dp_mst_encoder *intel_mst = enc_to_mst(encoder);
++      struct intel_digital_port *dig_port = intel_mst->primary;
++      struct intel_dp *intel_dp = &dig_port->dp;
++
++      if (intel_dp->active_mst_links == 0 &&
++          dig_port->base.post_pll_disable)
++              dig_port->base.post_pll_disable(state, encoder, old_crtc_state, 
old_conn_state);
++}
++
+ static void intel_mst_pre_pll_enable_dp(struct intel_atomic_state *state,
+                                       struct intel_encoder *encoder,
+                                       const struct intel_crtc_state 
*pipe_config,
+@@ -1146,6 +1160,7 @@ intel_dp_create_fake_mst_encoder(struct 
intel_digital_port *dig_port, enum pipe
+       intel_encoder->compute_config_late = intel_dp_mst_compute_config_late;
+       intel_encoder->disable = intel_mst_disable_dp;
+       intel_encoder->post_disable = intel_mst_post_disable_dp;
++      intel_encoder->post_pll_disable = intel_mst_post_pll_disable_dp;
+       intel_encoder->update_pipe = intel_ddi_update_pipe;
+       intel_encoder->pre_pll_enable = intel_mst_pre_pll_enable_dp;
+       intel_encoder->pre_enable = intel_mst_pre_enable_dp;
+diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c 
b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
+index 52cdbd4fc2fa0..48b726e408057 100644
+--- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c
++++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
+@@ -96,7 +96,6 @@ static void intel_crtc_disable_noatomic(struct intel_crtc 
*crtc,
+ 
+       intel_fbc_disable(crtc);
+       intel_update_watermarks(i915);
+-      intel_disable_shared_dpll(crtc_state);
+ 
+       intel_display_power_put_all_in_set(i915, &crtc->enabled_power_domains);
+ 
+diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c 
b/drivers/hwtracing/coresight/coresight-etm-perf.c
+index 711f451b69469..89e8ed214ea49 100644
+--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
++++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
+@@ -402,6 +402,7 @@ static void *etm_setup_aux(struct perf_event *event, void 
**pages,
+               trace_id = coresight_trace_id_get_cpu_id(cpu);
+               if (!IS_VALID_CS_TRACE_ID(trace_id)) {
+                       cpumask_clear_cpu(cpu, mask);
++                      coresight_release_path(path);
+                       continue;
+               }
+ 
+diff --git a/drivers/net/ethernet/freescale/fec_main.c 
b/drivers/net/ethernet/freescale/fec_main.c
+index 577d94821b3e7..38e5b5abe067c 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -3834,6 +3834,11 @@ static int fec_enet_txq_xmit_frame(struct 
fec_enet_private *fep,
+       index = fec_enet_get_bd_index(last_bdp, &txq->bd);
+       txq->tx_skbuff[index] = NULL;
+ 
++      /* Make sure the updates to rest of the descriptor are performed before
++       * transferring ownership.
++       */
++      dma_wmb();
++
+       /* Send it on its way.  Tell FEC it's ready, interrupt when done,
+        * it's the last BD of the frame, and to put the CRC on the end.
+        */
+@@ -3843,8 +3848,14 @@ static int fec_enet_txq_xmit_frame(struct 
fec_enet_private *fep,
+       /* If this was the last BD in the ring, start at the beginning again. */
+       bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd);
+ 
++      /* Make sure the update to bdp are performed before txq->bd.cur. */
++      dma_wmb();
++
+       txq->bd.cur = bdp;
+ 
++      /* Trigger transmission start */
++      writel(0, txq->bd.reg_desc_active);
++
+       return 0;
+ }
+ 
+@@ -3873,12 +3884,6 @@ static int fec_enet_xdp_xmit(struct net_device *dev,
+               sent_frames++;
+       }
+ 
+-      /* Make sure the update to bdp and tx_skbuff are performed. */
+-      wmb();
+-
+-      /* Trigger transmission start */
+-      writel(0, txq->bd.reg_desc_active);
+-
+       __netif_tx_unlock(nq);
+ 
+       return sent_frames;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile 
b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+index 8d4e25cc54ea3..78755dfeaccea 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
++++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+@@ -69,7 +69,7 @@ mlx5_core-$(CONFIG_MLX5_TC_SAMPLE)   += en/tc/sample.o
+ #
+ mlx5_core-$(CONFIG_MLX5_ESWITCH)   += eswitch.o eswitch_offloads.o 
eswitch_offloads_termtbl.o \
+                                     ecpf.o rdma.o esw/legacy.o \
+-                                    esw/debugfs.o esw/devlink_port.o 
esw/vporttbl.o esw/qos.o
++                                    esw/devlink_port.o esw/vporttbl.o 
esw/qos.o
+ 
+ mlx5_core-$(CONFIG_MLX5_ESWITCH)   += esw/acl/helper.o \
+                                     esw/acl/egress_lgcy.o 
esw/acl/egress_ofld.o \
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c 
b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+index 2b1094e5b0c9d..53acd9a8a4c35 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+@@ -5793,22 +5793,43 @@ bool mlx5e_tc_update_skb_nic(struct mlx5_cqe64 *cqe, 
struct sk_buff *skb)
+                                  0, NULL);
+ }
+ 
++static struct mapping_ctx *
++mlx5e_get_priv_obj_mapping(struct mlx5e_priv *priv)
++{
++      struct mlx5e_tc_table *tc;
++      struct mlx5_eswitch *esw;
++      struct mapping_ctx *ctx;
++
++      if (is_mdev_switchdev_mode(priv->mdev)) {
++              esw = priv->mdev->priv.eswitch;
++              ctx = esw->offloads.reg_c0_obj_pool;
++      } else {
++              tc = mlx5e_fs_get_tc(priv->fs);
++              ctx = tc->mapping;
++      }
++
++      return ctx;
++}
++
+ int mlx5e_tc_action_miss_mapping_get(struct mlx5e_priv *priv, struct 
mlx5_flow_attr *attr,
+                                    u64 act_miss_cookie, u32 *act_miss_mapping)
+ {
+-      struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+       struct mlx5_mapped_obj mapped_obj = {};
++      struct mlx5_eswitch *esw;
+       struct mapping_ctx *ctx;
+       int err;
+ 
+-      ctx = esw->offloads.reg_c0_obj_pool;
+-
++      ctx = mlx5e_get_priv_obj_mapping(priv);
+       mapped_obj.type = MLX5_MAPPED_OBJ_ACT_MISS;
+       mapped_obj.act_miss_cookie = act_miss_cookie;
+       err = mapping_add(ctx, &mapped_obj, act_miss_mapping);
+       if (err)
+               return err;
+ 
++      if (!is_mdev_switchdev_mode(priv->mdev))
++              return 0;
++
++      esw = priv->mdev->priv.eswitch;
+       attr->act_id_restore_rule = esw_add_restore_rule(esw, 
*act_miss_mapping);
+       if (IS_ERR(attr->act_id_restore_rule))
+               goto err_rule;
+@@ -5823,10 +5844,9 @@ err_rule:
+ void mlx5e_tc_action_miss_mapping_put(struct mlx5e_priv *priv, struct 
mlx5_flow_attr *attr,
+                                     u32 act_miss_mapping)
+ {
+-      struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+-      struct mapping_ctx *ctx;
++      struct mapping_ctx *ctx = mlx5e_get_priv_obj_mapping(priv);
+ 
+-      ctx = esw->offloads.reg_c0_obj_pool;
+-      mlx5_del_flow_rules(attr->act_id_restore_rule);
++      if (is_mdev_switchdev_mode(priv->mdev))
++              mlx5_del_flow_rules(attr->act_id_restore_rule);
+       mapping_remove(ctx, act_miss_mapping);
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/debugfs.c 
b/drivers/net/ethernet/mellanox/mlx5/core/esw/debugfs.c
+deleted file mode 100644
+index 3d0bbcca1cb99..0000000000000
+--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/debugfs.c
++++ /dev/null
+@@ -1,198 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+-/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. 
*/
+-
+-#include <linux/debugfs.h>
+-#include "eswitch.h"
+-
+-enum vnic_diag_counter {
+-      MLX5_VNIC_DIAG_TOTAL_Q_UNDER_PROCESSOR_HANDLE,
+-      MLX5_VNIC_DIAG_SEND_QUEUE_PRIORITY_UPDATE_FLOW,
+-      MLX5_VNIC_DIAG_COMP_EQ_OVERRUN,
+-      MLX5_VNIC_DIAG_ASYNC_EQ_OVERRUN,
+-      MLX5_VNIC_DIAG_CQ_OVERRUN,
+-      MLX5_VNIC_DIAG_INVALID_COMMAND,
+-      MLX5_VNIC_DIAG_QOUTA_EXCEEDED_COMMAND,
+-      MLX5_VNIC_DIAG_RX_STEERING_DISCARD,
+-};
+-
+-static int mlx5_esw_query_vnic_diag(struct mlx5_vport *vport, enum 
vnic_diag_counter counter,
+-                                  u64 *val)
+-{
+-      u32 out[MLX5_ST_SZ_DW(query_vnic_env_out)] = {};
+-      u32 in[MLX5_ST_SZ_DW(query_vnic_env_in)] = {};
+-      struct mlx5_core_dev *dev = vport->dev;
+-      u16 vport_num = vport->vport;
+-      void *vnic_diag_out;
+-      int err;
+-
+-      MLX5_SET(query_vnic_env_in, in, opcode, MLX5_CMD_OP_QUERY_VNIC_ENV);
+-      MLX5_SET(query_vnic_env_in, in, vport_number, vport_num);
+-      if (!mlx5_esw_is_manager_vport(dev->priv.eswitch, vport_num))
+-              MLX5_SET(query_vnic_env_in, in, other_vport, 1);
+-
+-      err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+-      if (err)
+-              return err;
+-
+-      vnic_diag_out = MLX5_ADDR_OF(query_vnic_env_out, out, vport_env);
+-      switch (counter) {
+-      case MLX5_VNIC_DIAG_TOTAL_Q_UNDER_PROCESSOR_HANDLE:
+-              *val = MLX5_GET(vnic_diagnostic_statistics, vnic_diag_out, 
total_error_queues);
+-              break;
+-      case MLX5_VNIC_DIAG_SEND_QUEUE_PRIORITY_UPDATE_FLOW:
+-              *val = MLX5_GET(vnic_diagnostic_statistics, vnic_diag_out,
+-                              send_queue_priority_update_flow);
+-              break;
+-      case MLX5_VNIC_DIAG_COMP_EQ_OVERRUN:
+-              *val = MLX5_GET(vnic_diagnostic_statistics, vnic_diag_out, 
comp_eq_overrun);
+-              break;
+-      case MLX5_VNIC_DIAG_ASYNC_EQ_OVERRUN:
+-              *val = MLX5_GET(vnic_diagnostic_statistics, vnic_diag_out, 
async_eq_overrun);
+-              break;
+-      case MLX5_VNIC_DIAG_CQ_OVERRUN:
+-              *val = MLX5_GET(vnic_diagnostic_statistics, vnic_diag_out, 
cq_overrun);
+-              break;
+-      case MLX5_VNIC_DIAG_INVALID_COMMAND:
+-              *val = MLX5_GET(vnic_diagnostic_statistics, vnic_diag_out, 
invalid_command);
+-              break;
+-      case MLX5_VNIC_DIAG_QOUTA_EXCEEDED_COMMAND:
+-              *val = MLX5_GET(vnic_diagnostic_statistics, vnic_diag_out, 
quota_exceeded_command);
+-              break;
+-      case MLX5_VNIC_DIAG_RX_STEERING_DISCARD:
+-              *val = MLX5_GET64(vnic_diagnostic_statistics, vnic_diag_out,
+-                                nic_receive_steering_discard);
+-              break;
+-      }
+-
+-      return 0;
+-}
+-
+-static int __show_vnic_diag(struct seq_file *file, struct mlx5_vport *vport,
+-                          enum vnic_diag_counter type)
+-{
+-      u64 val = 0;
+-      int ret;
+-
+-      ret = mlx5_esw_query_vnic_diag(vport, type, &val);
+-      if (ret)
+-              return ret;
+-
+-      seq_printf(file, "%llu\n", val);
+-      return 0;
+-}
+-
+-static int total_q_under_processor_handle_show(struct seq_file *file, void 
*priv)
+-{
+-      return __show_vnic_diag(file, file->private, 
MLX5_VNIC_DIAG_TOTAL_Q_UNDER_PROCESSOR_HANDLE);
+-}
+-
+-static int send_queue_priority_update_flow_show(struct seq_file *file, void 
*priv)
+-{
+-      return __show_vnic_diag(file, file->private,
+-                              MLX5_VNIC_DIAG_SEND_QUEUE_PRIORITY_UPDATE_FLOW);
+-}
+-
+-static int comp_eq_overrun_show(struct seq_file *file, void *priv)
+-{
+-      return __show_vnic_diag(file, file->private, 
MLX5_VNIC_DIAG_COMP_EQ_OVERRUN);
+-}
+-
+-static int async_eq_overrun_show(struct seq_file *file, void *priv)
+-{
+-      return __show_vnic_diag(file, file->private, 
MLX5_VNIC_DIAG_ASYNC_EQ_OVERRUN);
+-}
+-
+-static int cq_overrun_show(struct seq_file *file, void *priv)
+-{
+-      return __show_vnic_diag(file, file->private, MLX5_VNIC_DIAG_CQ_OVERRUN);
+-}
+-
+-static int invalid_command_show(struct seq_file *file, void *priv)
+-{
+-      return __show_vnic_diag(file, file->private, 
MLX5_VNIC_DIAG_INVALID_COMMAND);
+-}
+-
+-static int quota_exceeded_command_show(struct seq_file *file, void *priv)
+-{
+-      return __show_vnic_diag(file, file->private, 
MLX5_VNIC_DIAG_QOUTA_EXCEEDED_COMMAND);
+-}
+-
+-static int rx_steering_discard_show(struct seq_file *file, void *priv)
+-{
+-      return __show_vnic_diag(file, file->private, 
MLX5_VNIC_DIAG_RX_STEERING_DISCARD);
+-}
+-
+-DEFINE_SHOW_ATTRIBUTE(total_q_under_processor_handle);
+-DEFINE_SHOW_ATTRIBUTE(send_queue_priority_update_flow);
+-DEFINE_SHOW_ATTRIBUTE(comp_eq_overrun);
+-DEFINE_SHOW_ATTRIBUTE(async_eq_overrun);
+-DEFINE_SHOW_ATTRIBUTE(cq_overrun);
+-DEFINE_SHOW_ATTRIBUTE(invalid_command);
+-DEFINE_SHOW_ATTRIBUTE(quota_exceeded_command);
+-DEFINE_SHOW_ATTRIBUTE(rx_steering_discard);
+-
+-void mlx5_esw_vport_debugfs_destroy(struct mlx5_eswitch *esw, u16 vport_num)
+-{
+-      struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
+-
+-      debugfs_remove_recursive(vport->dbgfs);
+-      vport->dbgfs = NULL;
+-}
+-
+-/* vnic diag dir name is "pf", "ecpf" or "{vf/sf}_xxxx" */
+-#define VNIC_DIAG_DIR_NAME_MAX_LEN 8
+-
+-void mlx5_esw_vport_debugfs_create(struct mlx5_eswitch *esw, u16 vport_num, 
bool is_sf, u16 sf_num)
+-{
+-      struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
+-      struct dentry *vnic_diag;
+-      char dir_name[VNIC_DIAG_DIR_NAME_MAX_LEN];
+-      int err;
+-
+-      if (!MLX5_CAP_GEN(esw->dev, vport_group_manager))
+-              return;
+-
+-      if (vport_num == MLX5_VPORT_PF) {
+-              strcpy(dir_name, "pf");
+-      } else if (vport_num == MLX5_VPORT_ECPF) {
+-              strcpy(dir_name, "ecpf");
+-      } else {
+-              err = snprintf(dir_name, VNIC_DIAG_DIR_NAME_MAX_LEN, "%s_%d", 
is_sf ? "sf" : "vf",
+-                             is_sf ? sf_num : vport_num - 
MLX5_VPORT_FIRST_VF);
+-              if (WARN_ON(err < 0))
+-                      return;
+-      }
+-
+-      vport->dbgfs = debugfs_create_dir(dir_name, esw->dbgfs);
+-      vnic_diag = debugfs_create_dir("vnic_diag", vport->dbgfs);
+-
+-      if (MLX5_CAP_GEN(esw->dev, vnic_env_queue_counters)) {
+-              debugfs_create_file("total_q_under_processor_handle", 0444, 
vnic_diag, vport,
+-                                  &total_q_under_processor_handle_fops);
+-              debugfs_create_file("send_queue_priority_update_flow", 0444, 
vnic_diag, vport,
+-                                  &send_queue_priority_update_flow_fops);
+-      }
+-
+-      if (MLX5_CAP_GEN(esw->dev, eq_overrun_count)) {
+-              debugfs_create_file("comp_eq_overrun", 0444, vnic_diag, vport,
+-                                  &comp_eq_overrun_fops);
+-              debugfs_create_file("async_eq_overrun", 0444, vnic_diag, vport,
+-                                  &async_eq_overrun_fops);
+-      }
+-
+-      if (MLX5_CAP_GEN(esw->dev, vnic_env_cq_overrun))
+-              debugfs_create_file("cq_overrun", 0444, vnic_diag, vport, 
&cq_overrun_fops);
+-
+-      if (MLX5_CAP_GEN(esw->dev, invalid_command_count))
+-              debugfs_create_file("invalid_command", 0444, vnic_diag, vport,
+-                                  &invalid_command_fops);
+-
+-      if (MLX5_CAP_GEN(esw->dev, quota_exceeded_count))
+-              debugfs_create_file("quota_exceeded_command", 0444, vnic_diag, 
vport,
+-                                  &quota_exceeded_command_fops);
+-
+-      if (MLX5_CAP_GEN(esw->dev, nic_receive_steering_discard))
+-              debugfs_create_file("rx_steering_discard", 0444, vnic_diag, 
vport,
+-                                  &rx_steering_discard_fops);
+-
+-}
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c 
b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+index 19fed514fc173..bb2720a23a501 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+@@ -36,7 +36,6 @@
+ #include <linux/mlx5/vport.h>
+ #include <linux/mlx5/fs.h>
+ #include <linux/mlx5/mpfs.h>
+-#include <linux/debugfs.h>
+ #include "esw/acl/lgcy.h"
+ #include "esw/legacy.h"
+ #include "esw/qos.h"
+@@ -1056,7 +1055,6 @@ int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, 
u16 vport_num,
+       if (err)
+               return err;
+ 
+-      mlx5_esw_vport_debugfs_create(esw, vport_num, false, 0);
+       err = esw_offloads_load_rep(esw, vport_num);
+       if (err)
+               goto err_rep;
+@@ -1064,7 +1062,6 @@ int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, 
u16 vport_num,
+       return err;
+ 
+ err_rep:
+-      mlx5_esw_vport_debugfs_destroy(esw, vport_num);
+       mlx5_esw_vport_disable(esw, vport_num);
+       return err;
+ }
+@@ -1072,7 +1069,6 @@ err_rep:
+ void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num)
+ {
+       esw_offloads_unload_rep(esw, vport_num);
+-      mlx5_esw_vport_debugfs_destroy(esw, vport_num);
+       mlx5_esw_vport_disable(esw, vport_num);
+ }
+ 
+@@ -1672,7 +1668,6 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
+       dev->priv.eswitch = esw;
+       BLOCKING_INIT_NOTIFIER_HEAD(&esw->n_head);
+ 
+-      esw->dbgfs = debugfs_create_dir("esw", 
mlx5_debugfs_get_dev_root(esw->dev));
+       esw_info(dev,
+                "Total vports %d, per vport: max uc(%d) max mc(%d)\n",
+                esw->total_vports,
+@@ -1696,7 +1691,6 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
+ 
+       esw_info(esw->dev, "cleanup\n");
+ 
+-      debugfs_remove_recursive(esw->dbgfs);
+       esw->dev->priv.eswitch = NULL;
+       destroy_workqueue(esw->work_queue);
+       WARN_ON(refcount_read(&esw->qos.refcnt));
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h 
b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+index c8c12d1672f99..5fd971cee6fdc 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+@@ -195,7 +195,6 @@ struct mlx5_vport {
+       enum mlx5_eswitch_vport_event enabled_events;
+       int index;
+       struct devlink_port *dl_port;
+-      struct dentry *dbgfs;
+ };
+ 
+ struct mlx5_esw_indir_table;
+@@ -342,7 +341,7 @@ struct mlx5_eswitch {
+               u32             large_group_num;
+       }  params;
+       struct blocking_notifier_head n_head;
+-      struct dentry *dbgfs;
++      bool paired[MLX5_MAX_PORTS];
+ };
+ 
+ void esw_offloads_disable(struct mlx5_eswitch *esw);
+@@ -705,9 +704,6 @@ int mlx5_esw_offloads_devlink_port_register(struct 
mlx5_eswitch *esw, u16 vport_
+ void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, u16 
vport_num);
+ struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, 
u16 vport_num);
+ 
+-void mlx5_esw_vport_debugfs_create(struct mlx5_eswitch *esw, u16 vport_num, 
bool is_sf, u16 sf_num);
+-void mlx5_esw_vport_debugfs_destroy(struct mlx5_eswitch *esw, u16 vport_num);
+-
+ int mlx5_esw_devlink_sf_port_register(struct mlx5_eswitch *esw, struct 
devlink_port *dl_port,
+                                     u16 vport_num, u32 controller, u32 sfnum);
+ void mlx5_esw_devlink_sf_port_unregister(struct mlx5_eswitch *esw, u16 
vport_num);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c 
b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+index 590df9bf39a56..a60c9f292e10c 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+@@ -2744,6 +2744,9 @@ static int mlx5_esw_offloads_devcom_event(int event,
+                   mlx5_eswitch_vport_match_metadata_enabled(peer_esw))
+                       break;
+ 
++              if (esw->paired[mlx5_get_dev_index(peer_esw->dev)])
++                      break;
++
+               err = mlx5_esw_offloads_set_ns_peer(esw, peer_esw, true);
+               if (err)
+                       goto err_out;
+@@ -2755,14 +2758,18 @@ static int mlx5_esw_offloads_devcom_event(int event,
+               if (err)
+                       goto err_pair;
+ 
++              esw->paired[mlx5_get_dev_index(peer_esw->dev)] = true;
++              peer_esw->paired[mlx5_get_dev_index(esw->dev)] = true;
+               mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true);
+               break;
+ 
+       case ESW_OFFLOADS_DEVCOM_UNPAIR:
+-              if (!mlx5_devcom_is_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS))
++              if (!esw->paired[mlx5_get_dev_index(peer_esw->dev)])
+                       break;
+ 
+               mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false);
++              esw->paired[mlx5_get_dev_index(peer_esw->dev)] = false;
++              peer_esw->paired[mlx5_get_dev_index(esw->dev)] = false;
+               mlx5_esw_offloads_unpair(peer_esw);
+               mlx5_esw_offloads_unpair(esw);
+               mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false);
+@@ -3777,14 +3784,12 @@ int mlx5_esw_offloads_sf_vport_enable(struct 
mlx5_eswitch *esw, struct devlink_p
+       if (err)
+               goto devlink_err;
+ 
+-      mlx5_esw_vport_debugfs_create(esw, vport_num, true, sfnum);
+       err = mlx5_esw_offloads_rep_load(esw, vport_num);
+       if (err)
+               goto rep_err;
+       return 0;
+ 
+ rep_err:
+-      mlx5_esw_vport_debugfs_destroy(esw, vport_num);
+       mlx5_esw_devlink_sf_port_unregister(esw, vport_num);
+ devlink_err:
+       mlx5_esw_vport_disable(esw, vport_num);
+@@ -3794,7 +3799,6 @@ devlink_err:
+ void mlx5_esw_offloads_sf_vport_disable(struct mlx5_eswitch *esw, u16 
vport_num)
+ {
+       mlx5_esw_offloads_rep_unload(esw, vport_num);
+-      mlx5_esw_vport_debugfs_destroy(esw, vport_num);
+       mlx5_esw_devlink_sf_port_unregister(esw, vport_num);
+       mlx5_esw_vport_disable(esw, vport_num);
+ }
+diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h
+index a50235fdf7d99..055e4ca5b3b5c 100644
+--- a/drivers/net/phy/mscc/mscc.h
++++ b/drivers/net/phy/mscc/mscc.h
+@@ -179,6 +179,7 @@ enum rgmii_clock_delay {
+ #define VSC8502_RGMII_CNTL              20
+ #define VSC8502_RGMII_RX_DELAY_MASK     0x0070
+ #define VSC8502_RGMII_TX_DELAY_MASK     0x0007
++#define VSC8502_RGMII_RX_CLK_DISABLE    0x0800
+ 
+ #define MSCC_PHY_WOL_LOWER_MAC_ADDR     21
+ #define MSCC_PHY_WOL_MID_MAC_ADDR       22
+diff --git a/drivers/net/phy/mscc/mscc_main.c 
b/drivers/net/phy/mscc/mscc_main.c
+index bd81a4b041e52..adc8cd6f2d95a 100644
+--- a/drivers/net/phy/mscc/mscc_main.c
++++ b/drivers/net/phy/mscc/mscc_main.c
+@@ -519,14 +519,27 @@ out_unlock:
+  *  * 2.0 ns (which causes the data to be sampled at exactly half way between
+  *    clock transitions at 1000 Mbps) if delays should be enabled
+  */
+-static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl,
+-                                 u16 rgmii_rx_delay_mask,
+-                                 u16 rgmii_tx_delay_mask)
++static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 
rgmii_cntl,
++                                   u16 rgmii_rx_delay_mask,
++                                   u16 rgmii_tx_delay_mask)
+ {
+       u16 rgmii_rx_delay_pos = ffs(rgmii_rx_delay_mask) - 1;
+       u16 rgmii_tx_delay_pos = ffs(rgmii_tx_delay_mask) - 1;
+       u16 reg_val = 0;
+-      int rc;
++      u16 mask = 0;
++      int rc = 0;
++
++      /* For traffic to pass, the VSC8502 family needs the RX_CLK disable bit
++       * to be unset for all PHY modes, so do that as part of the paged
++       * register modification.
++       * For some family members (like VSC8530/31/40/41) this bit is reserved
++       * and read-only, and the RX clock is enabled by default.
++       */
++      if (rgmii_cntl == VSC8502_RGMII_CNTL)
++              mask |= VSC8502_RGMII_RX_CLK_DISABLE;
++
++      if (phy_interface_is_rgmii(phydev))
++              mask |= rgmii_rx_delay_mask | rgmii_tx_delay_mask;
+ 
+       mutex_lock(&phydev->lock);
+ 
+@@ -537,10 +550,9 @@ static int vsc85xx_rgmii_set_skews(struct phy_device 
*phydev, u32 rgmii_cntl,
+           phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+               reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_tx_delay_pos;
+ 
+-      rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
+-                            rgmii_cntl,
+-                            rgmii_rx_delay_mask | rgmii_tx_delay_mask,
+-                            reg_val);
++      if (mask)
++              rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
++                                    rgmii_cntl, mask, reg_val);
+ 
+       mutex_unlock(&phydev->lock);
+ 
+@@ -549,19 +561,11 @@ static int vsc85xx_rgmii_set_skews(struct phy_device 
*phydev, u32 rgmii_cntl,
+ 
+ static int vsc85xx_default_config(struct phy_device *phydev)
+ {
+-      int rc;
+-
+       phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
+ 
+-      if (phy_interface_mode_is_rgmii(phydev->interface)) {
+-              rc = vsc85xx_rgmii_set_skews(phydev, VSC8502_RGMII_CNTL,
+-                                           VSC8502_RGMII_RX_DELAY_MASK,
+-                                           VSC8502_RGMII_TX_DELAY_MASK);
+-              if (rc)
+-                      return rc;
+-      }
+-
+-      return 0;
++      return vsc85xx_update_rgmii_cntl(phydev, VSC8502_RGMII_CNTL,
++                                       VSC8502_RGMII_RX_DELAY_MASK,
++                                       VSC8502_RGMII_TX_DELAY_MASK);
+ }
+ 
+ static int vsc85xx_get_tunable(struct phy_device *phydev,
+@@ -1758,13 +1762,11 @@ static int vsc8584_config_init(struct phy_device 
*phydev)
+       if (ret)
+               return ret;
+ 
+-      if (phy_interface_is_rgmii(phydev)) {
+-              ret = vsc85xx_rgmii_set_skews(phydev, VSC8572_RGMII_CNTL,
+-                                            VSC8572_RGMII_RX_DELAY_MASK,
+-                                            VSC8572_RGMII_TX_DELAY_MASK);
+-              if (ret)
+-                      return ret;
+-      }
++      ret = vsc85xx_update_rgmii_cntl(phydev, VSC8572_RGMII_CNTL,
++                                      VSC8572_RGMII_RX_DELAY_MASK,
++                                      VSC8572_RGMII_TX_DELAY_MASK);
++      if (ret)
++              return ret;
+ 
+       ret = genphy_soft_reset(phydev);
+       if (ret)
+diff --git a/drivers/platform/x86/amd/pmf/core.c 
b/drivers/platform/x86/amd/pmf/core.c
+index 0acc0b6221290..dc9803e1a4b9b 100644
+--- a/drivers/platform/x86/amd/pmf/core.c
++++ b/drivers/platform/x86/amd/pmf/core.c
+@@ -245,24 +245,29 @@ static const struct pci_device_id pmf_pci_ids[] = {
+       { }
+ };
+ 
+-int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
++static void amd_pmf_set_dram_addr(struct amd_pmf_dev *dev)
+ {
+       u64 phys_addr;
+       u32 hi, low;
+ 
+-      INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics);
++      phys_addr = virt_to_phys(dev->buf);
++      hi = phys_addr >> 32;
++      low = phys_addr & GENMASK(31, 0);
++
++      amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL);
++      amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL);
++}
+ 
++int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
++{
+       /* Get Metrics Table Address */
+       dev->buf = kzalloc(sizeof(dev->m_table), GFP_KERNEL);
+       if (!dev->buf)
+               return -ENOMEM;
+ 
+-      phys_addr = virt_to_phys(dev->buf);
+-      hi = phys_addr >> 32;
+-      low = phys_addr & GENMASK(31, 0);
++      INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics);
+ 
+-      amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL);
+-      amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL);
++      amd_pmf_set_dram_addr(dev);
+ 
+       /*
+        * Start collecting the metrics data after a small delay
+@@ -273,6 +278,18 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev)
+       return 0;
+ }
+ 
++static int amd_pmf_resume_handler(struct device *dev)
++{
++      struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
++
++      if (pdev->buf)
++              amd_pmf_set_dram_addr(pdev);
++
++      return 0;
++}
++
++static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, NULL, amd_pmf_resume_handler);
++
+ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
+ {
+       int ret;
+@@ -414,6 +431,7 @@ static struct platform_driver amd_pmf_driver = {
+               .name = "amd-pmf",
+               .acpi_match_table = amd_pmf_acpi_ids,
+               .dev_groups = amd_pmf_driver_groups,
++              .pm = pm_sleep_ptr(&amd_pmf_pm),
+       },
+       .probe = amd_pmf_probe,
+       .remove = amd_pmf_remove,
+diff --git a/drivers/power/supply/rt9467-charger.c 
b/drivers/power/supply/rt9467-charger.c
+index 73f744a3155d4..ea33693b69779 100644
+--- a/drivers/power/supply/rt9467-charger.c
++++ b/drivers/power/supply/rt9467-charger.c
+@@ -1023,7 +1023,7 @@ static int rt9467_request_interrupt(struct 
rt9467_chg_data *data)
+       for (i = 0; i < num_chg_irqs; i++) {
+               virq = regmap_irq_get_virq(data->irq_chip_data, 
chg_irqs[i].hwirq);
+               if (virq <= 0)
+-                      return dev_err_probe(dev, virq, "Failed to get (%s) 
irq\n",
++                      return dev_err_probe(dev, -EINVAL, "Failed to get (%s) 
irq\n",
+                                            chg_irqs[i].name);
+ 
+               ret = devm_request_threaded_irq(dev, virq, NULL, 
chg_irqs[i].handler,
+diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
+index babb039bcb431..b106faf21a723 100644
+--- a/drivers/spi/spi-geni-qcom.c
++++ b/drivers/spi/spi-geni-qcom.c
+@@ -294,6 +294,8 @@ static void spi_geni_set_cs(struct spi_device *slv, bool 
set_flag)
+       mas->cs_flag = set_flag;
+       /* set xfer_mode to FIFO to complete cs_done in isr */
+       mas->cur_xfer_mode = GENI_SE_FIFO;
++      geni_se_select_mode(se, mas->cur_xfer_mode);
++
+       reinit_completion(&mas->cs_done);
+       if (set_flag)
+               geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0);
+diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
+index 493c31de0edb9..0620dbe5cca0c 100644
+--- a/drivers/vfio/vfio_iommu_type1.c
++++ b/drivers/vfio/vfio_iommu_type1.c
+@@ -860,6 +860,11 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data,
+               if (ret)
+                       goto pin_unwind;
+ 
++              if (!pfn_valid(phys_pfn)) {
++                      ret = -EINVAL;
++                      goto pin_unwind;
++              }
++
+               ret = vfio_add_to_pfn_list(dma, iova, phys_pfn);
+               if (ret) {
+                       if (put_pfn(phys_pfn, dma->prot) && do_accounting)
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index dbcaac8b69665..4a882f9ba1f1f 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -1577,6 +1577,16 @@ static inline void skb_copy_hash(struct sk_buff *to, 
const struct sk_buff *from)
+       to->l4_hash = from->l4_hash;
+ };
+ 
++static inline int skb_cmp_decrypted(const struct sk_buff *skb1,
++                                  const struct sk_buff *skb2)
++{
++#ifdef CONFIG_TLS_DEVICE
++      return skb2->decrypted - skb1->decrypted;
++#else
++      return 0;
++#endif
++}
++
+ static inline void skb_copy_decrypted(struct sk_buff *to,
+                                     const struct sk_buff *from)
+ {
+diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h
+index 84f787416a54d..054d7911bfc9f 100644
+--- a/include/linux/skmsg.h
++++ b/include/linux/skmsg.h
+@@ -71,7 +71,6 @@ struct sk_psock_link {
+ };
+ 
+ struct sk_psock_work_state {
+-      struct sk_buff                  *skb;
+       u32                             len;
+       u32                             off;
+ };
+@@ -105,7 +104,7 @@ struct sk_psock {
+       struct proto                    *sk_proto;
+       struct mutex                    work_mutex;
+       struct sk_psock_work_state      work_state;
+-      struct work_struct              work;
++      struct delayed_work             work;
+       struct rcu_work                 rwork;
+ };
+ 
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index db9f828e9d1ee..76bf0a11bdc77 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -1467,6 +1467,8 @@ static inline void tcp_adjust_rcv_ssthresh(struct sock 
*sk)
+ }
+ 
+ void tcp_cleanup_rbuf(struct sock *sk, int copied);
++void __tcp_cleanup_rbuf(struct sock *sk, int copied);
++
+ 
+ /* We provision sk_rcvbuf around 200% of sk_rcvlowat.
+  * If 87.5 % (7/8) of the space has been consumed, we want to override
+@@ -2323,6 +2325,14 @@ int tcp_bpf_update_proto(struct sock *sk, struct 
sk_psock *psock, bool restore);
+ void tcp_bpf_clone(const struct sock *sk, struct sock *newsk);
+ #endif /* CONFIG_BPF_SYSCALL */
+ 
++#ifdef CONFIG_INET
++void tcp_eat_skb(struct sock *sk, struct sk_buff *skb);
++#else
++static inline void tcp_eat_skb(struct sock *sk, struct sk_buff *skb)
++{
++}
++#endif
++
+ int tcp_bpf_sendmsg_redir(struct sock *sk, bool ingress,
+                         struct sk_msg *msg, u32 bytes, int flags);
+ #endif /* CONFIG_NET_SOCK_MSG */
+diff --git a/include/net/tls.h b/include/net/tls.h
+index 154949c7b0c88..c36bf4c50027e 100644
+--- a/include/net/tls.h
++++ b/include/net/tls.h
+@@ -124,6 +124,7 @@ struct tls_strparser {
+       u32 mark : 8;
+       u32 stopped : 1;
+       u32 copy_mode : 1;
++      u32 mixed_decrypted : 1;
+       u32 msg_ready : 1;
+ 
+       struct strp_msg stm;
+diff --git a/kernel/bpf/offload.c b/kernel/bpf/offload.c
+index 0c85e06f7ea7f..ee146430d9984 100644
+--- a/kernel/bpf/offload.c
++++ b/kernel/bpf/offload.c
+@@ -853,4 +853,4 @@ static int __init bpf_offload_init(void)
+       return rhashtable_init(&offdevs, &offdevs_params);
+ }
+ 
+-late_initcall(bpf_offload_init);
++core_initcall(bpf_offload_init);
+diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
+index f597fe0db9f8f..1d249d839819d 100644
+--- a/net/bluetooth/hci_sock.c
++++ b/net/bluetooth/hci_sock.c
+@@ -987,6 +987,34 @@ static int hci_sock_ioctl(struct socket *sock, unsigned 
int cmd,
+ 
+       BT_DBG("cmd %x arg %lx", cmd, arg);
+ 
++      /* Make sure the cmd is valid before doing anything */
++      switch (cmd) {
++      case HCIGETDEVLIST:
++      case HCIGETDEVINFO:
++      case HCIGETCONNLIST:
++      case HCIDEVUP:
++      case HCIDEVDOWN:
++      case HCIDEVRESET:
++      case HCIDEVRESTAT:
++      case HCISETSCAN:
++      case HCISETAUTH:
++      case HCISETENCRYPT:
++      case HCISETPTYPE:
++      case HCISETLINKPOL:
++      case HCISETLINKMODE:
++      case HCISETACLMTU:
++      case HCISETSCOMTU:
++      case HCIINQUIRY:
++      case HCISETRAW:
++      case HCIGETCONNINFO:
++      case HCIGETAUTHINFO:
++      case HCIBLOCKADDR:
++      case HCIUNBLOCKADDR:
++              break;
++      default:
++              return -ENOIOCTLCMD;
++      }
++
+       lock_sock(sk);
+ 
+       if (hci_pi(sk)->channel != HCI_CHANNEL_RAW) {
+diff --git a/net/core/skmsg.c b/net/core/skmsg.c
+index f81883759d381..a9060e1f0e437 100644
+--- a/net/core/skmsg.c
++++ b/net/core/skmsg.c
+@@ -481,8 +481,6 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock 
*psock, struct msghdr *msg,
+               msg_rx = sk_psock_peek_msg(psock);
+       }
+ out:
+-      if (psock->work_state.skb && copied > 0)
+-              schedule_work(&psock->work);
+       return copied;
+ }
+ EXPORT_SYMBOL_GPL(sk_msg_recvmsg);
+@@ -624,42 +622,33 @@ static int sk_psock_handle_skb(struct sk_psock *psock, 
struct sk_buff *skb,
+ 
+ static void sk_psock_skb_state(struct sk_psock *psock,
+                              struct sk_psock_work_state *state,
+-                             struct sk_buff *skb,
+                              int len, int off)
+ {
+       spin_lock_bh(&psock->ingress_lock);
+       if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) {
+-              state->skb = skb;
+               state->len = len;
+               state->off = off;
+-      } else {
+-              sock_drop(psock->sk, skb);
+       }
+       spin_unlock_bh(&psock->ingress_lock);
+ }
+ 
+ static void sk_psock_backlog(struct work_struct *work)
+ {
+-      struct sk_psock *psock = container_of(work, struct sk_psock, work);
++      struct delayed_work *dwork = to_delayed_work(work);
++      struct sk_psock *psock = container_of(dwork, struct sk_psock, work);
+       struct sk_psock_work_state *state = &psock->work_state;
+       struct sk_buff *skb = NULL;
++      u32 len = 0, off = 0;
+       bool ingress;
+-      u32 len, off;
+       int ret;
+ 
+       mutex_lock(&psock->work_mutex);
+-      if (unlikely(state->skb)) {
+-              spin_lock_bh(&psock->ingress_lock);
+-              skb = state->skb;
++      if (unlikely(state->len)) {
+               len = state->len;
+               off = state->off;
+-              state->skb = NULL;
+-              spin_unlock_bh(&psock->ingress_lock);
+       }
+-      if (skb)
+-              goto start;
+ 
+-      while ((skb = skb_dequeue(&psock->ingress_skb))) {
++      while ((skb = skb_peek(&psock->ingress_skb))) {
+               len = skb->len;
+               off = 0;
+               if (skb_bpf_strparser(skb)) {
+@@ -668,7 +657,6 @@ static void sk_psock_backlog(struct work_struct *work)
+                       off = stm->offset;
+                       len = stm->full_len;
+               }
+-start:
+               ingress = skb_bpf_ingress(skb);
+               skb_bpf_redirect_clear(skb);
+               do {
+@@ -678,22 +666,28 @@ start:
+                                                         len, ingress);
+                       if (ret <= 0) {
+                               if (ret == -EAGAIN) {
+-                                      sk_psock_skb_state(psock, state, skb,
+-                                                         len, off);
++                                      sk_psock_skb_state(psock, state, len, 
off);
++
++                                      /* Delay slightly to prioritize any
++                                       * other work that might be here.
++                                       */
++                                      if (sk_psock_test_state(psock, 
SK_PSOCK_TX_ENABLED))
++                                              
schedule_delayed_work(&psock->work, 1);
+                                       goto end;
+                               }
+                               /* Hard errors break pipe and stop xmit. */
+                               sk_psock_report_error(psock, ret ? -ret : 
EPIPE);
+                               sk_psock_clear_state(psock, 
SK_PSOCK_TX_ENABLED);
+-                              sock_drop(psock->sk, skb);
+                               goto end;
+                       }
+                       off += ret;
+                       len -= ret;
+               } while (len);
+ 
+-              if (!ingress)
++              skb = skb_dequeue(&psock->ingress_skb);
++              if (!ingress) {
+                       kfree_skb(skb);
++              }
+       }
+ end:
+       mutex_unlock(&psock->work_mutex);
+@@ -734,7 +728,7 @@ struct sk_psock *sk_psock_init(struct sock *sk, int node)
+       INIT_LIST_HEAD(&psock->link);
+       spin_lock_init(&psock->link_lock);
+ 
+-      INIT_WORK(&psock->work, sk_psock_backlog);
++      INIT_DELAYED_WORK(&psock->work, sk_psock_backlog);
+       mutex_init(&psock->work_mutex);
+       INIT_LIST_HEAD(&psock->ingress_msg);
+       spin_lock_init(&psock->ingress_lock);
+@@ -786,11 +780,6 @@ static void __sk_psock_zap_ingress(struct sk_psock *psock)
+               skb_bpf_redirect_clear(skb);
+               sock_drop(psock->sk, skb);
+       }
+-      kfree_skb(psock->work_state.skb);
+-      /* We null the skb here to ensure that calls to sk_psock_backlog
+-       * do not pick up the free'd skb.
+-       */
+-      psock->work_state.skb = NULL;
+       __sk_psock_purge_ingress_msg(psock);
+ }
+ 
+@@ -809,7 +798,6 @@ void sk_psock_stop(struct sk_psock *psock)
+       spin_lock_bh(&psock->ingress_lock);
+       sk_psock_clear_state(psock, SK_PSOCK_TX_ENABLED);
+       sk_psock_cork_free(psock);
+-      __sk_psock_zap_ingress(psock);
+       spin_unlock_bh(&psock->ingress_lock);
+ }
+ 
+@@ -823,7 +811,8 @@ static void sk_psock_destroy(struct work_struct *work)
+ 
+       sk_psock_done_strp(psock);
+ 
+-      cancel_work_sync(&psock->work);
++      cancel_delayed_work_sync(&psock->work);
++      __sk_psock_zap_ingress(psock);
+       mutex_destroy(&psock->work_mutex);
+ 
+       psock_progs_drop(&psock->progs);
+@@ -938,7 +927,7 @@ static int sk_psock_skb_redirect(struct sk_psock *from, 
struct sk_buff *skb)
+       }
+ 
+       skb_queue_tail(&psock_other->ingress_skb, skb);
+-      schedule_work(&psock_other->work);
++      schedule_delayed_work(&psock_other->work, 0);
+       spin_unlock_bh(&psock_other->ingress_lock);
+       return 0;
+ }
+@@ -990,10 +979,8 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, 
struct sk_buff *skb,
+               err = -EIO;
+               sk_other = psock->sk;
+               if (sock_flag(sk_other, SOCK_DEAD) ||
+-                  !sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) {
+-                      skb_bpf_redirect_clear(skb);
++                  !sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
+                       goto out_free;
+-              }
+ 
+               skb_bpf_set_ingress(skb);
+ 
+@@ -1018,22 +1005,23 @@ static int sk_psock_verdict_apply(struct sk_psock 
*psock, struct sk_buff *skb,
+                       spin_lock_bh(&psock->ingress_lock);
+                       if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) {
+                               skb_queue_tail(&psock->ingress_skb, skb);
+-                              schedule_work(&psock->work);
++                              schedule_delayed_work(&psock->work, 0);
+                               err = 0;
+                       }
+                       spin_unlock_bh(&psock->ingress_lock);
+-                      if (err < 0) {
+-                              skb_bpf_redirect_clear(skb);
++                      if (err < 0)
+                               goto out_free;
+-                      }
+               }
+               break;
+       case __SK_REDIRECT:
++              tcp_eat_skb(psock->sk, skb);
+               err = sk_psock_skb_redirect(psock, skb);
+               break;
+       case __SK_DROP:
+       default:
+ out_free:
++              skb_bpf_redirect_clear(skb);
++              tcp_eat_skb(psock->sk, skb);
+               sock_drop(psock->sk, skb);
+       }
+ 
+@@ -1049,7 +1037,7 @@ static void sk_psock_write_space(struct sock *sk)
+       psock = sk_psock(sk);
+       if (likely(psock)) {
+               if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
+-                      schedule_work(&psock->work);
++                      schedule_delayed_work(&psock->work, 0);
+               write_space = psock->saved_write_space;
+       }
+       rcu_read_unlock();
+@@ -1078,8 +1066,7 @@ static void sk_psock_strp_read(struct strparser *strp, 
struct sk_buff *skb)
+               skb_dst_drop(skb);
+               skb_bpf_redirect_clear(skb);
+               ret = bpf_prog_run_pin_on_cpu(prog, skb);
+-              if (ret == SK_PASS)
+-                      skb_bpf_set_strparser(skb);
++              skb_bpf_set_strparser(skb);
+               ret = sk_psock_map_verd(ret, skb_bpf_redirect_fetch(skb));
+               skb->sk = NULL;
+       }
+@@ -1183,12 +1170,11 @@ static int sk_psock_verdict_recv(struct sock *sk, 
struct sk_buff *skb)
+       int ret = __SK_DROP;
+       int len = skb->len;
+ 
+-      skb_get(skb);
+-
+       rcu_read_lock();
+       psock = sk_psock(sk);
+       if (unlikely(!psock)) {
+               len = 0;
++              tcp_eat_skb(sk, skb);
+               sock_drop(sk, skb);
+               goto out;
+       }
+@@ -1212,12 +1198,21 @@ out:
+ static void sk_psock_verdict_data_ready(struct sock *sk)
+ {
+       struct socket *sock = sk->sk_socket;
++      int copied;
+ 
+       trace_sk_data_ready(sk);
+ 
+       if (unlikely(!sock || !sock->ops || !sock->ops->read_skb))
+               return;
+-      sock->ops->read_skb(sk, sk_psock_verdict_recv);
++      copied = sock->ops->read_skb(sk, sk_psock_verdict_recv);
++      if (copied >= 0) {
++              struct sk_psock *psock;
++
++              rcu_read_lock();
++              psock = sk_psock(sk);
++              psock->saved_data_ready(sk);
++              rcu_read_unlock();
++      }
+ }
+ 
+ void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock)
+diff --git a/net/core/sock_map.c b/net/core/sock_map.c
+index a055139f410e2..08851511294c0 100644
+--- a/net/core/sock_map.c
++++ b/net/core/sock_map.c
+@@ -1624,9 +1624,10 @@ void sock_map_close(struct sock *sk, long timeout)
+               rcu_read_unlock();
+               sk_psock_stop(psock);
+               release_sock(sk);
+-              cancel_work_sync(&psock->work);
++              cancel_delayed_work_sync(&psock->work);
+               sk_psock_put(sk, psock);
+       }
++
+       /* Make sure we do not recurse. This is a bug.
+        * Leak the socket instead of crashing on a stack overflow.
+        */
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index 6c7c666554ced..ed63ee8f0d7e3 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -1570,7 +1570,7 @@ static int tcp_peek_sndq(struct sock *sk, struct msghdr 
*msg, int len)
+  * calculation of whether or not we must ACK for the sake of
+  * a window update.
+  */
+-static void __tcp_cleanup_rbuf(struct sock *sk, int copied)
++void __tcp_cleanup_rbuf(struct sock *sk, int copied)
+ {
+       struct tcp_sock *tp = tcp_sk(sk);
+       bool time_to_ack = false;
+@@ -1772,7 +1772,6 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t 
recv_actor)
+               WARN_ON_ONCE(!skb_set_owner_sk_safe(skb, sk));
+               tcp_flags = TCP_SKB_CB(skb)->tcp_flags;
+               used = recv_actor(sk, skb);
+-              consume_skb(skb);
+               if (used < 0) {
+                       if (!copied)
+                               copied = used;
+@@ -1786,14 +1785,6 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t 
recv_actor)
+                       break;
+               }
+       }
+-      WRITE_ONCE(tp->copied_seq, seq);
+-
+-      tcp_rcv_space_adjust(sk);
+-
+-      /* Clean up data we have read: This will do ACK frames. */
+-      if (copied > 0)
+-              __tcp_cleanup_rbuf(sk, copied);
+-
+       return copied;
+ }
+ EXPORT_SYMBOL(tcp_read_skb);
+diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
+index 2e9547467edbe..5f93918c063c7 100644
+--- a/net/ipv4/tcp_bpf.c
++++ b/net/ipv4/tcp_bpf.c
+@@ -11,6 +11,24 @@
+ #include <net/inet_common.h>
+ #include <net/tls.h>
+ 
++void tcp_eat_skb(struct sock *sk, struct sk_buff *skb)
++{
++      struct tcp_sock *tcp;
++      int copied;
++
++      if (!skb || !skb->len || !sk_is_tcp(sk))
++              return;
++
++      if (skb_bpf_strparser(skb))
++              return;
++
++      tcp = tcp_sk(sk);
++      copied = tcp->copied_seq + skb->len;
++      WRITE_ONCE(tcp->copied_seq, copied);
++      tcp_rcv_space_adjust(sk);
++      __tcp_cleanup_rbuf(sk, skb->len);
++}
++
+ static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock,
+                          struct sk_msg *msg, u32 apply_bytes, int flags)
+ {
+@@ -174,14 +192,34 @@ static int tcp_msg_wait_data(struct sock *sk, struct 
sk_psock *psock,
+       return ret;
+ }
+ 
++static bool is_next_msg_fin(struct sk_psock *psock)
++{
++      struct scatterlist *sge;
++      struct sk_msg *msg_rx;
++      int i;
++
++      msg_rx = sk_psock_peek_msg(psock);
++      i = msg_rx->sg.start;
++      sge = sk_msg_elem(msg_rx, i);
++      if (!sge->length) {
++              struct sk_buff *skb = msg_rx->skb;
++
++              if (skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
++                      return true;
++      }
++      return false;
++}
++
+ static int tcp_bpf_recvmsg_parser(struct sock *sk,
+                                 struct msghdr *msg,
+                                 size_t len,
+                                 int flags,
+                                 int *addr_len)
+ {
++      struct tcp_sock *tcp = tcp_sk(sk);
++      u32 seq = tcp->copied_seq;
+       struct sk_psock *psock;
+-      int copied;
++      int copied = 0;
+ 
+       if (unlikely(flags & MSG_ERRQUEUE))
+               return inet_recv_error(sk, msg, len, addr_len);
+@@ -194,8 +232,43 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
+               return tcp_recvmsg(sk, msg, len, flags, addr_len);
+ 
+       lock_sock(sk);
++
++      /* We may have received data on the sk_receive_queue pre-accept and
++       * then we can not use read_skb in this context because we haven't
++       * assigned a sk_socket yet so have no link to the ops. The work-around
++       * is to check the sk_receive_queue and in these cases read skbs off
++       * queue again. The read_skb hook is not running at this point because
++       * of lock_sock so we avoid having multiple runners in read_skb.
++       */
++      if (unlikely(!skb_queue_empty(&sk->sk_receive_queue))) {
++              tcp_data_ready(sk);
++              /* This handles the ENOMEM errors if we both receive data
++               * pre accept and are already under memory pressure. At least
++               * let user know to retry.
++               */
++              if (unlikely(!skb_queue_empty(&sk->sk_receive_queue))) {
++                      copied = -EAGAIN;
++                      goto out;
++              }
++      }
++
+ msg_bytes_ready:
+       copied = sk_msg_recvmsg(sk, psock, msg, len, flags);
++      /* The typical case for EFAULT is the socket was gracefully
++       * shutdown with a FIN pkt. So check here the other case is
++       * some error on copy_page_to_iter which would be unexpected.
++       * On fin return correct return code to zero.
++       */
++      if (copied == -EFAULT) {
++              bool is_fin = is_next_msg_fin(psock);
++
++              if (is_fin) {
++                      copied = 0;
++                      seq++;
++                      goto out;
++              }
++      }
++      seq += copied;
+       if (!copied) {
+               long timeo;
+               int data;
+@@ -233,6 +306,10 @@ msg_bytes_ready:
+               copied = -EAGAIN;
+       }
+ out:
++      WRITE_ONCE(tcp->copied_seq, seq);
++      tcp_rcv_space_adjust(sk);
++      if (copied > 0)
++              __tcp_cleanup_rbuf(sk, copied);
+       release_sock(sk);
+       sk_psock_put(sk, psock);
+       return copied;
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index c605d171eb2d9..8aaae82e78aeb 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -1813,7 +1813,7 @@ EXPORT_SYMBOL(__skb_recv_udp);
+ int udp_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
+ {
+       struct sk_buff *skb;
+-      int err, copied;
++      int err;
+ 
+ try_again:
+       skb = skb_recv_udp(sk, MSG_DONTWAIT, &err);
+@@ -1832,10 +1832,7 @@ try_again:
+       }
+ 
+       WARN_ON_ONCE(!skb_set_owner_sk_safe(skb, sk));
+-      copied = recv_actor(sk, skb);
+-      kfree_skb(skb);
+-
+-      return copied;
++      return recv_actor(sk, skb);
+ }
+ EXPORT_SYMBOL(udp_read_skb);
+ 
+diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
+index 6f3b23a6653cc..d40544cd61a6c 100644
+--- a/net/netfilter/nf_conntrack_netlink.c
++++ b/net/netfilter/nf_conntrack_netlink.c
+@@ -1559,9 +1559,6 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] 
= {
+ 
+ static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data)
+ {
+-      if (test_bit(IPS_OFFLOAD_BIT, &ct->status))
+-              return 0;
+-
+       return ctnetlink_filter_match(ct, data);
+ }
+ 
+@@ -1631,11 +1628,6 @@ static int ctnetlink_del_conntrack(struct sk_buff *skb,
+ 
+       ct = nf_ct_tuplehash_to_ctrack(h);
+ 
+-      if (test_bit(IPS_OFFLOAD_BIT, &ct->status)) {
+-              nf_ct_put(ct);
+-              return -EBUSY;
+-      }
+-
+       if (cda[CTA_ID]) {
+               __be32 id = nla_get_be32(cda[CTA_ID]);
+ 
+diff --git a/net/tls/tls.h b/net/tls/tls.h
+index 804c3880d0288..0672acab27731 100644
+--- a/net/tls/tls.h
++++ b/net/tls/tls.h
+@@ -167,6 +167,11 @@ static inline bool tls_strp_msg_ready(struct 
tls_sw_context_rx *ctx)
+       return ctx->strp.msg_ready;
+ }
+ 
++static inline bool tls_strp_msg_mixed_decrypted(struct tls_sw_context_rx *ctx)
++{
++      return ctx->strp.mixed_decrypted;
++}
++
+ #ifdef CONFIG_TLS_DEVICE
+ int tls_device_init(void);
+ void tls_device_cleanup(void);
+diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
+index a7cc4f9faac28..bf69c9d6d06c0 100644
+--- a/net/tls/tls_device.c
++++ b/net/tls/tls_device.c
+@@ -1007,20 +1007,14 @@ int tls_device_decrypted(struct sock *sk, struct 
tls_context *tls_ctx)
+       struct tls_sw_context_rx *sw_ctx = tls_sw_ctx_rx(tls_ctx);
+       struct sk_buff *skb = tls_strp_msg(sw_ctx);
+       struct strp_msg *rxm = strp_msg(skb);
+-      int is_decrypted = skb->decrypted;
+-      int is_encrypted = !is_decrypted;
+-      struct sk_buff *skb_iter;
+-      int left;
+-
+-      left = rxm->full_len - skb->len;
+-      /* Check if all the data is decrypted already */
+-      skb_iter = skb_shinfo(skb)->frag_list;
+-      while (skb_iter && left > 0) {
+-              is_decrypted &= skb_iter->decrypted;
+-              is_encrypted &= !skb_iter->decrypted;
+-
+-              left -= skb_iter->len;
+-              skb_iter = skb_iter->next;
++      int is_decrypted, is_encrypted;
++
++      if (!tls_strp_msg_mixed_decrypted(sw_ctx)) {
++              is_decrypted = skb->decrypted;
++              is_encrypted = !is_decrypted;
++      } else {
++              is_decrypted = 0;
++              is_encrypted = 0;
+       }
+ 
+       trace_tls_device_decrypted(sk, tcp_sk(sk)->copied_seq - rxm->full_len,
+diff --git a/net/tls/tls_strp.c b/net/tls/tls_strp.c
+index 955ac3e0bf4d3..da95abbb7ea32 100644
+--- a/net/tls/tls_strp.c
++++ b/net/tls/tls_strp.c
+@@ -29,34 +29,50 @@ static void tls_strp_anchor_free(struct tls_strparser 
*strp)
+       struct skb_shared_info *shinfo = skb_shinfo(strp->anchor);
+ 
+       DEBUG_NET_WARN_ON_ONCE(atomic_read(&shinfo->dataref) != 1);
+-      shinfo->frag_list = NULL;
++      if (!strp->copy_mode)
++              shinfo->frag_list = NULL;
+       consume_skb(strp->anchor);
+       strp->anchor = NULL;
+ }
+ 
+-/* Create a new skb with the contents of input copied to its page frags */
+-static struct sk_buff *tls_strp_msg_make_copy(struct tls_strparser *strp)
++static struct sk_buff *
++tls_strp_skb_copy(struct tls_strparser *strp, struct sk_buff *in_skb,
++                int offset, int len)
+ {
+-      struct strp_msg *rxm;
+       struct sk_buff *skb;
+-      int i, err, offset;
++      int i, err;
+ 
+-      skb = alloc_skb_with_frags(0, strp->stm.full_len, TLS_PAGE_ORDER,
++      skb = alloc_skb_with_frags(0, len, TLS_PAGE_ORDER,
+                                  &err, strp->sk->sk_allocation);
+       if (!skb)
+               return NULL;
+ 
+-      offset = strp->stm.offset;
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+ 
+-              WARN_ON_ONCE(skb_copy_bits(strp->anchor, offset,
++              WARN_ON_ONCE(skb_copy_bits(in_skb, offset,
+                                          skb_frag_address(frag),
+                                          skb_frag_size(frag)));
+               offset += skb_frag_size(frag);
+       }
+ 
+-      skb_copy_header(skb, strp->anchor);
++      skb->len = len;
++      skb->data_len = len;
++      skb_copy_header(skb, in_skb);
++      return skb;
++}
++
++/* Create a new skb with the contents of input copied to its page frags */
++static struct sk_buff *tls_strp_msg_make_copy(struct tls_strparser *strp)
++{
++      struct strp_msg *rxm;
++      struct sk_buff *skb;
++
++      skb = tls_strp_skb_copy(strp, strp->anchor, strp->stm.offset,
++                              strp->stm.full_len);
++      if (!skb)
++              return NULL;
++
+       rxm = strp_msg(skb);
+       rxm->offset = 0;
+       return skb;
+@@ -180,22 +196,22 @@ static void tls_strp_flush_anchor_copy(struct 
tls_strparser *strp)
+       for (i = 0; i < shinfo->nr_frags; i++)
+               __skb_frag_unref(&shinfo->frags[i], false);
+       shinfo->nr_frags = 0;
++      if (strp->copy_mode) {
++              kfree_skb_list(shinfo->frag_list);
++              shinfo->frag_list = NULL;
++      }
+       strp->copy_mode = 0;
++      strp->mixed_decrypted = 0;
+ }
+ 
+-static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
+-                         unsigned int offset, size_t in_len)
++static int tls_strp_copyin_frag(struct tls_strparser *strp, struct sk_buff 
*skb,
++                              struct sk_buff *in_skb, unsigned int offset,
++                              size_t in_len)
+ {
+-      struct tls_strparser *strp = (struct tls_strparser *)desc->arg.data;
+-      struct sk_buff *skb;
+-      skb_frag_t *frag;
+       size_t len, chunk;
++      skb_frag_t *frag;
+       int sz;
+ 
+-      if (strp->msg_ready)
+-              return 0;
+-
+-      skb = strp->anchor;
+       frag = &skb_shinfo(skb)->frags[skb->len / PAGE_SIZE];
+ 
+       len = in_len;
+@@ -208,19 +224,26 @@ static int tls_strp_copyin(read_descriptor_t *desc, 
struct sk_buff *in_skb,
+                                          skb_frag_size(frag),
+                                          chunk));
+ 
+-              sz = tls_rx_msg_size(strp, strp->anchor);
+-              if (sz < 0) {
+-                      desc->error = sz;
+-                      return 0;
+-              }
+-
+-              /* We may have over-read, sz == 0 is guaranteed under-read */
+-              if (sz > 0)
+-                      chunk = min_t(size_t, chunk, sz - skb->len);
+-
+               skb->len += chunk;
+               skb->data_len += chunk;
+               skb_frag_size_add(frag, chunk);
++
++              sz = tls_rx_msg_size(strp, skb);
++              if (sz < 0)
++                      return sz;
++
++              /* We may have over-read, sz == 0 is guaranteed under-read */
++              if (unlikely(sz && sz < skb->len)) {
++                      int over = skb->len - sz;
++
++                      WARN_ON_ONCE(over > chunk);
++                      skb->len -= over;
++                      skb->data_len -= over;
++                      skb_frag_size_add(frag, -over);
++
++                      chunk -= over;
++              }
++
+               frag++;
+               len -= chunk;
+               offset += chunk;
+@@ -247,15 +270,99 @@ static int tls_strp_copyin(read_descriptor_t *desc, 
struct sk_buff *in_skb,
+               offset += chunk;
+       }
+ 
+-      if (strp->stm.full_len == skb->len) {
++read_done:
++      return in_len - len;
++}
++
++static int tls_strp_copyin_skb(struct tls_strparser *strp, struct sk_buff 
*skb,
++                             struct sk_buff *in_skb, unsigned int offset,
++                             size_t in_len)
++{
++      struct sk_buff *nskb, *first, *last;
++      struct skb_shared_info *shinfo;
++      size_t chunk;
++      int sz;
++
++      if (strp->stm.full_len)
++              chunk = strp->stm.full_len - skb->len;
++      else
++              chunk = TLS_MAX_PAYLOAD_SIZE + PAGE_SIZE;
++      chunk = min(chunk, in_len);
++
++      nskb = tls_strp_skb_copy(strp, in_skb, offset, chunk);
++      if (!nskb)
++              return -ENOMEM;
++
++      shinfo = skb_shinfo(skb);
++      if (!shinfo->frag_list) {
++              shinfo->frag_list = nskb;
++              nskb->prev = nskb;
++      } else {
++              first = shinfo->frag_list;
++              last = first->prev;
++              last->next = nskb;
++              first->prev = nskb;
++      }
++
++      skb->len += chunk;
++      skb->data_len += chunk;
++
++      if (!strp->stm.full_len) {
++              sz = tls_rx_msg_size(strp, skb);
++              if (sz < 0)
++                      return sz;
++
++              /* We may have over-read, sz == 0 is guaranteed under-read */
++              if (unlikely(sz && sz < skb->len)) {
++                      int over = skb->len - sz;
++
++                      WARN_ON_ONCE(over > chunk);
++                      skb->len -= over;
++                      skb->data_len -= over;
++                      __pskb_trim(nskb, nskb->len - over);
++
++                      chunk -= over;
++              }
++
++              strp->stm.full_len = sz;
++      }
++
++      return chunk;
++}
++
++static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
++                         unsigned int offset, size_t in_len)
++{
++      struct tls_strparser *strp = (struct tls_strparser *)desc->arg.data;
++      struct sk_buff *skb;
++      int ret;
++
++      if (strp->msg_ready)
++              return 0;
++
++      skb = strp->anchor;
++      if (!skb->len)
++              skb_copy_decrypted(skb, in_skb);
++      else
++              strp->mixed_decrypted |= !!skb_cmp_decrypted(skb, in_skb);
++
++      if (IS_ENABLED(CONFIG_TLS_DEVICE) && strp->mixed_decrypted)
++              ret = tls_strp_copyin_skb(strp, skb, in_skb, offset, in_len);
++      else
++              ret = tls_strp_copyin_frag(strp, skb, in_skb, offset, in_len);
++      if (ret < 0) {
++              desc->error = ret;
++              ret = 0;
++      }
++
++      if (strp->stm.full_len && strp->stm.full_len == skb->len) {
+               desc->count = 0;
+ 
+               strp->msg_ready = 1;
+               tls_rx_msg_ready(strp);
+       }
+ 
+-read_done:
+-      return in_len - len;
++      return ret;
+ }
+ 
+ static int tls_strp_read_copyin(struct tls_strparser *strp)
+@@ -315,15 +422,19 @@ static int tls_strp_read_copy(struct tls_strparser 
*strp, bool qshort)
+       return 0;
+ }
+ 
+-static bool tls_strp_check_no_dup(struct tls_strparser *strp)
++static bool tls_strp_check_queue_ok(struct tls_strparser *strp)
+ {
+       unsigned int len = strp->stm.offset + strp->stm.full_len;
+-      struct sk_buff *skb;
++      struct sk_buff *first, *skb;
+       u32 seq;
+ 
+-      skb = skb_shinfo(strp->anchor)->frag_list;
+-      seq = TCP_SKB_CB(skb)->seq;
++      first = skb_shinfo(strp->anchor)->frag_list;
++      skb = first;
++      seq = TCP_SKB_CB(first)->seq;
+ 
++      /* Make sure there's no duplicate data in the queue,
++       * and the decrypted status matches.
++       */
+       while (skb->len < len) {
+               seq += skb->len;
+               len -= skb->len;
+@@ -331,6 +442,8 @@ static bool tls_strp_check_no_dup(struct tls_strparser 
*strp)
+ 
+               if (TCP_SKB_CB(skb)->seq != seq)
+                       return false;
++              if (skb_cmp_decrypted(first, skb))
++                      return false;
+       }
+ 
+       return true;
+@@ -411,7 +524,7 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
+                       return tls_strp_read_copy(strp, true);
+       }
+ 
+-      if (!tls_strp_check_no_dup(strp))
++      if (!tls_strp_check_queue_ok(strp))
+               return tls_strp_read_copy(strp, false);
+ 
+       strp->msg_ready = 1;
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index 635b8bf6b937c..6e6a7c37d685c 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -2304,10 +2304,14 @@ static void tls_data_ready(struct sock *sk)
+       struct tls_context *tls_ctx = tls_get_ctx(sk);
+       struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
+       struct sk_psock *psock;
++      gfp_t alloc_save;
+ 
+       trace_sk_data_ready(sk);
+ 
++      alloc_save = sk->sk_allocation;
++      sk->sk_allocation = GFP_ATOMIC;
+       tls_strp_data_ready(&ctx->strp);
++      sk->sk_allocation = alloc_save;
+ 
+       psock = sk_psock_get(sk);
+       if (psock) {
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index 29c6083a37daf..9383afe3e570b 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -2553,7 +2553,7 @@ static int unix_read_skb(struct sock *sk, 
skb_read_actor_t recv_actor)
+ {
+       struct unix_sock *u = unix_sk(sk);
+       struct sk_buff *skb;
+-      int err, copied;
++      int err;
+ 
+       mutex_lock(&u->iolock);
+       skb = skb_recv_datagram(sk, MSG_DONTWAIT, &err);
+@@ -2561,10 +2561,7 @@ static int unix_read_skb(struct sock *sk, 
skb_read_actor_t recv_actor)
+       if (!skb)
+               return err;
+ 
+-      copied = recv_actor(sk, skb);
+-      kfree_skb(skb);
+-
+-      return copied;
++      return recv_actor(sk, skb);
+ }
+ 
+ /*
+diff --git a/sound/soc/intel/avs/control.c b/sound/soc/intel/avs/control.c
+index a8b14b784f8a5..3dfa2e9816db0 100644
+--- a/sound/soc/intel/avs/control.c
++++ b/sound/soc/intel/avs/control.c
+@@ -21,17 +21,25 @@ static struct avs_dev *avs_get_kcontrol_adev(struct 
snd_kcontrol *kcontrol)
+       return to_avs_dev(w->dapm->component->dev);
+ }
+ 
+-static struct avs_path_module *avs_get_kcontrol_module(struct avs_dev *adev, 
u32 id)
++static struct avs_path_module *avs_get_volume_module(struct avs_dev *adev, 
u32 id)
+ {
+       struct avs_path *path;
+       struct avs_path_pipeline *ppl;
+       struct avs_path_module *mod;
+ 
+-      list_for_each_entry(path, &adev->path_list, node)
+-              list_for_each_entry(ppl, &path->ppl_list, node)
+-                      list_for_each_entry(mod, &ppl->mod_list, node)
+-                              if (mod->template->ctl_id && 
mod->template->ctl_id == id)
++      spin_lock(&adev->path_list_lock);
++      list_for_each_entry(path, &adev->path_list, node) {
++              list_for_each_entry(ppl, &path->ppl_list, node) {
++                      list_for_each_entry(mod, &ppl->mod_list, node) {
++                              if (guid_equal(&mod->template->cfg_ext->type, 
&AVS_PEAKVOL_MOD_UUID)
++                                  && mod->template->ctl_id == id) {
++                                      spin_unlock(&adev->path_list_lock);
+                                       return mod;
++                              }
++                      }
++              }
++      }
++      spin_unlock(&adev->path_list_lock);
+ 
+       return NULL;
+ }
+@@ -49,7 +57,7 @@ int avs_control_volume_get(struct snd_kcontrol *kcontrol, 
struct snd_ctl_elem_va
+       /* prevent access to modules while path is being constructed */
+       mutex_lock(&adev->path_mutex);
+ 
+-      active_module = avs_get_kcontrol_module(adev, ctl_data->id);
++      active_module = avs_get_volume_module(adev, ctl_data->id);
+       if (active_module) {
+               ret = avs_ipc_peakvol_get_volume(adev, active_module->module_id,
+                                                active_module->instance_id, 
&dspvols,
+@@ -89,7 +97,7 @@ int avs_control_volume_put(struct snd_kcontrol *kcontrol, 
struct snd_ctl_elem_va
+               changed = 1;
+       }
+ 
+-      active_module = avs_get_kcontrol_module(adev, ctl_data->id);
++      active_module = avs_get_volume_module(adev, ctl_data->id);
+       if (active_module) {
+               dspvol.channel_id = AVS_ALL_CHANNELS_MASK;
+               dspvol.target_volume = *volume;
+diff --git a/tools/testing/selftests/bpf/Makefile 
b/tools/testing/selftests/bpf/Makefile
+index b677dcd0b77af..ad01c9e1ff12b 100644
+--- a/tools/testing/selftests/bpf/Makefile
++++ b/tools/testing/selftests/bpf/Makefile
+@@ -197,7 +197,7 @@ $(OUTPUT)/urandom_read: urandom_read.c urandom_read_aux.c 
$(OUTPUT)/liburandom_r
+ 
+ $(OUTPUT)/sign-file: ../../../../scripts/sign-file.c
+       $(call msg,SIGN-FILE,,$@)
+-      $(Q)$(CC) $(shell $(HOSTPKG_CONFIG)--cflags libcrypto 2> /dev/null) \
++      $(Q)$(CC) $(shell $(HOSTPKG_CONFIG) --cflags libcrypto 2> /dev/null) \
+                 $< -o $@ \
+                 $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null || 
echo -lcrypto)
+ 

Reply via email to