commit:     9a0f3f45250e1f141ecebe8d8f3b029bdd106174
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Mon Apr  7 10:30:48 2025 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Mon Apr  7 10:30:48 2025 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=9a0f3f45

Linux patch 6.6.86

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

 0000_README             |   4 +
 1085_linux-6.6.86.patch | 950 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 954 insertions(+)

diff --git a/0000_README b/0000_README
index 93ccd742..01b25ad3 100644
--- a/0000_README
+++ b/0000_README
@@ -383,6 +383,10 @@ Patch:  1084_linux-6.6.85.patch
 From:   https://www.kernel.org
 Desc:   Linux 6.6.85
 
+Patch:  1085_linux-6.6.86.patch
+From:   https://www.kernel.org
+Desc:   Linux 6.6.86
+
 Patch:  1510_fs-enable-link-security-restrictions-by-default.patch
 From:   
http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch
 Desc:   Enable link security restrictions by default.

diff --git a/1085_linux-6.6.86.patch b/1085_linux-6.6.86.patch
new file mode 100644
index 00000000..2139cd2c
--- /dev/null
+++ b/1085_linux-6.6.86.patch
@@ -0,0 +1,950 @@
+diff --git a/Makefile b/Makefile
+index bb3bd3c9072059..2b22872d3cea59 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 6
+-SUBLEVEL = 85
++SUBLEVEL = 86
+ EXTRAVERSION =
+ NAME = Pinguïn Aangedreven
+ 
+diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
+index fef62e4a9edde6..ed1a25f457e48e 100644
+--- a/arch/arm/mm/fault.c
++++ b/arch/arm/mm/fault.c
+@@ -27,6 +27,13 @@
+ 
+ #ifdef CONFIG_MMU
+ 
++bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
++{
++      unsigned long addr = (unsigned long)unsafe_src;
++
++      return addr >= TASK_SIZE && ULONG_MAX - addr >= size;
++}
++
+ /*
+  * This is useful to dump out the page tables associated with
+  * 'addr' in mm 'mm'.
+@@ -556,6 +563,7 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, 
struct pt_regs *regs)
+       if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs))
+               return;
+ 
++      pr_alert("8<--- cut here ---\n");
+       pr_alert("Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n",
+               inf->name, ifsr, addr);
+ 
+diff --git a/drivers/counter/microchip-tcb-capture.c 
b/drivers/counter/microchip-tcb-capture.c
+index b3e615cbd2caa6..461f57f66631c3 100644
+--- a/drivers/counter/microchip-tcb-capture.c
++++ b/drivers/counter/microchip-tcb-capture.c
+@@ -368,6 +368,25 @@ static int mchp_tc_probe(struct platform_device *pdev)
+                       channel);
+       }
+ 
++      /* Disable Quadrature Decoder and position measure */
++      ret = regmap_update_bits(regmap, ATMEL_TC_BMR, ATMEL_TC_QDEN | 
ATMEL_TC_POSEN, 0);
++      if (ret)
++              return ret;
++
++      /* Setup the period capture mode */
++      ret = regmap_update_bits(regmap, ATMEL_TC_REG(priv->channel[0], CMR),
++                               ATMEL_TC_WAVE | ATMEL_TC_ABETRG | 
ATMEL_TC_CMR_MASK |
++                               ATMEL_TC_TCCLKS,
++                               ATMEL_TC_CMR_MASK);
++      if (ret)
++              return ret;
++
++      /* Enable clock and trigger counter */
++      ret = regmap_write(regmap, ATMEL_TC_REG(priv->channel[0], CCR),
++                         ATMEL_TC_CLKEN | ATMEL_TC_SWTRG);
++      if (ret)
++              return ret;
++
+       priv->tc_cfg = tcb_config;
+       priv->regmap = regmap;
+       counter->name = dev_name(&pdev->dev);
+diff --git a/drivers/counter/stm32-lptimer-cnt.c 
b/drivers/counter/stm32-lptimer-cnt.c
+index 8439755559b219..537fe9b669f352 100644
+--- a/drivers/counter/stm32-lptimer-cnt.c
++++ b/drivers/counter/stm32-lptimer-cnt.c
+@@ -58,37 +58,43 @@ static int stm32_lptim_set_enable_state(struct 
stm32_lptim_cnt *priv,
+               return 0;
+       }
+ 
++      ret = clk_enable(priv->clk);
++      if (ret)
++              goto disable_cnt;
++
+       /* LP timer must be enabled before writing CMP & ARR */
+       ret = regmap_write(priv->regmap, STM32_LPTIM_ARR, priv->ceiling);
+       if (ret)
+-              return ret;
++              goto disable_clk;
+ 
+       ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, 0);
+       if (ret)
+-              return ret;
++              goto disable_clk;
+ 
+       /* ensure CMP & ARR registers are properly written */
+       ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val,
+                                      (val & STM32_LPTIM_CMPOK_ARROK) == 
STM32_LPTIM_CMPOK_ARROK,
+                                      100, 1000);
+       if (ret)
+-              return ret;
++              goto disable_clk;
+ 
+       ret = regmap_write(priv->regmap, STM32_LPTIM_ICR,
+                          STM32_LPTIM_CMPOKCF_ARROKCF);
+       if (ret)
+-              return ret;
++              goto disable_clk;
+ 
+-      ret = clk_enable(priv->clk);
+-      if (ret) {
+-              regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
+-              return ret;
+-      }
+       priv->enabled = true;
+ 
+       /* Start LP timer in continuous mode */
+       return regmap_update_bits(priv->regmap, STM32_LPTIM_CR,
+                                 STM32_LPTIM_CNTSTRT, STM32_LPTIM_CNTSTRT);
++
++disable_clk:
++      clk_disable(priv->clk);
++disable_cnt:
++      regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
++
++      return ret;
+ }
+ 
+ static int stm32_lptim_setup(struct stm32_lptim_cnt *priv, int enable)
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 986ee37688c16c..2b7f98a2e36f55 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -2825,8 +2825,7 @@ static int dm_resume(void *handle)
+       struct dm_atomic_state *dm_state = 
to_dm_atomic_state(dm->atomic_obj.state);
+       enum dc_connection_type new_connection_type = dc_connection_none;
+       struct dc_state *dc_state;
+-      int i, r, j, ret;
+-      bool need_hotplug = false;
++      int i, r, j;
+ 
+       if (amdgpu_in_reset(adev)) {
+               dc_state = dm->cached_dc_state;
+@@ -3003,23 +3002,16 @@ static int dm_resume(void *handle)
+                   aconnector->mst_root)
+                       continue;
+ 
+-              ret = drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr, 
true);
+-
+-              if (ret < 0) {
+-                      dm_helpers_dp_mst_stop_top_mgr(aconnector->dc_link->ctx,
+-                                      aconnector->dc_link);
+-                      need_hotplug = true;
+-              }
++              drm_dp_mst_topology_queue_probe(&aconnector->mst_mgr);
+       }
+       drm_connector_list_iter_end(&iter);
+ 
+-      if (need_hotplug)
+-              drm_kms_helper_hotplug_event(ddev);
+-
+       amdgpu_dm_irq_resume_late(adev);
+ 
+       amdgpu_dm_smu_write_watermarks_table(adev);
+ 
++      drm_kms_helper_hotplug_event(ddev);
++
+       return 0;
+ }
+ 
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c 
b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
+index 3f3b555b4523a2..597fa0364a3a9b 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
+@@ -1753,7 +1753,7 @@ static int dcn315_populate_dml_pipes_from_context(
+                               bool split_required = 
pipe->stream->timing.pix_clk_100hz >= 
dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc)
+                                               || (pipe->plane_state && 
pipe->plane_state->src_rect.width > 5120);
+ 
+-                              if (remaining_det_segs > MIN_RESERVED_DET_SEGS)
++                              if (remaining_det_segs > MIN_RESERVED_DET_SEGS 
&& crb_pipes != 0)
+                                       
pipes[pipe_cnt].pipe.src.det_size_override += (remaining_det_segs - 
MIN_RESERVED_DET_SEGS) / crb_pipes +
+                                                       (crb_idx < 
(remaining_det_segs - MIN_RESERVED_DET_SEGS) % crb_pipes ? 1 : 0);
+                               if (pipes[pipe_cnt].pipe.src.det_size_override 
> 2 * DCN3_15_MAX_DET_SEGS) {
+diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
+index 08f8a22431fe1f..71a30387ca125b 100644
+--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
++++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
+@@ -2692,6 +2692,11 @@ static void drm_dp_mst_link_probe_work(struct 
work_struct *work)
+               drm_kms_helper_hotplug_event(dev);
+ }
+ 
++static void drm_dp_mst_queue_probe_work(struct drm_dp_mst_topology_mgr *mgr)
++{
++      queue_work(system_long_wq, &mgr->work);
++}
++
+ static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
+                                u8 *guid)
+ {
+@@ -3643,7 +3648,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct 
drm_dp_mst_topology_mgr *mgr, bool ms
+               /* Write reset payload */
+               drm_dp_dpcd_write_payload(mgr, 0, 0, 0x3f);
+ 
+-              queue_work(system_long_wq, &mgr->work);
++              drm_dp_mst_queue_probe_work(mgr);
+ 
+               ret = 0;
+       } else {
+@@ -3680,6 +3685,33 @@ drm_dp_mst_topology_mgr_invalidate_mstb(struct 
drm_dp_mst_branch *mstb)
+                       drm_dp_mst_topology_mgr_invalidate_mstb(port->mstb);
+ }
+ 
++/**
++ * drm_dp_mst_topology_queue_probe - Queue a topology probe
++ * @mgr: manager to probe
++ *
++ * Queue a work to probe the MST topology. Driver's should call this only to
++ * sync the topology's HW->SW state after the MST link's parameters have
++ * changed in a way the state could've become out-of-sync. This is the case
++ * for instance when the link rate between the source and first downstream
++ * branch device has switched between UHBR and non-UHBR rates. Except of those
++ * cases - for instance when a sink gets plugged/unplugged to a port - the SW
++ * state will get updated automatically via MST UP message notifications.
++ */
++void drm_dp_mst_topology_queue_probe(struct drm_dp_mst_topology_mgr *mgr)
++{
++      mutex_lock(&mgr->lock);
++
++      if (drm_WARN_ON(mgr->dev, !mgr->mst_state || !mgr->mst_primary))
++              goto out_unlock;
++
++      drm_dp_mst_topology_mgr_invalidate_mstb(mgr->mst_primary);
++      drm_dp_mst_queue_probe_work(mgr);
++
++out_unlock:
++      mutex_unlock(&mgr->lock);
++}
++EXPORT_SYMBOL(drm_dp_mst_topology_queue_probe);
++
+ /**
+  * drm_dp_mst_topology_mgr_suspend() - suspend the MST manager
+  * @mgr: manager to suspend
+@@ -3766,7 +3798,7 @@ int drm_dp_mst_topology_mgr_resume(struct 
drm_dp_mst_topology_mgr *mgr,
+        * state of our in-memory topology back into sync with reality. So,
+        * restart the probing process as if we're probing a new hub
+        */
+-      queue_work(system_long_wq, &mgr->work);
++      drm_dp_mst_queue_probe_work(mgr);
+       mutex_unlock(&mgr->lock);
+ 
+       if (sync) {
+diff --git a/drivers/hid/hid-plantronics.c b/drivers/hid/hid-plantronics.c
+index 25cfd964dc25d9..acb9eb18f7ccfe 100644
+--- a/drivers/hid/hid-plantronics.c
++++ b/drivers/hid/hid-plantronics.c
+@@ -6,9 +6,6 @@
+  *  Copyright (c) 2015-2018 Terry Junge <[email protected]>
+  */
+ 
+-/*
+- */
+-
+ #include "hid-ids.h"
+ 
+ #include <linux/hid.h>
+@@ -23,30 +20,28 @@
+ 
+ #define PLT_VOL_UP            0x00b1
+ #define PLT_VOL_DOWN          0x00b2
++#define PLT_MIC_MUTE          0x00b5
+ 
+ #define PLT1_VOL_UP           (PLT_HID_1_0_PAGE | PLT_VOL_UP)
+ #define PLT1_VOL_DOWN         (PLT_HID_1_0_PAGE | PLT_VOL_DOWN)
++#define PLT1_MIC_MUTE         (PLT_HID_1_0_PAGE | PLT_MIC_MUTE)
+ #define PLT2_VOL_UP           (PLT_HID_2_0_PAGE | PLT_VOL_UP)
+ #define PLT2_VOL_DOWN         (PLT_HID_2_0_PAGE | PLT_VOL_DOWN)
++#define PLT2_MIC_MUTE         (PLT_HID_2_0_PAGE | PLT_MIC_MUTE)
++#define HID_TELEPHONY_MUTE    (HID_UP_TELEPHONY | 0x2f)
++#define HID_CONSUMER_MUTE     (HID_UP_CONSUMER | 0xe2)
+ 
+ #define PLT_DA60              0xda60
+ #define PLT_BT300_MIN         0x0413
+ #define PLT_BT300_MAX         0x0418
+ 
+-
+-#define PLT_ALLOW_CONSUMER (field->application == HID_CP_CONSUMERCONTROL && \
+-                          (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER)
+-
+-#define PLT_QUIRK_DOUBLE_VOLUME_KEYS BIT(0)
+-#define PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS BIT(1)
+-
+ #define PLT_DOUBLE_KEY_TIMEOUT 5 /* ms */
+-#define PLT_FOLLOWED_OPPOSITE_KEY_TIMEOUT 220 /* ms */
+ 
+ struct plt_drv_data {
+       unsigned long device_type;
+-      unsigned long last_volume_key_ts;
+-      u32 quirks;
++      unsigned long last_key_ts;
++      unsigned long double_key_to;
++      __u16 last_key;
+ };
+ 
+ static int plantronics_input_mapping(struct hid_device *hdev,
+@@ -58,34 +53,43 @@ static int plantronics_input_mapping(struct hid_device 
*hdev,
+       unsigned short mapped_key;
+       struct plt_drv_data *drv_data = hid_get_drvdata(hdev);
+       unsigned long plt_type = drv_data->device_type;
++      int allow_mute = usage->hid == HID_TELEPHONY_MUTE;
++      int allow_consumer = field->application == HID_CP_CONSUMERCONTROL &&
++                      (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER &&
++                      usage->hid != HID_CONSUMER_MUTE;
+ 
+       /* special case for PTT products */
+       if (field->application == HID_GD_JOYSTICK)
+               goto defaulted;
+ 
+-      /* handle volume up/down mapping */
+       /* non-standard types or multi-HID interfaces - plt_type is PID */
+       if (!(plt_type & HID_USAGE_PAGE)) {
+               switch (plt_type) {
+               case PLT_DA60:
+-                      if (PLT_ALLOW_CONSUMER)
++                      if (allow_consumer)
+                               goto defaulted;
+-                      goto ignored;
++                      if (usage->hid == HID_CONSUMER_MUTE) {
++                              mapped_key = KEY_MICMUTE;
++                              goto mapped;
++                      }
++                      break;
+               default:
+-                      if (PLT_ALLOW_CONSUMER)
++                      if (allow_consumer || allow_mute)
+                               goto defaulted;
+               }
++              goto ignored;
+       }
+-      /* handle standard types - plt_type is 0xffa0uuuu or 0xffa2uuuu */
+-      /* 'basic telephony compliant' - allow default consumer page map */
+-      else if ((plt_type & HID_USAGE) >= PLT_BASIC_TELEPHONY &&
+-               (plt_type & HID_USAGE) != PLT_BASIC_EXCEPTION) {
+-              if (PLT_ALLOW_CONSUMER)
+-                      goto defaulted;
+-      }
+-      /* not 'basic telephony' - apply legacy mapping */
+-      /* only map if the field is in the device's primary vendor page */
+-      else if (!((field->application ^ plt_type) & HID_USAGE_PAGE)) {
++
++      /* handle standard consumer control mapping */
++      /* and standard telephony mic mute mapping */
++      if (allow_consumer || allow_mute)
++              goto defaulted;
++
++      /* handle vendor unique types - plt_type is 0xffa0uuuu or 0xffa2uuuu */
++      /* if not 'basic telephony compliant' - map vendor unique controls */
++      if (!((plt_type & HID_USAGE) >= PLT_BASIC_TELEPHONY &&
++            (plt_type & HID_USAGE) != PLT_BASIC_EXCEPTION) &&
++            !((field->application ^ plt_type) & HID_USAGE_PAGE))
+               switch (usage->hid) {
+               case PLT1_VOL_UP:
+               case PLT2_VOL_UP:
+@@ -95,8 +99,11 @@ static int plantronics_input_mapping(struct hid_device 
*hdev,
+               case PLT2_VOL_DOWN:
+                       mapped_key = KEY_VOLUMEDOWN;
+                       goto mapped;
++              case PLT1_MIC_MUTE:
++              case PLT2_MIC_MUTE:
++                      mapped_key = KEY_MICMUTE;
++                      goto mapped;
+               }
+-      }
+ 
+ /*
+  * Future mapping of call control or other usages,
+@@ -105,6 +112,8 @@ static int plantronics_input_mapping(struct hid_device 
*hdev,
+  */
+ 
+ ignored:
++      hid_dbg(hdev, "usage: %08x (appl: %08x) - ignored\n",
++              usage->hid, field->application);
+       return -1;
+ 
+ defaulted:
+@@ -123,38 +132,26 @@ static int plantronics_event(struct hid_device *hdev, 
struct hid_field *field,
+                            struct hid_usage *usage, __s32 value)
+ {
+       struct plt_drv_data *drv_data = hid_get_drvdata(hdev);
++      unsigned long prev_tsto, cur_ts;
++      __u16 prev_key, cur_key;
+ 
+-      if (drv_data->quirks & PLT_QUIRK_DOUBLE_VOLUME_KEYS) {
+-              unsigned long prev_ts, cur_ts;
++      /* Usages are filtered in plantronics_usages. */
+ 
+-              /* Usages are filtered in plantronics_usages. */
++      /* HZ too low for ms resolution - double key detection disabled */
++      /* or it is a key release - handle key presses only. */
++      if (!drv_data->double_key_to || !value)
++              return 0;
+ 
+-              if (!value) /* Handle key presses only. */
+-                      return 0;
++      prev_tsto = drv_data->last_key_ts + drv_data->double_key_to;
++      cur_ts = drv_data->last_key_ts = jiffies;
++      prev_key = drv_data->last_key;
++      cur_key = drv_data->last_key = usage->code;
+ 
+-              prev_ts = drv_data->last_volume_key_ts;
+-              cur_ts = jiffies;
+-              if (jiffies_to_msecs(cur_ts - prev_ts) <= 
PLT_DOUBLE_KEY_TIMEOUT)
+-                      return 1; /* Ignore the repeated key. */
+-
+-              drv_data->last_volume_key_ts = cur_ts;
++      /* If the same key occurs in <= double_key_to -- ignore it */
++      if (prev_key == cur_key && time_before_eq(cur_ts, prev_tsto)) {
++              hid_dbg(hdev, "double key %d ignored\n", cur_key);
++              return 1; /* Ignore the repeated key. */
+       }
+-      if (drv_data->quirks & PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS) {
+-              unsigned long prev_ts, cur_ts;
+-
+-              /* Usages are filtered in plantronics_usages. */
+-
+-              if (!value) /* Handle key presses only. */
+-                      return 0;
+-
+-              prev_ts = drv_data->last_volume_key_ts;
+-              cur_ts = jiffies;
+-              if (jiffies_to_msecs(cur_ts - prev_ts) <= 
PLT_FOLLOWED_OPPOSITE_KEY_TIMEOUT)
+-                      return 1; /* Ignore the followed opposite volume key. */
+-
+-              drv_data->last_volume_key_ts = cur_ts;
+-      }
+-
+       return 0;
+ }
+ 
+@@ -196,12 +193,16 @@ static int plantronics_probe(struct hid_device *hdev,
+       ret = hid_parse(hdev);
+       if (ret) {
+               hid_err(hdev, "parse failed\n");
+-              goto err;
++              return ret;
+       }
+ 
+       drv_data->device_type = plantronics_device_type(hdev);
+-      drv_data->quirks = id->driver_data;
+-      drv_data->last_volume_key_ts = jiffies - 
msecs_to_jiffies(PLT_DOUBLE_KEY_TIMEOUT);
++      drv_data->double_key_to = msecs_to_jiffies(PLT_DOUBLE_KEY_TIMEOUT);
++      drv_data->last_key_ts = jiffies - drv_data->double_key_to;
++
++      /* if HZ does not allow ms resolution - disable double key detection */
++      if (drv_data->double_key_to < PLT_DOUBLE_KEY_TIMEOUT)
++              drv_data->double_key_to = 0;
+ 
+       hid_set_drvdata(hdev, drv_data);
+ 
+@@ -210,29 +211,10 @@ static int plantronics_probe(struct hid_device *hdev,
+       if (ret)
+               hid_err(hdev, "hw start failed\n");
+ 
+-err:
+       return ret;
+ }
+ 
+ static const struct hid_device_id plantronics_devices[] = {
+-      { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
+-                                       
USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3210_SERIES),
+-              .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS },
+-      { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
+-                                       
USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3220_SERIES),
+-              .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS },
+-      { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
+-                                       
USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3215_SERIES),
+-              .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS },
+-      { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
+-                                       
USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3225_SERIES),
+-              .driver_data = PLT_QUIRK_DOUBLE_VOLUME_KEYS },
+-      { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
+-                                       
USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3325_SERIES),
+-              .driver_data = PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS },
+-      { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS,
+-                                       
USB_DEVICE_ID_PLANTRONICS_ENCOREPRO_500_SERIES),
+-              .driver_data = PLT_QUIRK_FOLLOWED_OPPOSITE_VOLUME_KEYS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) },
+       { }
+ };
+@@ -241,6 +223,14 @@ MODULE_DEVICE_TABLE(hid, plantronics_devices);
+ static const struct hid_usage_id plantronics_usages[] = {
+       { HID_CP_VOLUMEUP, EV_KEY, HID_ANY_ID },
+       { HID_CP_VOLUMEDOWN, EV_KEY, HID_ANY_ID },
++      { HID_TELEPHONY_MUTE, EV_KEY, HID_ANY_ID },
++      { HID_CONSUMER_MUTE, EV_KEY, HID_ANY_ID },
++      { PLT2_VOL_UP, EV_KEY, HID_ANY_ID },
++      { PLT2_VOL_DOWN, EV_KEY, HID_ANY_ID },
++      { PLT2_MIC_MUTE, EV_KEY, HID_ANY_ID },
++      { PLT1_VOL_UP, EV_KEY, HID_ANY_ID },
++      { PLT1_VOL_DOWN, EV_KEY, HID_ANY_ID },
++      { PLT1_MIC_MUTE, EV_KEY, HID_ANY_ID },
+       { HID_TERMINATOR, HID_TERMINATOR, HID_TERMINATOR }
+ };
+ 
+diff --git a/drivers/memstick/host/rtsx_usb_ms.c 
b/drivers/memstick/host/rtsx_usb_ms.c
+index 29271ad4728a2f..dec279845a752d 100644
+--- a/drivers/memstick/host/rtsx_usb_ms.c
++++ b/drivers/memstick/host/rtsx_usb_ms.c
+@@ -813,6 +813,7 @@ static int rtsx_usb_ms_drv_remove(struct platform_device 
*pdev)
+ 
+       host->eject = true;
+       cancel_work_sync(&host->handle_req);
++      cancel_delayed_work_sync(&host->poll_card);
+ 
+       mutex_lock(&host->host_mutex);
+       if (host->req) {
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index 8e30df676ededb..dc84d9029c2c79 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -1373,9 +1373,11 @@ static const struct usb_device_id products[] = {
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a0, 0)}, /* Telit FN920C04 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a4, 0)}, /* Telit FN920C04 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a9, 0)}, /* Telit FN920C04 */
++      {QMI_QUIRK_SET_DTR(0x1bc7, 0x10b0, 0)}, /* Telit FE990B */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10c0, 0)}, /* Telit FE910C04 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10c4, 0)}, /* Telit FE910C04 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x10c8, 0)}, /* Telit FE910C04 */
++      {QMI_QUIRK_SET_DTR(0x1bc7, 0x10d0, 0)}, /* Telit FN990B */
+       {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)},    /* Telit ME910 */
+       {QMI_FIXED_INTF(0x1bc7, 0x1101, 3)},    /* Telit ME910 dual modem */
+       {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
+diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
+index 9f66c47dc58bc7..08cbc8e4b361df 100644
+--- a/drivers/net/usb/usbnet.c
++++ b/drivers/net/usb/usbnet.c
+@@ -178,6 +178,17 @@ int usbnet_get_ethernet_addr(struct usbnet *dev, int 
iMACAddress)
+ }
+ EXPORT_SYMBOL_GPL(usbnet_get_ethernet_addr);
+ 
++static bool usbnet_needs_usb_name_format(struct usbnet *dev, struct 
net_device *net)
++{
++      /* Point to point devices which don't have a real MAC address
++       * (or report a fake local one) have historically used the usb%d
++       * naming. Preserve this..
++       */
++      return (dev->driver_info->flags & FLAG_POINTTOPOINT) != 0 &&
++              (is_zero_ether_addr(net->dev_addr) ||
++               is_local_ether_addr(net->dev_addr));
++}
++
+ static void intr_complete (struct urb *urb)
+ {
+       struct usbnet   *dev = urb->context;
+@@ -1766,13 +1777,11 @@ usbnet_probe (struct usb_interface *udev, const struct 
usb_device_id *prod)
+               if (status < 0)
+                       goto out1;
+ 
+-              // heuristic:  "usb%d" for links we know are two-host,
+-              // else "eth%d" when there's reasonable doubt.  userspace
+-              // can rename the link if it knows better.
++              /* heuristic: rename to "eth%d" if we are not sure this link
++               * is two-host (these links keep "usb%d")
++               */
+               if ((dev->driver_info->flags & FLAG_ETHER) != 0 &&
+-                  ((dev->driver_info->flags & FLAG_POINTTOPOINT) == 0 ||
+-                   /* somebody touched it*/
+-                   !is_zero_ether_addr(net->dev_addr)))
++                  !usbnet_needs_usb_name_format(dev, net))
+                       strscpy(net->name, "eth%d", sizeof(net->name));
+               /* WLAN devices should always be named "wlan%d" */
+               if ((dev->driver_info->flags & FLAG_WLAN) != 0)
+diff --git a/drivers/reset/starfive/reset-starfive-jh71x0.c 
b/drivers/reset/starfive/reset-starfive-jh71x0.c
+index 55bbbd2de52cf9..29ce3486752f38 100644
+--- a/drivers/reset/starfive/reset-starfive-jh71x0.c
++++ b/drivers/reset/starfive/reset-starfive-jh71x0.c
+@@ -94,6 +94,9 @@ static int jh71x0_reset_status(struct reset_controller_dev 
*rcdev,
+       void __iomem *reg_status = data->status + offset * sizeof(u32);
+       u32 value = readl(reg_status);
+ 
++      if (!data->asserted)
++              return !(value & mask);
++
+       return !((value ^ data->asserted[offset]) & mask);
+ }
+ 
+diff --git a/drivers/tty/serial/8250/8250_dma.c 
b/drivers/tty/serial/8250/8250_dma.c
+index 7f23037813bc85..62492cf10bc9d4 100644
+--- a/drivers/tty/serial/8250/8250_dma.c
++++ b/drivers/tty/serial/8250/8250_dma.c
+@@ -152,7 +152,7 @@ void serial8250_tx_dma_flush(struct uart_8250_port *p)
+        */
+       dma->tx_size = 0;
+ 
+-      dmaengine_terminate_async(dma->rxchan);
++      dmaengine_terminate_async(dma->txchan);
+ }
+ 
+ int serial8250_rx_dma(struct uart_8250_port *p)
+diff --git a/drivers/tty/serial/8250/8250_pci.c 
b/drivers/tty/serial/8250/8250_pci.c
+index bbd7914ddc9adc..0b38fada414472 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -2576,6 +2576,22 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
+               .init           = pci_oxsemi_tornado_init,
+               .setup          = pci_oxsemi_tornado_setup,
+       },
++      {
++              .vendor         = PCI_VENDOR_ID_INTASHIELD,
++              .device         = 0x4026,
++              .subvendor      = PCI_ANY_ID,
++              .subdevice      = PCI_ANY_ID,
++              .init           = pci_oxsemi_tornado_init,
++              .setup          = pci_oxsemi_tornado_setup,
++      },
++      {
++              .vendor         = PCI_VENDOR_ID_INTASHIELD,
++              .device         = 0x4021,
++              .subvendor      = PCI_ANY_ID,
++              .subdevice      = PCI_ANY_ID,
++              .init           = pci_oxsemi_tornado_init,
++              .setup          = pci_oxsemi_tornado_setup,
++      },
+       {
+               .vendor         = PCI_VENDOR_ID_INTEL,
+               .device         = 0x8811,
+@@ -5107,6 +5123,14 @@ static const struct pci_device_id serial_pci_tbl[] = {
+               PCI_ANY_ID, PCI_ANY_ID,
+               0, 0,
+               pbn_b2_2_115200 },
++      {       PCI_VENDOR_ID_INTASHIELD, 0x0BA2,
++              PCI_ANY_ID, PCI_ANY_ID,
++              0, 0,
++              pbn_b2_2_115200 },
++      {       PCI_VENDOR_ID_INTASHIELD, 0x0BA3,
++              PCI_ANY_ID, PCI_ANY_ID,
++              0, 0,
++              pbn_b2_2_115200 },
+       /*
+        * Brainboxes UC-235/246
+        */
+@@ -5227,6 +5251,14 @@ static const struct pci_device_id serial_pci_tbl[] = {
+               PCI_ANY_ID, PCI_ANY_ID,
+               0, 0,
+               pbn_b2_4_115200 },
++      {       PCI_VENDOR_ID_INTASHIELD, 0x0C42,
++              PCI_ANY_ID, PCI_ANY_ID,
++              0, 0,
++              pbn_b2_4_115200 },
++      {       PCI_VENDOR_ID_INTASHIELD, 0x0C43,
++              PCI_ANY_ID, PCI_ANY_ID,
++              0, 0,
++              pbn_b2_4_115200 },
+       /*
+        * Brainboxes UC-420
+        */
+@@ -5453,6 +5485,20 @@ static const struct pci_device_id serial_pci_tbl[] = {
+               PCI_ANY_ID, PCI_ANY_ID,
+               0, 0,
+               pbn_oxsemi_1_15625000 },
++      /*
++       * Brainboxes XC-235
++       */
++      {       PCI_VENDOR_ID_INTASHIELD, 0x4026,
++              PCI_ANY_ID, PCI_ANY_ID,
++              0, 0,
++              pbn_oxsemi_1_15625000 },
++      /*
++       * Brainboxes XC-475
++       */
++      {       PCI_VENDOR_ID_INTASHIELD, 0x4021,
++              PCI_ANY_ID, PCI_ANY_ID,
++              0, 0,
++              pbn_oxsemi_1_15625000 },
+ 
+       /*
+        * Perle PCI-RAS cards
+diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
+index 8bd0f8e45b146f..70fa1e6aebe136 100644
+--- a/drivers/tty/serial/fsl_lpuart.c
++++ b/drivers/tty/serial/fsl_lpuart.c
+@@ -1488,6 +1488,19 @@ static int lpuart32_config_rs485(struct uart_port 
*port, struct ktermios *termio
+ 
+       unsigned long modem = lpuart32_read(&sport->port, UARTMODIR)
+                               & ~(UARTMODIR_TXRTSPOL | UARTMODIR_TXRTSE);
++      u32 ctrl;
++
++      /* TXRTSE and TXRTSPOL only can be changed when transmitter is 
disabled. */
++      ctrl = lpuart32_read(&sport->port, UARTCTRL);
++      if (ctrl & UARTCTRL_TE) {
++              /* wait for the transmit engine to complete */
++              lpuart32_wait_bit_set(&sport->port, UARTSTAT, UARTSTAT_TC);
++              lpuart32_write(&sport->port, ctrl & ~UARTCTRL_TE, UARTCTRL);
++
++              while (lpuart32_read(&sport->port, UARTCTRL) & UARTCTRL_TE)
++                      cpu_relax();
++      }
++
+       lpuart32_write(&sport->port, modem, UARTMODIR);
+ 
+       if (rs485->flags & SER_RS485_ENABLED) {
+@@ -1507,6 +1520,10 @@ static int lpuart32_config_rs485(struct uart_port 
*port, struct ktermios *termio
+       }
+ 
+       lpuart32_write(&sport->port, modem, UARTMODIR);
++
++      if (ctrl & UARTCTRL_TE)
++              lpuart32_write(&sport->port, ctrl, UARTCTRL);
++
+       return 0;
+ }
+ 
+diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
+index c5a6b133d3643f..51ed40529f9a7b 100644
+--- a/drivers/ufs/host/ufs-qcom.c
++++ b/drivers/ufs/host/ufs-qcom.c
+@@ -1918,10 +1918,12 @@ static int ufs_qcom_probe(struct platform_device *pdev)
+ static int ufs_qcom_remove(struct platform_device *pdev)
+ {
+       struct ufs_hba *hba =  platform_get_drvdata(pdev);
++      struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+ 
+       pm_runtime_get_sync(&(pdev)->dev);
+       ufshcd_remove(hba);
+-      platform_msi_domain_free_irqs(hba->dev);
++      if (host->esi_enabled)
++              platform_msi_domain_free_irqs(hba->dev);
+       return 0;
+ }
+ 
+diff --git a/drivers/usb/gadget/function/uvc_v4l2.c 
b/drivers/usb/gadget/function/uvc_v4l2.c
+index 3f0a9795c0d45d..0195625bef53ab 100644
+--- a/drivers/usb/gadget/function/uvc_v4l2.c
++++ b/drivers/usb/gadget/function/uvc_v4l2.c
+@@ -121,6 +121,9 @@ static struct uvcg_format *find_format_by_pix(struct 
uvc_device *uvc,
+       list_for_each_entry(format, &uvc->header->formats, entry) {
+               const struct uvc_format_desc *fmtdesc = 
to_uvc_format(format->fmt);
+ 
++              if (IS_ERR(fmtdesc))
++                      continue;
++
+               if (fmtdesc->fcc == pixelformat) {
+                       uformat = format->fmt;
+                       break;
+@@ -240,6 +243,7 @@ uvc_v4l2_try_format(struct file *file, void *fh, struct 
v4l2_format *fmt)
+       struct uvc_video *video = &uvc->video;
+       struct uvcg_format *uformat;
+       struct uvcg_frame *uframe;
++      const struct uvc_format_desc *fmtdesc;
+       u8 *fcc;
+ 
+       if (fmt->type != video->queue.queue.type)
+@@ -265,7 +269,10 @@ uvc_v4l2_try_format(struct file *file, void *fh, struct 
v4l2_format *fmt)
+       fmt->fmt.pix.field = V4L2_FIELD_NONE;
+       fmt->fmt.pix.bytesperline = uvc_v4l2_get_bytesperline(uformat, uframe);
+       fmt->fmt.pix.sizeimage = uvc_get_frame_size(uformat, uframe);
+-      fmt->fmt.pix.pixelformat = to_uvc_format(uformat)->fcc;
++      fmtdesc = to_uvc_format(uformat);
++      if (IS_ERR(fmtdesc))
++              return PTR_ERR(fmtdesc);
++      fmt->fmt.pix.pixelformat = fmtdesc->fcc;
+       fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
+       fmt->fmt.pix.priv = 0;
+ 
+@@ -375,6 +382,9 @@ uvc_v4l2_enum_format(struct file *file, void *fh, struct 
v4l2_fmtdesc *f)
+               return -EINVAL;
+ 
+       fmtdesc = to_uvc_format(uformat);
++      if (IS_ERR(fmtdesc))
++              return PTR_ERR(fmtdesc);
++
+       f->pixelformat = fmtdesc->fcc;
+ 
+       return 0;
+diff --git a/include/drm/display/drm_dp_mst_helper.h 
b/include/drm/display/drm_dp_mst_helper.h
+index ab1d73f93408e7..46705dacdd0816 100644
+--- a/include/drm/display/drm_dp_mst_helper.h
++++ b/include/drm/display/drm_dp_mst_helper.h
+@@ -859,6 +859,8 @@ int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr 
*mgr);
+ void drm_dp_mst_dump_topology(struct seq_file *m,
+                             struct drm_dp_mst_topology_mgr *mgr);
+ 
++void drm_dp_mst_topology_queue_probe(struct drm_dp_mst_topology_mgr *mgr);
++
+ void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
+ int __must_check
+ drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr,
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 191f0f95d3edf6..bc62bb2a3b132e 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -6653,7 +6653,7 @@ static bool try_to_accept_memory_one(struct zone *zone)
+ 
+ static bool cond_accept_memory(struct zone *zone, unsigned int order)
+ {
+-      long to_accept;
++      long to_accept, wmark;
+       bool ret = false;
+ 
+       if (!has_unaccepted_memory())
+@@ -6662,8 +6662,18 @@ static bool cond_accept_memory(struct zone *zone, 
unsigned int order)
+       if (list_empty(&zone->unaccepted_pages))
+               return false;
+ 
++      wmark = high_wmark_pages(zone);
++
++      /*
++       * Watermarks have not been initialized yet.
++       *
++       * Accepting one MAX_ORDER page to ensure progress.
++       */
++      if (!wmark)
++              return try_to_accept_memory_one(zone);
++
+       /* How much to accept to get to high watermark? */
+-      to_accept = high_wmark_pages(zone) -
++      to_accept = wmark -
+                   (zone_page_state(zone, NR_FREE_PAGES) -
+                   __zone_watermark_unusable_free(zone, order, 0) -
+                   zone_page_state(zone, NR_UNACCEPTED));
+diff --git a/net/atm/mpc.c b/net/atm/mpc.c
+index 033871e718a34f..583c27131b7d64 100644
+--- a/net/atm/mpc.c
++++ b/net/atm/mpc.c
+@@ -1314,6 +1314,8 @@ static void MPOA_cache_impos_rcvd(struct k_message *msg,
+       holding_time = msg->content.eg_info.holding_time;
+       dprintk("(%s) entry = %p, holding_time = %u\n",
+               mpc->dev->name, entry, holding_time);
++      if (entry == NULL && !holding_time)
++              return;
+       if (entry == NULL && holding_time) {
+               entry = mpc->eg_ops->add_entry(msg, mpc);
+               mpc->eg_ops->put(entry);
+diff --git a/net/ipv6/netfilter/nf_socket_ipv6.c 
b/net/ipv6/netfilter/nf_socket_ipv6.c
+index a7690ec6232596..9ea5ef56cb2704 100644
+--- a/net/ipv6/netfilter/nf_socket_ipv6.c
++++ b/net/ipv6/netfilter/nf_socket_ipv6.c
+@@ -103,6 +103,10 @@ struct sock *nf_sk_lookup_slow_v6(struct net *net, const 
struct sk_buff *skb,
+       struct sk_buff *data_skb = NULL;
+       int doff = 0;
+       int thoff = 0, tproto;
++#if IS_ENABLED(CONFIG_NF_CONNTRACK)
++      enum ip_conntrack_info ctinfo;
++      struct nf_conn const *ct;
++#endif
+ 
+       tproto = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL);
+       if (tproto < 0) {
+@@ -136,6 +140,25 @@ struct sock *nf_sk_lookup_slow_v6(struct net *net, const 
struct sk_buff *skb,
+               return NULL;
+       }
+ 
++#if IS_ENABLED(CONFIG_NF_CONNTRACK)
++      /* Do the lookup with the original socket address in
++       * case this is a reply packet of an established
++       * SNAT-ted connection.
++       */
++      ct = nf_ct_get(skb, &ctinfo);
++      if (ct &&
++          ((tproto != IPPROTO_ICMPV6 &&
++            ctinfo == IP_CT_ESTABLISHED_REPLY) ||
++           (tproto == IPPROTO_ICMPV6 &&
++            ctinfo == IP_CT_RELATED_REPLY)) &&
++          (ct->status & IPS_SRC_NAT_DONE)) {
++              daddr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.in6;
++              dport = (tproto == IPPROTO_TCP) ?
++                      ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.tcp.port :
++                      ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
++      }
++#endif
++
+       return nf_socket_get_sock_v6(net, data_skb, doff, tproto, saddr, daddr,
+                                    sport, dport, indev);
+ }
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 1fd6e84b0e3718..b3cd6090f46aad 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -10023,6 +10023,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x103c, 0x8811, "HP Spectre x360 15-eb1xxx", 
ALC285_FIXUP_HP_SPECTRE_X360_EB1),
+       SND_PCI_QUIRK(0x103c, 0x8812, "HP Spectre x360 15-eb1xxx", 
ALC285_FIXUP_HP_SPECTRE_X360_EB1),
+       SND_PCI_QUIRK(0x103c, 0x881d, "HP 250 G8 Notebook PC", 
ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
++      SND_PCI_QUIRK(0x103c, 0x881e, "HP Laptop 15s-du3xxx", 
ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
+       SND_PCI_QUIRK(0x103c, 0x8846, "HP EliteBook 850 G8 Notebook PC", 
ALC285_FIXUP_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x8847, "HP EliteBook x360 830 G8 Notebook PC", 
ALC285_FIXUP_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x884b, "HP EliteBook 840 Aero G8 Notebook PC", 
ALC285_FIXUP_HP_GPIO_LED),
+diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
+index 06965da51dd083..be0b3c8ac7055b 100644
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -3575,6 +3575,52 @@ static void snd_dragonfly_quirk_db_scale(struct 
usb_mixer_interface *mixer,
+       }
+ }
+ 
++/*
++ * Some Plantronics headsets have control names that don't meet ALSA naming
++ * standards. This function fixes nonstandard source names. By the time
++ * this function is called the control name should look like one of these:
++ * "source names Playback Volume"
++ * "source names Playback Switch"
++ * "source names Capture Volume"
++ * "source names Capture Switch"
++ * If any of the trigger words are found in the name then the name will
++ * be changed to:
++ * "Headset Playback Volume"
++ * "Headset Playback Switch"
++ * "Headset Capture Volume"
++ * "Headset Capture Switch"
++ * depending on the current suffix.
++ */
++static void snd_fix_plt_name(struct snd_usb_audio *chip,
++                           struct snd_ctl_elem_id *id)
++{
++      /* no variant of "Sidetone" should be added to this list */
++      static const char * const trigger[] = {
++              "Earphone", "Microphone", "Receive", "Transmit"
++      };
++      static const char * const suffix[] = {
++              " Playback Volume", " Playback Switch",
++              " Capture Volume", " Capture Switch"
++      };
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(trigger); i++)
++              if (strstr(id->name, trigger[i]))
++                      goto triggered;
++      usb_audio_dbg(chip, "no change in %s\n", id->name);
++      return;
++
++triggered:
++      for (i = 0; i < ARRAY_SIZE(suffix); i++)
++              if (strstr(id->name, suffix[i])) {
++                      usb_audio_dbg(chip, "fixing kctl name %s\n", id->name);
++                      snprintf(id->name, sizeof(id->name), "Headset%s",
++                               suffix[i]);
++                      return;
++              }
++      usb_audio_dbg(chip, "something wrong in kctl name %s\n", id->name);
++}
++
+ void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
+                                 struct usb_mixer_elem_info *cval, int unitid,
+                                 struct snd_kcontrol *kctl)
+@@ -3592,5 +3638,10 @@ void snd_usb_mixer_fu_apply_quirk(struct 
usb_mixer_interface *mixer,
+                       cval->min_mute = 1;
+               break;
+       }
++
++      /* ALSA-ify some Plantronics headset control names */
++      if (USB_ID_VENDOR(mixer->chip->usb_id) == 0x047f &&
++          (cval->control == UAC_FU_MUTE || cval->control == UAC_FU_VOLUME))
++              snd_fix_plt_name(mixer->chip, &kctl->id);
+ }
+ 


Reply via email to