--- /dev/null
+From 1a70dc15594ae20f6c1c5695204457bee4565b90 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 03:03:03 +0930
+Subject: ALSA: scarlett2: Add correct product series name to messages
+
+From: Geoffrey D. Bennett <g@b4.vu>
+
+[ Upstream commit 6e743781d62e28f5fa095e5f31f878819622c143 ]
+
+This driver was originally developed for the Focusrite Scarlett Gen 2
+series, but now also supports the Scarlett Gen 3 series, the
+Clarett 8Pre USB, and the Clarett+ 8Pre. The messages output by the
+driver on initialisation and error include the identifying text
+"Scarlett Gen 2/3", but this is no longer accurate, and writing
+"Scarlett Gen 2/3/Clarett USB/Clarett+" would be unwieldy.
+
+Add series_name field to the scarlett2_device_entry struct so that
+concise and accurate messages can be output.
+
+Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
+Link: https://lore.kernel.org/r/3774b9d35bf1fbdd6fdad9f3f4f97e9b82ac76bf.1694705811.git.g@b4.vu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: b61a3acada00 ("ALSA: scarlett2: Add Focusrite Clarett+ 2Pre and 4Pre support")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/mixer_scarlett_gen2.c | 81 ++++++++++++++++++++++-----------
+ 1 file changed, 54 insertions(+), 27 deletions(-)
+
+diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
+index c53ce9b81a7bb..83df5621c98f5 100644
+--- a/sound/usb/mixer_scarlett_gen2.c
++++ b/sound/usb/mixer_scarlett_gen2.c
+@@ -391,6 +391,7 @@ struct scarlett2_data {
+ struct mutex data_mutex; /* lock access to this data */
+ struct delayed_work work;
+ const struct scarlett2_device_info *info;
++ const char *series_name;
+ __u8 bInterfaceNumber;
+ __u8 bEndpointAddress;
+ __u16 wMaxPacketSize;
+@@ -887,25 +888,26 @@ static const struct scarlett2_device_info clarett_8pre_info = {
+ struct scarlett2_device_entry {
+ const u32 usb_id; /* USB device identifier */
+ const struct scarlett2_device_info *info;
++ const char *series_name;
+ };
+
+ static const struct scarlett2_device_entry scarlett2_devices[] = {
+ /* Supported Gen 2 devices */
+- { USB_ID(0x1235, 0x8203), &s6i6_gen2_info },
+- { USB_ID(0x1235, 0x8204), &s18i8_gen2_info },
+- { USB_ID(0x1235, 0x8201), &s18i20_gen2_info },
++ { USB_ID(0x1235, 0x8203), &s6i6_gen2_info, "Scarlett Gen 2" },
++ { USB_ID(0x1235, 0x8204), &s18i8_gen2_info, "Scarlett Gen 2" },
++ { USB_ID(0x1235, 0x8201), &s18i20_gen2_info, "Scarlett Gen 2" },
+
+ /* Supported Gen 3 devices */
+- { USB_ID(0x1235, 0x8211), &solo_gen3_info },
+- { USB_ID(0x1235, 0x8210), &s2i2_gen3_info },
+- { USB_ID(0x1235, 0x8212), &s4i4_gen3_info },
+- { USB_ID(0x1235, 0x8213), &s8i6_gen3_info },
+- { USB_ID(0x1235, 0x8214), &s18i8_gen3_info },
+- { USB_ID(0x1235, 0x8215), &s18i20_gen3_info },
++ { USB_ID(0x1235, 0x8211), &solo_gen3_info, "Scarlett Gen 3" },
++ { USB_ID(0x1235, 0x8210), &s2i2_gen3_info, "Scarlett Gen 3" },
++ { USB_ID(0x1235, 0x8212), &s4i4_gen3_info, "Scarlett Gen 3" },
++ { USB_ID(0x1235, 0x8213), &s8i6_gen3_info, "Scarlett Gen 3" },
++ { USB_ID(0x1235, 0x8214), &s18i8_gen3_info, "Scarlett Gen 3" },
++ { USB_ID(0x1235, 0x8215), &s18i20_gen3_info, "Scarlett Gen 3" },
+
+ /* Supported Clarett USB/Clarett+ devices */
+- { USB_ID(0x1235, 0x8208), &clarett_8pre_info },
+- { USB_ID(0x1235, 0x820c), &clarett_8pre_info },
++ { USB_ID(0x1235, 0x8208), &clarett_8pre_info, "Clarett USB" },
++ { USB_ID(0x1235, 0x820c), &clarett_8pre_info, "Clarett+" },
+
+ /* End of list */
+ { 0, NULL },
+@@ -1205,8 +1207,8 @@ static int scarlett2_usb(
+ if (err != req_buf_size) {
+ usb_audio_err(
+ mixer->chip,
+- "Scarlett Gen 2/3 USB request result cmd %x was %d\n",
+- cmd, err);
++ "%s USB request result cmd %x was %d\n",
++ private->series_name, cmd, err);
+ err = -EINVAL;
+ goto unlock;
+ }
+@@ -1222,9 +1224,8 @@ static int scarlett2_usb(
+ if (err != resp_buf_size) {
+ usb_audio_err(
+ mixer->chip,
+- "Scarlett Gen 2/3 USB response result cmd %x was %d "
+- "expected %zu\n",
+- cmd, err, resp_buf_size);
++ "%s USB response result cmd %x was %d expected %zu\n",
++ private->series_name, cmd, err, resp_buf_size);
+ err = -EINVAL;
+ goto unlock;
+ }
+@@ -1240,9 +1241,10 @@ static int scarlett2_usb(
+ resp->pad) {
+ usb_audio_err(
+ mixer->chip,
+- "Scarlett Gen 2/3 USB invalid response; "
++ "%s USB invalid response; "
+ "cmd tx/rx %d/%d seq %d/%d size %d/%d "
+ "error %d pad %d\n",
++ private->series_name,
+ le32_to_cpu(req->cmd), le32_to_cpu(resp->cmd),
+ le16_to_cpu(req->seq), le16_to_cpu(resp->seq),
+ resp_size, le16_to_cpu(resp->size),
+@@ -3798,7 +3800,7 @@ static int scarlett2_find_fc_interface(struct usb_device *dev,
+
+ /* Initialise private data */
+ static int scarlett2_init_private(struct usb_mixer_interface *mixer,
+- const struct scarlett2_device_info *info)
++ const struct scarlett2_device_entry *entry)
+ {
+ struct scarlett2_data *private =
+ kzalloc(sizeof(struct scarlett2_data), GFP_KERNEL);
+@@ -3814,7 +3816,8 @@ static int scarlett2_init_private(struct usb_mixer_interface *mixer,
+ mixer->private_free = scarlett2_private_free;
+ mixer->private_suspend = scarlett2_private_suspend;
+
+- private->info = info;
++ private->info = entry->info;
++ private->series_name = entry->series_name;
+ scarlett2_count_mux_io(private);
+ private->scarlett2_seq = 0;
+ private->mixer = mixer;
+@@ -4135,19 +4138,28 @@ static int scarlett2_init_notify(struct usb_mixer_interface *mixer)
+ return usb_submit_urb(mixer->urb, GFP_KERNEL);
+ }
+
+-static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer)
++static const struct scarlett2_device_entry *get_scarlett2_device_entry(
++ struct usb_mixer_interface *mixer)
+ {
+ const struct scarlett2_device_entry *entry = scarlett2_devices;
+- int err;
+
+ /* Find entry in scarlett2_devices */
+ while (entry->usb_id && entry->usb_id != mixer->chip->usb_id)
+ entry++;
+ if (!entry->usb_id)
+- return -EINVAL;
++ return NULL;
++
++ return entry;
++}
++
++static int snd_scarlett_gen2_controls_create(
++ struct usb_mixer_interface *mixer,
++ const struct scarlett2_device_entry *entry)
++{
++ int err;
+
+ /* Initialise private data */
+- err = scarlett2_init_private(mixer, entry->info);
++ err = scarlett2_init_private(mixer, entry);
+ if (err < 0)
+ return err;
+
+@@ -4231,17 +4243,30 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer)
+ int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer)
+ {
+ struct snd_usb_audio *chip = mixer->chip;
++ const struct scarlett2_device_entry *entry;
+ int err;
+
+ /* only use UAC_VERSION_2 */
+ if (!mixer->protocol)
+ return 0;
+
++ /* find entry in scarlett2_devices */
++ entry = get_scarlett2_device_entry(mixer);
++ if (!entry) {
++ usb_audio_err(mixer->chip,
++ "%s: missing device entry for %04x:%04x\n",
++ __func__,
++ USB_ID_VENDOR(chip->usb_id),
++ USB_ID_PRODUCT(chip->usb_id));
++ return 0;
++ }
++
+ if (chip->setup & SCARLETT2_DISABLE) {
+ usb_audio_info(chip,
+- "Focusrite Scarlett Gen 2/3 Mixer Driver disabled "
++ "Focusrite %s Mixer Driver disabled "
+ "by modprobe options (snd_usb_audio "
+ "vid=0x%04x pid=0x%04x device_setup=%d)\n",
++ entry->series_name,
+ USB_ID_VENDOR(chip->usb_id),
+ USB_ID_PRODUCT(chip->usb_id),
+ SCARLETT2_DISABLE);
+@@ -4249,14 +4274,16 @@ int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer)
+ }
+
+ usb_audio_info(chip,
+- "Focusrite Scarlett Gen 2/3 Mixer Driver enabled (pid=0x%04x); "
++ "Focusrite %s Mixer Driver enabled (pid=0x%04x); "
+ "report any issues to g@b4.vu",
++ entry->series_name,
+ USB_ID_PRODUCT(chip->usb_id));
+
+- err = snd_scarlett_gen2_controls_create(mixer);
++ err = snd_scarlett_gen2_controls_create(mixer, entry);
+ if (err < 0)
+ usb_audio_err(mixer->chip,
+- "Error initialising Scarlett Mixer Driver: %d",
++ "Error initialising %s Mixer Driver: %d",
++ entry->series_name,
+ err);
+
+ return err;
+--
+2.43.0
+
--- /dev/null
+From af4a3a3cfe96790e7ada75a3a256d2298502b55f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Sep 2023 01:11:30 +0930
+Subject: ALSA: scarlett2: Add Focusrite Clarett+ 2Pre and 4Pre support
+
+From: Geoffrey D. Bennett <g@b4.vu>
+
+[ Upstream commit b61a3acada0031e7a4922d1340b4296ab95c260b ]
+
+The Focusrite Clarett+ series uses the same protocol as the Scarlett
+Gen 2 and Gen 3 series. This patch adds support for the Clarett+ 2Pre
+and Clarett+ 4Pre similarly to the existing 8Pre support by adding
+appropriate entries to the scarlett2 driver.
+
+The Clarett 2Pre USB and 4Pre USB presumably use the same protocol as
+well, so support for them can easily be added if someone can test.
+
+Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
+Link: https://lore.kernel.org/r/ZRL7qjC3tYQllT3H@m.b4.vu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/mixer_quirks.c | 2 +
+ sound/usb/mixer_scarlett_gen2.c | 97 ++++++++++++++++++++++++++++++++-
+ 2 files changed, 98 insertions(+), 1 deletion(-)
+
+diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
+index b122d7aedb443..3721d59a56809 100644
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -3448,6 +3448,8 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
+ case USB_ID(0x1235, 0x8214): /* Focusrite Scarlett 18i8 3rd Gen */
+ case USB_ID(0x1235, 0x8215): /* Focusrite Scarlett 18i20 3rd Gen */
+ case USB_ID(0x1235, 0x8208): /* Focusrite Clarett 8Pre USB */
++ case USB_ID(0x1235, 0x820a): /* Focusrite Clarett+ 2Pre */
++ case USB_ID(0x1235, 0x820b): /* Focusrite Clarett+ 4Pre */
+ case USB_ID(0x1235, 0x820c): /* Focusrite Clarett+ 8Pre */
+ err = snd_scarlett_gen2_init(mixer);
+ break;
+diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
+index 83df5621c98f5..653dc7d8fb47c 100644
+--- a/sound/usb/mixer_scarlett_gen2.c
++++ b/sound/usb/mixer_scarlett_gen2.c
+@@ -6,7 +6,7 @@
+ * - 6i6/18i8/18i20 Gen 2
+ * - Solo/2i2/4i4/8i6/18i8/18i20 Gen 3
+ * - Clarett 8Pre USB
+- * - Clarett+ 8Pre
++ * - Clarett+ 2Pre/4Pre/8Pre
+ *
+ * Copyright (c) 2018-2023 by Geoffrey D. Bennett <g at b4.vu>
+ * Copyright (c) 2020-2021 by Vladimir Sadovnikov <sadko4u@gmail.com>
+@@ -60,6 +60,10 @@
+ * Support for Clarett 8Pre USB added in Sep 2023 (thanks to Philippe
+ * Perrot for confirmation).
+ *
++ * Support for Clarett+ 4Pre and 2Pre added in Sep 2023 (thanks to
++ * Gregory Rozzo for donating a 4Pre, and David Sherwood and Patrice
++ * Peterson for usbmon output).
++ *
+ * This ALSA mixer gives access to (model-dependent):
+ * - input, output, mixer-matrix muxes
+ * - mixer-matrix gain stages
+@@ -832,6 +836,95 @@ static const struct scarlett2_device_info s18i20_gen3_info = {
+ } },
+ };
+
++static const struct scarlett2_device_info clarett_2pre_info = {
++ .config_set = SCARLETT2_CONFIG_SET_CLARETT,
++ .line_out_hw_vol = 1,
++ .level_input_count = 2,
++ .air_input_count = 2,
++
++ .line_out_descrs = {
++ "Monitor L",
++ "Monitor R",
++ "Headphones L",
++ "Headphones R",
++ },
++
++ .port_count = {
++ [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 },
++ [SCARLETT2_PORT_TYPE_ANALOGUE] = { 2, 4 },
++ [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 0 },
++ [SCARLETT2_PORT_TYPE_ADAT] = { 8, 0 },
++ [SCARLETT2_PORT_TYPE_MIX] = { 10, 18 },
++ [SCARLETT2_PORT_TYPE_PCM] = { 4, 12 },
++ },
++
++ .mux_assignment = { {
++ { SCARLETT2_PORT_TYPE_PCM, 0, 12 },
++ { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 },
++ { SCARLETT2_PORT_TYPE_MIX, 0, 18 },
++ { SCARLETT2_PORT_TYPE_NONE, 0, 8 },
++ { 0, 0, 0 },
++ }, {
++ { SCARLETT2_PORT_TYPE_PCM, 0, 8 },
++ { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 },
++ { SCARLETT2_PORT_TYPE_MIX, 0, 18 },
++ { SCARLETT2_PORT_TYPE_NONE, 0, 8 },
++ { 0, 0, 0 },
++ }, {
++ { SCARLETT2_PORT_TYPE_PCM, 0, 2 },
++ { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 4 },
++ { SCARLETT2_PORT_TYPE_NONE, 0, 26 },
++ { 0, 0, 0 },
++ } },
++};
++
++static const struct scarlett2_device_info clarett_4pre_info = {
++ .config_set = SCARLETT2_CONFIG_SET_CLARETT,
++ .line_out_hw_vol = 1,
++ .level_input_count = 2,
++ .air_input_count = 4,
++
++ .line_out_descrs = {
++ "Monitor L",
++ "Monitor R",
++ "Headphones 1 L",
++ "Headphones 1 R",
++ "Headphones 2 L",
++ "Headphones 2 R",
++ },
++
++ .port_count = {
++ [SCARLETT2_PORT_TYPE_NONE] = { 1, 0 },
++ [SCARLETT2_PORT_TYPE_ANALOGUE] = { 8, 6 },
++ [SCARLETT2_PORT_TYPE_SPDIF] = { 2, 2 },
++ [SCARLETT2_PORT_TYPE_ADAT] = { 8, 0 },
++ [SCARLETT2_PORT_TYPE_MIX] = { 10, 18 },
++ [SCARLETT2_PORT_TYPE_PCM] = { 8, 18 },
++ },
++
++ .mux_assignment = { {
++ { SCARLETT2_PORT_TYPE_PCM, 0, 18 },
++ { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 6 },
++ { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
++ { SCARLETT2_PORT_TYPE_MIX, 0, 18 },
++ { SCARLETT2_PORT_TYPE_NONE, 0, 8 },
++ { 0, 0, 0 },
++ }, {
++ { SCARLETT2_PORT_TYPE_PCM, 0, 14 },
++ { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 6 },
++ { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
++ { SCARLETT2_PORT_TYPE_MIX, 0, 18 },
++ { SCARLETT2_PORT_TYPE_NONE, 0, 8 },
++ { 0, 0, 0 },
++ }, {
++ { SCARLETT2_PORT_TYPE_PCM, 0, 12 },
++ { SCARLETT2_PORT_TYPE_ANALOGUE, 0, 6 },
++ { SCARLETT2_PORT_TYPE_SPDIF, 0, 2 },
++ { SCARLETT2_PORT_TYPE_NONE, 0, 24 },
++ { 0, 0, 0 },
++ } },
++};
++
+ static const struct scarlett2_device_info clarett_8pre_info = {
+ .config_set = SCARLETT2_CONFIG_SET_CLARETT,
+ .line_out_hw_vol = 1,
+@@ -907,6 +1000,8 @@ static const struct scarlett2_device_entry scarlett2_devices[] = {
+
+ /* Supported Clarett USB/Clarett+ devices */
+ { USB_ID(0x1235, 0x8208), &clarett_8pre_info, "Clarett USB" },
++ { USB_ID(0x1235, 0x820a), &clarett_2pre_info, "Clarett+" },
++ { USB_ID(0x1235, 0x820b), &clarett_4pre_info, "Clarett+" },
+ { USB_ID(0x1235, 0x820c), &clarett_8pre_info, "Clarett+" },
+
+ /* End of list */
+--
+2.43.0
+
--- /dev/null
+From 93b953c99a41fb5e9660f50227a2c9def7619ad7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 7 Oct 2023 22:03:04 +1030
+Subject: ALSA: scarlett2: Add Focusrite Clarett 2Pre and 4Pre USB support
+
+From: Geoffrey D. Bennett <g@b4.vu>
+
+[ Upstream commit 2b17b489e47a956c8e93c8f1bcabb0343c851d90 ]
+
+It has been confirmed that all devices in the Focusrite Clarett USB
+series work the same as the devices in the Clarett+ series. Add the
+missing PIDs to enable support for the Clarett 2Pre and 4Pre USB.
+
+Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
+Link: https://lore.kernel.org/r/ZSFB8EVTG1PK1eq/@m.b4.vu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/mixer_quirks.c | 2 ++
+ sound/usb/mixer_scarlett_gen2.c | 8 ++++++--
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
+index 3721d59a56809..a331732fed890 100644
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -3447,6 +3447,8 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
+ case USB_ID(0x1235, 0x8213): /* Focusrite Scarlett 8i6 3rd Gen */
+ case USB_ID(0x1235, 0x8214): /* Focusrite Scarlett 18i8 3rd Gen */
+ case USB_ID(0x1235, 0x8215): /* Focusrite Scarlett 18i20 3rd Gen */
++ case USB_ID(0x1235, 0x8206): /* Focusrite Clarett 2Pre USB */
++ case USB_ID(0x1235, 0x8207): /* Focusrite Clarett 4Pre USB */
+ case USB_ID(0x1235, 0x8208): /* Focusrite Clarett 8Pre USB */
+ case USB_ID(0x1235, 0x820a): /* Focusrite Clarett+ 2Pre */
+ case USB_ID(0x1235, 0x820b): /* Focusrite Clarett+ 4Pre */
+diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
+index 653dc7d8fb47c..e5e70abf5286b 100644
+--- a/sound/usb/mixer_scarlett_gen2.c
++++ b/sound/usb/mixer_scarlett_gen2.c
+@@ -5,7 +5,7 @@
+ * Supported models:
+ * - 6i6/18i8/18i20 Gen 2
+ * - Solo/2i2/4i4/8i6/18i8/18i20 Gen 3
+- * - Clarett 8Pre USB
++ * - Clarett 2Pre/4Pre/8Pre USB
+ * - Clarett+ 2Pre/4Pre/8Pre
+ *
+ * Copyright (c) 2018-2023 by Geoffrey D. Bennett <g at b4.vu>
+@@ -64,6 +64,8 @@
+ * Gregory Rozzo for donating a 4Pre, and David Sherwood and Patrice
+ * Peterson for usbmon output).
+ *
++ * Support for Clarett 2Pre and 4Pre USB added in Oct 2023.
++ *
+ * This ALSA mixer gives access to (model-dependent):
+ * - input, output, mixer-matrix muxes
+ * - mixer-matrix gain stages
+@@ -999,6 +1001,8 @@ static const struct scarlett2_device_entry scarlett2_devices[] = {
+ { USB_ID(0x1235, 0x8215), &s18i20_gen3_info, "Scarlett Gen 3" },
+
+ /* Supported Clarett USB/Clarett+ devices */
++ { USB_ID(0x1235, 0x8206), &clarett_2pre_info, "Clarett USB" },
++ { USB_ID(0x1235, 0x8207), &clarett_4pre_info, "Clarett USB" },
+ { USB_ID(0x1235, 0x8208), &clarett_8pre_info, "Clarett USB" },
+ { USB_ID(0x1235, 0x820a), &clarett_2pre_info, "Clarett+" },
+ { USB_ID(0x1235, 0x820b), &clarett_4pre_info, "Clarett+" },
+@@ -1197,7 +1201,7 @@ static const struct scarlett2_config
+ [SCARLETT2_CONFIG_TALKBACK_MAP] = {
+ .offset = 0xb0, .size = 16, .activate = 10 },
+
+-/* Clarett+ 8Pre */
++/* Clarett USB and Clarett+ devices: 2Pre, 4Pre, 8Pre */
+ }, {
+ [SCARLETT2_CONFIG_DIM_MUTE] = {
+ .offset = 0x31, .size = 8, .activate = 2 },
+--
+2.43.0
+
--- /dev/null
+From bc37874cb1330dfe64ab2dc79d81b303cb0d7203 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 03:02:37 +0930
+Subject: ALSA: scarlett2: Add support for Clarett 8Pre USB
+
+From: Geoffrey D. Bennett <g@b4.vu>
+
+[ Upstream commit b9a98cdd3ac7b80d8ea0f6acd81c88ad3d8bcb4a ]
+
+The Clarett 8Pre USB works the same as the Clarett+ 8Pre, only the USB
+ID is different.
+
+Tested-by: Philippe Perrot <philippe@perrot-net.fr>
+Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
+Link: https://lore.kernel.org/r/e59f47b29e2037f031b56bde10474c6e96e31ba5.1694705811.git.g@b4.vu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/mixer_quirks.c | 1 +
+ sound/usb/mixer_scarlett_gen2.c | 11 ++++++++---
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
+index 1f32e3ae3aa31..b122d7aedb443 100644
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -3447,6 +3447,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
+ case USB_ID(0x1235, 0x8213): /* Focusrite Scarlett 8i6 3rd Gen */
+ case USB_ID(0x1235, 0x8214): /* Focusrite Scarlett 18i8 3rd Gen */
+ case USB_ID(0x1235, 0x8215): /* Focusrite Scarlett 18i20 3rd Gen */
++ case USB_ID(0x1235, 0x8208): /* Focusrite Clarett 8Pre USB */
+ case USB_ID(0x1235, 0x820c): /* Focusrite Clarett+ 8Pre */
+ err = snd_scarlett_gen2_init(mixer);
+ break;
+diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
+index cfb7345ee7a8c..bf3d916d5a13c 100644
+--- a/sound/usb/mixer_scarlett_gen2.c
++++ b/sound/usb/mixer_scarlett_gen2.c
+@@ -1,13 +1,14 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /*
+- * Focusrite Scarlett Gen 2/3 and Clarett+ Driver for ALSA
++ * Focusrite Scarlett Gen 2/3 and Clarett USB/Clarett+ Driver for ALSA
+ *
+ * Supported models:
+ * - 6i6/18i8/18i20 Gen 2
+ * - Solo/2i2/4i4/8i6/18i8/18i20 Gen 3
++ * - Clarett 8Pre USB
+ * - Clarett+ 8Pre
+ *
+- * Copyright (c) 2018-2022 by Geoffrey D. Bennett <g at b4.vu>
++ * Copyright (c) 2018-2023 by Geoffrey D. Bennett <g at b4.vu>
+ * Copyright (c) 2020-2021 by Vladimir Sadovnikov <sadko4u@gmail.com>
+ * Copyright (c) 2022 by Christian Colglazier <christian@cacolglazier.com>
+ *
+@@ -56,6 +57,9 @@
+ * Support for Clarett+ 8Pre added in Aug 2022 by Christian
+ * Colglazier.
+ *
++ * Support for Clarett 8Pre USB added in Sep 2023 (thanks to Philippe
++ * Perrot for confirmation).
++ *
+ * This ALSA mixer gives access to (model-dependent):
+ * - input, output, mixer-matrix muxes
+ * - mixer-matrix gain stages
+@@ -899,7 +903,8 @@ static const struct scarlett2_device_entry scarlett2_devices[] = {
+ { USB_ID(0x1235, 0x8214), &s18i8_gen3_info },
+ { USB_ID(0x1235, 0x8215), &s18i20_gen3_info },
+
+- /* Supported Clarett+ devices */
++ /* Supported Clarett USB/Clarett+ devices */
++ { USB_ID(0x1235, 0x8208), &clarett_8pre_info },
+ { USB_ID(0x1235, 0x820c), &clarett_8pre_info },
+
+ /* End of list */
+--
+2.43.0
+
--- /dev/null
+From d7da5fd48f26e16cf88bbb8f2e9bca23d0d8ade1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 03:01:57 +0930
+Subject: ALSA: scarlett2: Default mixer driver to enabled
+
+From: Geoffrey D. Bennett <g@b4.vu>
+
+[ Upstream commit bc83058f598757a908b30f8f536338cb1478ab5b ]
+
+Early versions of this mixer driver did not work on all hardware, so
+out of caution the driver was disabled by default and had to be
+explicitly enabled with device_setup=1.
+
+Since commit 764fa6e686e0 ("ALSA: usb-audio: scarlett2: Fix device
+hang with ehci-pci") no more problems of this nature have been
+reported. Therefore, enable the driver by default but provide a new
+device_setup option to disable the driver in case that is needed.
+
+- device_setup value of 0 now means "enable" rather than "disable".
+- device_setup value of 1 is now ignored.
+- device_setup value of 4 now means "disable".
+
+Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
+Link: https://lore.kernel.org/r/89600a35b40307f2766578ad1ca2f21801286b58.1694705811.git.g@b4.vu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: b61a3acada00 ("ALSA: scarlett2: Add Focusrite Clarett+ 2Pre and 4Pre support")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/mixer_scarlett_gen2.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
+index bf3d916d5a13c..c53ce9b81a7bb 100644
+--- a/sound/usb/mixer_scarlett_gen2.c
++++ b/sound/usb/mixer_scarlett_gen2.c
+@@ -145,12 +145,12 @@
+
+ #include "mixer_scarlett_gen2.h"
+
+-/* device_setup value to enable */
+-#define SCARLETT2_ENABLE 0x01
+-
+ /* device_setup value to allow turning MSD mode back on */
+ #define SCARLETT2_MSD_ENABLE 0x02
+
++/* device_setup value to disable this mixer driver */
++#define SCARLETT2_DISABLE 0x04
++
+ /* some gui mixers can't handle negative ctl values */
+ #define SCARLETT2_VOLUME_BIAS 127
+
+@@ -4237,19 +4237,20 @@ int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer)
+ if (!mixer->protocol)
+ return 0;
+
+- if (!(chip->setup & SCARLETT2_ENABLE)) {
++ if (chip->setup & SCARLETT2_DISABLE) {
+ usb_audio_info(chip,
+- "Focusrite Scarlett Gen 2/3 Mixer Driver disabled; "
+- "use options snd_usb_audio vid=0x%04x pid=0x%04x "
+- "device_setup=1 to enable and report any issues "
+- "to g@b4.vu",
++ "Focusrite Scarlett Gen 2/3 Mixer Driver disabled "
++ "by modprobe options (snd_usb_audio "
++ "vid=0x%04x pid=0x%04x device_setup=%d)\n",
+ USB_ID_VENDOR(chip->usb_id),
+- USB_ID_PRODUCT(chip->usb_id));
++ USB_ID_PRODUCT(chip->usb_id),
++ SCARLETT2_DISABLE);
+ return 0;
+ }
+
+ usb_audio_info(chip,
+- "Focusrite Scarlett Gen 2/3 Mixer Driver enabled pid=0x%04x",
++ "Focusrite Scarlett Gen 2/3 Mixer Driver enabled (pid=0x%04x); "
++ "report any issues to g@b4.vu",
+ USB_ID_PRODUCT(chip->usb_id));
+
+ err = snd_scarlett_gen2_controls_create(mixer);
+--
+2.43.0
+
--- /dev/null
+From 81d93f4f95db569abab7e9be131cad9419facf17 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 03:02:16 +0930
+Subject: ALSA: scarlett2: Move USB IDs out from device_info struct
+
+From: Geoffrey D. Bennett <g@b4.vu>
+
+[ Upstream commit d98cc489029dba4d99714c2e8ec4f5ba249f6851 ]
+
+By moving the USB IDs from the device_info struct into
+scarlett2_devices[], that will allow for devices with different
+USB IDs to share the same device_info.
+
+Tested-by: Philippe Perrot <philippe@perrot-net.fr>
+Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
+Link: https://lore.kernel.org/r/8263368e8d49e6fcebc709817bd82ab79b404468.1694705811.git.g@b4.vu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: b9a98cdd3ac7 ("ALSA: scarlett2: Add support for Clarett 8Pre USB")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/mixer_scarlett_gen2.c | 63 ++++++++++++---------------------
+ 1 file changed, 23 insertions(+), 40 deletions(-)
+
+diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c
+index c04cff7225411..cfb7345ee7a8c 100644
+--- a/sound/usb/mixer_scarlett_gen2.c
++++ b/sound/usb/mixer_scarlett_gen2.c
+@@ -317,8 +317,6 @@ struct scarlett2_mux_entry {
+ };
+
+ struct scarlett2_device_info {
+- u32 usb_id; /* USB device identifier */
+-
+ /* Gen 3 devices have an internal MSD mode switch that needs
+ * to be disabled in order to access the full functionality of
+ * the device.
+@@ -440,8 +438,6 @@ struct scarlett2_data {
+ /*** Model-specific data ***/
+
+ static const struct scarlett2_device_info s6i6_gen2_info = {
+- .usb_id = USB_ID(0x1235, 0x8203),
+-
+ .config_set = SCARLETT2_CONFIG_SET_GEN_2,
+ .level_input_count = 2,
+ .pad_input_count = 2,
+@@ -486,8 +482,6 @@ static const struct scarlett2_device_info s6i6_gen2_info = {
+ };
+
+ static const struct scarlett2_device_info s18i8_gen2_info = {
+- .usb_id = USB_ID(0x1235, 0x8204),
+-
+ .config_set = SCARLETT2_CONFIG_SET_GEN_2,
+ .level_input_count = 2,
+ .pad_input_count = 4,
+@@ -535,8 +529,6 @@ static const struct scarlett2_device_info s18i8_gen2_info = {
+ };
+
+ static const struct scarlett2_device_info s18i20_gen2_info = {
+- .usb_id = USB_ID(0x1235, 0x8201),
+-
+ .config_set = SCARLETT2_CONFIG_SET_GEN_2,
+ .line_out_hw_vol = 1,
+
+@@ -589,8 +581,6 @@ static const struct scarlett2_device_info s18i20_gen2_info = {
+ };
+
+ static const struct scarlett2_device_info solo_gen3_info = {
+- .usb_id = USB_ID(0x1235, 0x8211),
+-
+ .has_msd_mode = 1,
+ .config_set = SCARLETT2_CONFIG_SET_NO_MIXER,
+ .level_input_count = 1,
+@@ -602,8 +592,6 @@ static const struct scarlett2_device_info solo_gen3_info = {
+ };
+
+ static const struct scarlett2_device_info s2i2_gen3_info = {
+- .usb_id = USB_ID(0x1235, 0x8210),
+-
+ .has_msd_mode = 1,
+ .config_set = SCARLETT2_CONFIG_SET_NO_MIXER,
+ .level_input_count = 2,
+@@ -614,8 +602,6 @@ static const struct scarlett2_device_info s2i2_gen3_info = {
+ };
+
+ static const struct scarlett2_device_info s4i4_gen3_info = {
+- .usb_id = USB_ID(0x1235, 0x8212),
+-
+ .has_msd_mode = 1,
+ .config_set = SCARLETT2_CONFIG_SET_GEN_3,
+ .level_input_count = 2,
+@@ -660,8 +646,6 @@ static const struct scarlett2_device_info s4i4_gen3_info = {
+ };
+
+ static const struct scarlett2_device_info s8i6_gen3_info = {
+- .usb_id = USB_ID(0x1235, 0x8213),
+-
+ .has_msd_mode = 1,
+ .config_set = SCARLETT2_CONFIG_SET_GEN_3,
+ .level_input_count = 2,
+@@ -713,8 +697,6 @@ static const struct scarlett2_device_info s8i6_gen3_info = {
+ };
+
+ static const struct scarlett2_device_info s18i8_gen3_info = {
+- .usb_id = USB_ID(0x1235, 0x8214),
+-
+ .has_msd_mode = 1,
+ .config_set = SCARLETT2_CONFIG_SET_GEN_3,
+ .line_out_hw_vol = 1,
+@@ -783,8 +765,6 @@ static const struct scarlett2_device_info s18i8_gen3_info = {
+ };
+
+ static const struct scarlett2_device_info s18i20_gen3_info = {
+- .usb_id = USB_ID(0x1235, 0x8215),
+-
+ .has_msd_mode = 1,
+ .config_set = SCARLETT2_CONFIG_SET_GEN_3,
+ .line_out_hw_vol = 1,
+@@ -848,8 +828,6 @@ static const struct scarlett2_device_info s18i20_gen3_info = {
+ };
+
+ static const struct scarlett2_device_info clarett_8pre_info = {
+- .usb_id = USB_ID(0x1235, 0x820c),
+-
+ .config_set = SCARLETT2_CONFIG_SET_CLARETT,
+ .line_out_hw_vol = 1,
+ .level_input_count = 2,
+@@ -902,25 +880,30 @@ static const struct scarlett2_device_info clarett_8pre_info = {
+ } },
+ };
+
+-static const struct scarlett2_device_info *scarlett2_devices[] = {
++struct scarlett2_device_entry {
++ const u32 usb_id; /* USB device identifier */
++ const struct scarlett2_device_info *info;
++};
++
++static const struct scarlett2_device_entry scarlett2_devices[] = {
+ /* Supported Gen 2 devices */
+- &s6i6_gen2_info,
+- &s18i8_gen2_info,
+- &s18i20_gen2_info,
++ { USB_ID(0x1235, 0x8203), &s6i6_gen2_info },
++ { USB_ID(0x1235, 0x8204), &s18i8_gen2_info },
++ { USB_ID(0x1235, 0x8201), &s18i20_gen2_info },
+
+ /* Supported Gen 3 devices */
+- &solo_gen3_info,
+- &s2i2_gen3_info,
+- &s4i4_gen3_info,
+- &s8i6_gen3_info,
+- &s18i8_gen3_info,
+- &s18i20_gen3_info,
++ { USB_ID(0x1235, 0x8211), &solo_gen3_info },
++ { USB_ID(0x1235, 0x8210), &s2i2_gen3_info },
++ { USB_ID(0x1235, 0x8212), &s4i4_gen3_info },
++ { USB_ID(0x1235, 0x8213), &s8i6_gen3_info },
++ { USB_ID(0x1235, 0x8214), &s18i8_gen3_info },
++ { USB_ID(0x1235, 0x8215), &s18i20_gen3_info },
+
+ /* Supported Clarett+ devices */
+- &clarett_8pre_info,
++ { USB_ID(0x1235, 0x820c), &clarett_8pre_info },
+
+ /* End of list */
+- NULL
++ { 0, NULL },
+ };
+
+ /* get the starting port index number for a given port type/direction */
+@@ -4149,17 +4132,17 @@ static int scarlett2_init_notify(struct usb_mixer_interface *mixer)
+
+ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer)
+ {
+- const struct scarlett2_device_info **info = scarlett2_devices;
++ const struct scarlett2_device_entry *entry = scarlett2_devices;
+ int err;
+
+- /* Find device in scarlett2_devices */
+- while (*info && (*info)->usb_id != mixer->chip->usb_id)
+- info++;
+- if (!*info)
++ /* Find entry in scarlett2_devices */
++ while (entry->usb_id && entry->usb_id != mixer->chip->usb_id)
++ entry++;
++ if (!entry->usb_id)
+ return -EINVAL;
+
+ /* Initialise private data */
+- err = scarlett2_init_private(mixer, *info);
++ err = scarlett2_init_private(mixer, entry->info);
+ if (err < 0)
+ return err;
+
+--
+2.43.0
+
--- /dev/null
+From 9061ae27fb9689cb6debe89d82ec501d18aededa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Oct 2023 04:31:28 +1030
+Subject: ALSA: scarlett2: Rename scarlett_gen2 to scarlett2
+
+From: Geoffrey D. Bennett <g@b4.vu>
+
+[ Upstream commit efc3d7d20361cc59325a9f0525e079333b4459c0 ]
+
+This driver was originally developed for the Focusrite Scarlett Gen 2
+series. Since then Focusrite have used a similar protocol for their
+Gen 3, Gen 4, Clarett USB, Clarett+, and Vocaster series.
+
+Let's call this common protocol the "Scarlett 2 Protocol" and rename
+the driver to scarlett2 to not imply that it is restricted to Gen 2
+series devices.
+
+Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
+Link: https://lore.kernel.org/r/e1ad7f69a1e20cdb39094164504389160c1a0a0b.1698342632.git.g@b4.vu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ MAINTAINERS | 2 +-
+ sound/usb/Makefile | 2 +-
+ sound/usb/mixer_quirks.c | 4 ++--
+ .../usb/{mixer_scarlett_gen2.c => mixer_scarlett2.c} | 12 +++++++-----
+ sound/usb/mixer_scarlett2.h | 7 +++++++
+ sound/usb/mixer_scarlett_gen2.h | 7 -------
+ 6 files changed, 18 insertions(+), 16 deletions(-)
+ rename sound/usb/{mixer_scarlett_gen2.c => mixer_scarlett2.c} (99%)
+ create mode 100644 sound/usb/mixer_scarlett2.h
+ delete mode 100644 sound/usb/mixer_scarlett_gen2.h
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 40312bb550f06..72a2880afab7a 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -8142,7 +8142,7 @@ M: Geoffrey D. Bennett <g@b4.vu>
+ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
+ S: Maintained
+ T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
+-F: sound/usb/mixer_scarlett_gen2.c
++F: sound/usb/mixer_scarlett2.c
+
+ FORCEDETH GIGABIT ETHERNET DRIVER
+ M: Rain River <rain.1986.08.12@gmail.com>
+diff --git a/sound/usb/Makefile b/sound/usb/Makefile
+index db5ff76d0e61f..8c657c2753c84 100644
+--- a/sound/usb/Makefile
++++ b/sound/usb/Makefile
+@@ -12,7 +12,7 @@ snd-usb-audio-objs := card.o \
+ mixer.o \
+ mixer_quirks.o \
+ mixer_scarlett.o \
+- mixer_scarlett_gen2.o \
++ mixer_scarlett2.o \
+ mixer_us16x08.o \
+ mixer_s1810c.o \
+ pcm.o \
+diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
+index a331732fed890..c8d48566e1759 100644
+--- a/sound/usb/mixer_quirks.c
++++ b/sound/usb/mixer_quirks.c
+@@ -33,7 +33,7 @@
+ #include "mixer.h"
+ #include "mixer_quirks.h"
+ #include "mixer_scarlett.h"
+-#include "mixer_scarlett_gen2.h"
++#include "mixer_scarlett2.h"
+ #include "mixer_us16x08.h"
+ #include "mixer_s1810c.h"
+ #include "helper.h"
+@@ -3453,7 +3453,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
+ case USB_ID(0x1235, 0x820a): /* Focusrite Clarett+ 2Pre */
+ case USB_ID(0x1235, 0x820b): /* Focusrite Clarett+ 4Pre */
+ case USB_ID(0x1235, 0x820c): /* Focusrite Clarett+ 8Pre */
+- err = snd_scarlett_gen2_init(mixer);
++ err = snd_scarlett2_init(mixer);
+ break;
+
+ case USB_ID(0x041e, 0x323b): /* Creative Sound Blaster E1 */
+diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett2.c
+similarity index 99%
+rename from sound/usb/mixer_scarlett_gen2.c
+rename to sound/usb/mixer_scarlett2.c
+index e5e70abf5286b..90480b9b9b089 100644
+--- a/sound/usb/mixer_scarlett_gen2.c
++++ b/sound/usb/mixer_scarlett2.c
+@@ -1,6 +1,8 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /*
+- * Focusrite Scarlett Gen 2/3 and Clarett USB/Clarett+ Driver for ALSA
++ * Focusrite Scarlett 2 Protocol Driver for ALSA
++ * (including Scarlett 2nd Gen, 3rd Gen, Clarett USB, and Clarett+
++ * series products)
+ *
+ * Supported models:
+ * - 6i6/18i8/18i20 Gen 2
+@@ -149,7 +151,7 @@
+ #include "mixer.h"
+ #include "helper.h"
+
+-#include "mixer_scarlett_gen2.h"
++#include "mixer_scarlett2.h"
+
+ /* device_setup value to allow turning MSD mode back on */
+ #define SCARLETT2_MSD_ENABLE 0x02
+@@ -4251,7 +4253,7 @@ static const struct scarlett2_device_entry *get_scarlett2_device_entry(
+ return entry;
+ }
+
+-static int snd_scarlett_gen2_controls_create(
++static int snd_scarlett2_controls_create(
+ struct usb_mixer_interface *mixer,
+ const struct scarlett2_device_entry *entry)
+ {
+@@ -4339,7 +4341,7 @@ static int snd_scarlett_gen2_controls_create(
+ return 0;
+ }
+
+-int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer)
++int snd_scarlett2_init(struct usb_mixer_interface *mixer)
+ {
+ struct snd_usb_audio *chip = mixer->chip;
+ const struct scarlett2_device_entry *entry;
+@@ -4378,7 +4380,7 @@ int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer)
+ entry->series_name,
+ USB_ID_PRODUCT(chip->usb_id));
+
+- err = snd_scarlett_gen2_controls_create(mixer, entry);
++ err = snd_scarlett2_controls_create(mixer, entry);
+ if (err < 0)
+ usb_audio_err(mixer->chip,
+ "Error initialising %s Mixer Driver: %d",
+diff --git a/sound/usb/mixer_scarlett2.h b/sound/usb/mixer_scarlett2.h
+new file mode 100644
+index 0000000000000..d209362cf41a6
+--- /dev/null
++++ b/sound/usb/mixer_scarlett2.h
+@@ -0,0 +1,7 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef __USB_MIXER_SCARLETT2_H
++#define __USB_MIXER_SCARLETT2_H
++
++int snd_scarlett2_init(struct usb_mixer_interface *mixer);
++
++#endif /* __USB_MIXER_SCARLETT2_H */
+diff --git a/sound/usb/mixer_scarlett_gen2.h b/sound/usb/mixer_scarlett_gen2.h
+deleted file mode 100644
+index 668c6b0cb50a6..0000000000000
+--- a/sound/usb/mixer_scarlett_gen2.h
++++ /dev/null
+@@ -1,7 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-#ifndef __USB_MIXER_SCARLETT_GEN2_H
+-#define __USB_MIXER_SCARLETT_GEN2_H
+-
+-int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer);
+-
+-#endif /* __USB_MIXER_SCARLETT_GEN2_H */
+--
+2.43.0
+
--- /dev/null
+From 2d9170f123541e6e41c59b7745442b172d5e6072 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Sep 2023 15:25:32 +0200
+Subject: ASoC: ti: Convert Pandora ASoC to GPIO descriptors
+
+From: Linus Walleij <linus.walleij@linaro.org>
+
+[ Upstream commit 319e6ac143b9e9048e527ab9dd2aabb8fdf3d60f ]
+
+The Pandora uses GPIO descriptors pretty much exclusively, but not
+for ASoC, so let's fix it. Register the pins in a descriptor table
+in the machine since the ASoC device is not using device tree.
+
+Use static locals for the GPIO descriptors because I'm not able
+to experient with better state storage on any real hardware. Others
+using the Pandora can come afterwards and improve this.
+
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Acked-by: Jarkko Nikula <jarkko.nikula@bitmer.com>
+Link: https://lore.kernel.org/r/20230926-descriptors-asoc-ti-v1-4-60cf4f8adbc5@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/mach-omap2/pdata-quirks.c | 10 +++++
+ sound/soc/ti/omap3pandora.c | 63 +++++++++++-------------------
+ 2 files changed, 33 insertions(+), 40 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
+index c1c0121f478d6..b947bacf23a37 100644
+--- a/arch/arm/mach-omap2/pdata-quirks.c
++++ b/arch/arm/mach-omap2/pdata-quirks.c
+@@ -275,9 +275,19 @@ static struct platform_device pandora_backlight = {
+ .id = -1,
+ };
+
++static struct gpiod_lookup_table pandora_soc_audio_gpios = {
++ .dev_id = "soc-audio",
++ .table = {
++ GPIO_LOOKUP("gpio-112-127", 6, "dac", GPIO_ACTIVE_HIGH),
++ GPIO_LOOKUP("gpio-0-15", 14, "amp", GPIO_ACTIVE_HIGH),
++ { }
++ },
++};
++
+ static void __init omap3_pandora_legacy_init(void)
+ {
+ platform_device_register(&pandora_backlight);
++ gpiod_add_lookup_table(&pandora_soc_audio_gpios);
+ }
+ #endif /* CONFIG_ARCH_OMAP3 */
+
+diff --git a/sound/soc/ti/omap3pandora.c b/sound/soc/ti/omap3pandora.c
+index a287e9747c2a1..fa92ed97dfe3b 100644
+--- a/sound/soc/ti/omap3pandora.c
++++ b/sound/soc/ti/omap3pandora.c
+@@ -7,7 +7,7 @@
+
+ #include <linux/clk.h>
+ #include <linux/platform_device.h>
+-#include <linux/gpio.h>
++#include <linux/gpio/consumer.h>
+ #include <linux/delay.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/module.h>
+@@ -21,12 +21,11 @@
+
+ #include "omap-mcbsp.h"
+
+-#define OMAP3_PANDORA_DAC_POWER_GPIO 118
+-#define OMAP3_PANDORA_AMP_POWER_GPIO 14
+-
+ #define PREFIX "ASoC omap3pandora: "
+
+ static struct regulator *omap3pandora_dac_reg;
++static struct gpio_desc *dac_power_gpio;
++static struct gpio_desc *amp_power_gpio;
+
+ static int omap3pandora_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+@@ -78,9 +77,9 @@ static int omap3pandora_dac_event(struct snd_soc_dapm_widget *w,
+ return ret;
+ }
+ mdelay(1);
+- gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1);
++ gpiod_set_value(dac_power_gpio, 1);
+ } else {
+- gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 0);
++ gpiod_set_value(dac_power_gpio, 0);
+ mdelay(1);
+ regulator_disable(omap3pandora_dac_reg);
+ }
+@@ -92,9 +91,9 @@ static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+ {
+ if (SND_SOC_DAPM_EVENT_ON(event))
+- gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 1);
++ gpiod_set_value(amp_power_gpio, 1);
+ else
+- gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 0);
++ gpiod_set_value(amp_power_gpio, 0);
+
+ return 0;
+ }
+@@ -229,35 +228,10 @@ static int __init omap3pandora_soc_init(void)
+
+ pr_info("OMAP3 Pandora SoC init\n");
+
+- ret = gpio_request(OMAP3_PANDORA_DAC_POWER_GPIO, "dac_power");
+- if (ret) {
+- pr_err(PREFIX "Failed to get DAC power GPIO\n");
+- return ret;
+- }
+-
+- ret = gpio_direction_output(OMAP3_PANDORA_DAC_POWER_GPIO, 0);
+- if (ret) {
+- pr_err(PREFIX "Failed to set DAC power GPIO direction\n");
+- goto fail0;
+- }
+-
+- ret = gpio_request(OMAP3_PANDORA_AMP_POWER_GPIO, "amp_power");
+- if (ret) {
+- pr_err(PREFIX "Failed to get amp power GPIO\n");
+- goto fail0;
+- }
+-
+- ret = gpio_direction_output(OMAP3_PANDORA_AMP_POWER_GPIO, 0);
+- if (ret) {
+- pr_err(PREFIX "Failed to set amp power GPIO direction\n");
+- goto fail1;
+- }
+-
+ omap3pandora_snd_device = platform_device_alloc("soc-audio", -1);
+ if (omap3pandora_snd_device == NULL) {
+ pr_err(PREFIX "Platform device allocation failed\n");
+- ret = -ENOMEM;
+- goto fail1;
++ return -ENOMEM;
+ }
+
+ platform_set_drvdata(omap3pandora_snd_device, &snd_soc_card_omap3pandora);
+@@ -268,6 +242,20 @@ static int __init omap3pandora_soc_init(void)
+ goto fail2;
+ }
+
++ dac_power_gpio = devm_gpiod_get(&omap3pandora_snd_device->dev,
++ "dac", GPIOD_OUT_LOW);
++ if (IS_ERR(dac_power_gpio)) {
++ ret = PTR_ERR(dac_power_gpio);
++ goto fail3;
++ }
++
++ amp_power_gpio = devm_gpiod_get(&omap3pandora_snd_device->dev,
++ "amp", GPIOD_OUT_LOW);
++ if (IS_ERR(amp_power_gpio)) {
++ ret = PTR_ERR(amp_power_gpio);
++ goto fail3;
++ }
++
+ omap3pandora_dac_reg = regulator_get(&omap3pandora_snd_device->dev, "vcc");
+ if (IS_ERR(omap3pandora_dac_reg)) {
+ pr_err(PREFIX "Failed to get DAC regulator from %s: %ld\n",
+@@ -283,10 +271,7 @@ static int __init omap3pandora_soc_init(void)
+ platform_device_del(omap3pandora_snd_device);
+ fail2:
+ platform_device_put(omap3pandora_snd_device);
+-fail1:
+- gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO);
+-fail0:
+- gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO);
++
+ return ret;
+ }
+ module_init(omap3pandora_soc_init);
+@@ -295,8 +280,6 @@ static void __exit omap3pandora_soc_exit(void)
+ {
+ regulator_put(omap3pandora_dac_reg);
+ platform_device_unregister(omap3pandora_snd_device);
+- gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO);
+- gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO);
+ }
+ module_exit(omap3pandora_soc_exit);
+
+--
+2.43.0
+
--- /dev/null
+From 3412ba3e03e0c72638d059ea48241fa764ca46e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Mar 2024 11:41:58 -0700
+Subject: clk: Get runtime PM before walking tree during disable_unused
+
+From: Stephen Boyd <sboyd@kernel.org>
+
+[ Upstream commit e581cf5d216289ef292d1a4036d53ce90e122469 ]
+
+Doug reported [1] the following hung task:
+
+ INFO: task swapper/0:1 blocked for more than 122 seconds.
+ Not tainted 5.15.149-21875-gf795ebc40eb8 #1
+ "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+ task:swapper/0 state:D stack: 0 pid: 1 ppid: 0 flags:0x00000008
+ Call trace:
+ __switch_to+0xf4/0x1f4
+ __schedule+0x418/0xb80
+ schedule+0x5c/0x10c
+ rpm_resume+0xe0/0x52c
+ rpm_resume+0x178/0x52c
+ __pm_runtime_resume+0x58/0x98
+ clk_pm_runtime_get+0x30/0xb0
+ clk_disable_unused_subtree+0x58/0x208
+ clk_disable_unused_subtree+0x38/0x208
+ clk_disable_unused_subtree+0x38/0x208
+ clk_disable_unused_subtree+0x38/0x208
+ clk_disable_unused_subtree+0x38/0x208
+ clk_disable_unused+0x4c/0xe4
+ do_one_initcall+0xcc/0x2d8
+ do_initcall_level+0xa4/0x148
+ do_initcalls+0x5c/0x9c
+ do_basic_setup+0x24/0x30
+ kernel_init_freeable+0xec/0x164
+ kernel_init+0x28/0x120
+ ret_from_fork+0x10/0x20
+ INFO: task kworker/u16:0:9 blocked for more than 122 seconds.
+ Not tainted 5.15.149-21875-gf795ebc40eb8 #1
+ "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+ task:kworker/u16:0 state:D stack: 0 pid: 9 ppid: 2 flags:0x00000008
+ Workqueue: events_unbound deferred_probe_work_func
+ Call trace:
+ __switch_to+0xf4/0x1f4
+ __schedule+0x418/0xb80
+ schedule+0x5c/0x10c
+ schedule_preempt_disabled+0x2c/0x48
+ __mutex_lock+0x238/0x488
+ __mutex_lock_slowpath+0x1c/0x28
+ mutex_lock+0x50/0x74
+ clk_prepare_lock+0x7c/0x9c
+ clk_core_prepare_lock+0x20/0x44
+ clk_prepare+0x24/0x30
+ clk_bulk_prepare+0x40/0xb0
+ mdss_runtime_resume+0x54/0x1c8
+ pm_generic_runtime_resume+0x30/0x44
+ __genpd_runtime_resume+0x68/0x7c
+ genpd_runtime_resume+0x108/0x1f4
+ __rpm_callback+0x84/0x144
+ rpm_callback+0x30/0x88
+ rpm_resume+0x1f4/0x52c
+ rpm_resume+0x178/0x52c
+ __pm_runtime_resume+0x58/0x98
+ __device_attach+0xe0/0x170
+ device_initial_probe+0x1c/0x28
+ bus_probe_device+0x3c/0x9c
+ device_add+0x644/0x814
+ mipi_dsi_device_register_full+0xe4/0x170
+ devm_mipi_dsi_device_register_full+0x28/0x70
+ ti_sn_bridge_probe+0x1dc/0x2c0
+ auxiliary_bus_probe+0x4c/0x94
+ really_probe+0xcc/0x2c8
+ __driver_probe_device+0xa8/0x130
+ driver_probe_device+0x48/0x110
+ __device_attach_driver+0xa4/0xcc
+ bus_for_each_drv+0x8c/0xd8
+ __device_attach+0xf8/0x170
+ device_initial_probe+0x1c/0x28
+ bus_probe_device+0x3c/0x9c
+ deferred_probe_work_func+0x9c/0xd8
+ process_one_work+0x148/0x518
+ worker_thread+0x138/0x350
+ kthread+0x138/0x1e0
+ ret_from_fork+0x10/0x20
+
+The first thread is walking the clk tree and calling
+clk_pm_runtime_get() to power on devices required to read the clk
+hardware via struct clk_ops::is_enabled(). This thread holds the clk
+prepare_lock, and is trying to runtime PM resume a device, when it finds
+that the device is in the process of resuming so the thread schedule()s
+away waiting for the device to finish resuming before continuing. The
+second thread is runtime PM resuming the same device, but the runtime
+resume callback is calling clk_prepare(), trying to grab the
+prepare_lock waiting on the first thread.
+
+This is a classic ABBA deadlock. To properly fix the deadlock, we must
+never runtime PM resume or suspend a device with the clk prepare_lock
+held. Actually doing that is near impossible today because the global
+prepare_lock would have to be dropped in the middle of the tree, the
+device runtime PM resumed/suspended, and then the prepare_lock grabbed
+again to ensure consistency of the clk tree topology. If anything
+changes with the clk tree in the meantime, we've lost and will need to
+start the operation all over again.
+
+Luckily, most of the time we're simply incrementing or decrementing the
+runtime PM count on an active device, so we don't have the chance to
+schedule away with the prepare_lock held. Let's fix this immediate
+problem that can be triggered more easily by simply booting on Qualcomm
+sc7180.
+
+Introduce a list of clk_core structures that have been registered, or
+are in the process of being registered, that require runtime PM to
+operate. Iterate this list and call clk_pm_runtime_get() on each of them
+without holding the prepare_lock during clk_disable_unused(). This way
+we can be certain that the runtime PM state of the devices will be
+active and resumed so we can't schedule away while walking the clk tree
+with the prepare_lock held. Similarly, call clk_pm_runtime_put() without
+the prepare_lock held to properly drop the runtime PM reference. We
+remove the calls to clk_pm_runtime_{get,put}() in this path because
+they're superfluous now that we know the devices are runtime resumed.
+
+Reported-by: Douglas Anderson <dianders@chromium.org>
+Closes: https://lore.kernel.org/all/20220922084322.RFC.2.I375b6b9e0a0a5348962f004beb3dafee6a12dfbb@changeid/ [1]
+Closes: https://issuetracker.google.com/328070191
+Cc: Marek Szyprowski <m.szyprowski@samsung.com>
+Cc: Ulf Hansson <ulf.hansson@linaro.org>
+Cc: Krzysztof Kozlowski <krzk@kernel.org>
+Fixes: 9a34b45397e5 ("clk: Add support for runtime PM")
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Link: https://lore.kernel.org/r/20240325184204.745706-5-sboyd@kernel.org
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/clk.c | 117 +++++++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 105 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
+index 56b8f540e8abe..7c87a8084df76 100644
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -37,6 +37,10 @@ static HLIST_HEAD(clk_root_list);
+ static HLIST_HEAD(clk_orphan_list);
+ static LIST_HEAD(clk_notifier_list);
+
++/* List of registered clks that use runtime PM */
++static HLIST_HEAD(clk_rpm_list);
++static DEFINE_MUTEX(clk_rpm_list_lock);
++
+ static const struct hlist_head *all_lists[] = {
+ &clk_root_list,
+ &clk_orphan_list,
+@@ -59,6 +63,7 @@ struct clk_core {
+ struct clk_hw *hw;
+ struct module *owner;
+ struct device *dev;
++ struct hlist_node rpm_node;
+ struct device_node *of_node;
+ struct clk_core *parent;
+ struct clk_parent_map *parents;
+@@ -122,6 +127,89 @@ static void clk_pm_runtime_put(struct clk_core *core)
+ pm_runtime_put_sync(core->dev);
+ }
+
++/**
++ * clk_pm_runtime_get_all() - Runtime "get" all clk provider devices
++ *
++ * Call clk_pm_runtime_get() on all runtime PM enabled clks in the clk tree so
++ * that disabling unused clks avoids a deadlock where a device is runtime PM
++ * resuming/suspending and the runtime PM callback is trying to grab the
++ * prepare_lock for something like clk_prepare_enable() while
++ * clk_disable_unused_subtree() holds the prepare_lock and is trying to runtime
++ * PM resume/suspend the device as well.
++ *
++ * Context: Acquires the 'clk_rpm_list_lock' and returns with the lock held on
++ * success. Otherwise the lock is released on failure.
++ *
++ * Return: 0 on success, negative errno otherwise.
++ */
++static int clk_pm_runtime_get_all(void)
++{
++ int ret;
++ struct clk_core *core, *failed;
++
++ /*
++ * Grab the list lock to prevent any new clks from being registered
++ * or unregistered until clk_pm_runtime_put_all().
++ */
++ mutex_lock(&clk_rpm_list_lock);
++
++ /*
++ * Runtime PM "get" all the devices that are needed for the clks
++ * currently registered. Do this without holding the prepare_lock, to
++ * avoid the deadlock.
++ */
++ hlist_for_each_entry(core, &clk_rpm_list, rpm_node) {
++ ret = clk_pm_runtime_get(core);
++ if (ret) {
++ failed = core;
++ pr_err("clk: Failed to runtime PM get '%s' for clk '%s'\n",
++ dev_name(failed->dev), failed->name);
++ goto err;
++ }
++ }
++
++ return 0;
++
++err:
++ hlist_for_each_entry(core, &clk_rpm_list, rpm_node) {
++ if (core == failed)
++ break;
++
++ clk_pm_runtime_put(core);
++ }
++ mutex_unlock(&clk_rpm_list_lock);
++
++ return ret;
++}
++
++/**
++ * clk_pm_runtime_put_all() - Runtime "put" all clk provider devices
++ *
++ * Put the runtime PM references taken in clk_pm_runtime_get_all() and release
++ * the 'clk_rpm_list_lock'.
++ */
++static void clk_pm_runtime_put_all(void)
++{
++ struct clk_core *core;
++
++ hlist_for_each_entry(core, &clk_rpm_list, rpm_node)
++ clk_pm_runtime_put(core);
++ mutex_unlock(&clk_rpm_list_lock);
++}
++
++static void clk_pm_runtime_init(struct clk_core *core)
++{
++ struct device *dev = core->dev;
++
++ if (dev && pm_runtime_enabled(dev)) {
++ core->rpm_enabled = true;
++
++ mutex_lock(&clk_rpm_list_lock);
++ hlist_add_head(&core->rpm_node, &clk_rpm_list);
++ mutex_unlock(&clk_rpm_list_lock);
++ }
++}
++
+ /*** locking ***/
+ static void clk_prepare_lock(void)
+ {
+@@ -1362,9 +1450,6 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core)
+ if (core->flags & CLK_IGNORE_UNUSED)
+ return;
+
+- if (clk_pm_runtime_get(core))
+- return;
+-
+ if (clk_core_is_prepared(core)) {
+ trace_clk_unprepare(core);
+ if (core->ops->unprepare_unused)
+@@ -1373,8 +1458,6 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core)
+ core->ops->unprepare(core->hw);
+ trace_clk_unprepare_complete(core);
+ }
+-
+- clk_pm_runtime_put(core);
+ }
+
+ static void __init clk_disable_unused_subtree(struct clk_core *core)
+@@ -1390,9 +1473,6 @@ static void __init clk_disable_unused_subtree(struct clk_core *core)
+ if (core->flags & CLK_OPS_PARENT_ENABLE)
+ clk_core_prepare_enable(core->parent);
+
+- if (clk_pm_runtime_get(core))
+- goto unprepare_out;
+-
+ flags = clk_enable_lock();
+
+ if (core->enable_count)
+@@ -1417,8 +1497,6 @@ static void __init clk_disable_unused_subtree(struct clk_core *core)
+
+ unlock_out:
+ clk_enable_unlock(flags);
+- clk_pm_runtime_put(core);
+-unprepare_out:
+ if (core->flags & CLK_OPS_PARENT_ENABLE)
+ clk_core_disable_unprepare(core->parent);
+ }
+@@ -1434,6 +1512,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup);
+ static int __init clk_disable_unused(void)
+ {
+ struct clk_core *core;
++ int ret;
+
+ if (clk_ignore_unused) {
+ pr_warn("clk: Not disabling unused clocks\n");
+@@ -1442,6 +1521,13 @@ static int __init clk_disable_unused(void)
+
+ pr_info("clk: Disabling unused clocks\n");
+
++ ret = clk_pm_runtime_get_all();
++ if (ret)
++ return ret;
++ /*
++ * Grab the prepare lock to keep the clk topology stable while iterating
++ * over clks.
++ */
+ clk_prepare_lock();
+
+ hlist_for_each_entry(core, &clk_root_list, child_node)
+@@ -1458,6 +1544,8 @@ static int __init clk_disable_unused(void)
+
+ clk_prepare_unlock();
+
++ clk_pm_runtime_put_all();
++
+ return 0;
+ }
+ late_initcall_sync(clk_disable_unused);
+@@ -4152,6 +4240,12 @@ static void __clk_release(struct kref *ref)
+ {
+ struct clk_core *core = container_of(ref, struct clk_core, ref);
+
++ if (core->rpm_enabled) {
++ mutex_lock(&clk_rpm_list_lock);
++ hlist_del(&core->rpm_node);
++ mutex_unlock(&clk_rpm_list_lock);
++ }
++
+ clk_core_free_parent_map(core);
+ kfree_const(core->name);
+ kfree(core);
+@@ -4191,9 +4285,8 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
+ }
+ core->ops = init->ops;
+
+- if (dev && pm_runtime_enabled(dev))
+- core->rpm_enabled = true;
+ core->dev = dev;
++ clk_pm_runtime_init(core);
+ core->of_node = np;
+ if (dev && dev->driver)
+ core->owner = dev->driver->owner;
+--
+2.43.0
+
--- /dev/null
+From 3d18d8c18eea27073229ed3c512791713a7aac50 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Mar 2024 11:41:59 -0700
+Subject: clk: Get runtime PM before walking tree for clk_summary
+
+From: Stephen Boyd <sboyd@kernel.org>
+
+[ Upstream commit 9d1e795f754db1ac3344528b7af0b17b8146f321 ]
+
+Similar to the previous commit, we should make sure that all devices are
+runtime resumed before printing the clk_summary through debugfs. Failure
+to do so would result in a deadlock if the thread is resuming a device
+to print clk state and that device is also runtime resuming in another
+thread, e.g the screen is turning on and the display driver is starting
+up. We remove the calls to clk_pm_runtime_{get,put}() in this path
+because they're superfluous now that we know the devices are runtime
+resumed. This also squashes a bug where the return value of
+clk_pm_runtime_get() wasn't checked, leading to an RPM count underflow
+on error paths.
+
+Fixes: 1bb294a7981c ("clk: Enable/Disable runtime PM for clk_summary")
+Cc: Taniya Das <quic_tdas@quicinc.com>
+Cc: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Link: https://lore.kernel.org/r/20240325184204.745706-6-sboyd@kernel.org
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/clk.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
+index 011e7632541fa..4a67c0d4823cf 100644
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -3321,9 +3321,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
+ {
+ struct clk_core *child;
+
+- clk_pm_runtime_get(c);
+ clk_summary_show_one(s, c, level);
+- clk_pm_runtime_put(c);
+
+ hlist_for_each_entry(child, &c->children, child_node)
+ clk_summary_show_subtree(s, child, level + 1);
+@@ -3333,11 +3331,15 @@ static int clk_summary_show(struct seq_file *s, void *data)
+ {
+ struct clk_core *c;
+ struct hlist_head **lists = s->private;
++ int ret;
+
+ seq_puts(s, " enable prepare protect duty hardware connection\n");
+ seq_puts(s, " clock count count count rate accuracy phase cycle enable consumer id\n");
+ seq_puts(s, "---------------------------------------------------------------------------------------------------------------------------------------------\n");
+
++ ret = clk_pm_runtime_get_all();
++ if (ret)
++ return ret;
+
+ clk_prepare_lock();
+
+@@ -3346,6 +3348,7 @@ static int clk_summary_show(struct seq_file *s, void *data)
+ clk_summary_show_subtree(s, c, 0);
+
+ clk_prepare_unlock();
++ clk_pm_runtime_put_all();
+
+ return 0;
+ }
+@@ -3393,8 +3396,14 @@ static int clk_dump_show(struct seq_file *s, void *data)
+ struct clk_core *c;
+ bool first_node = true;
+ struct hlist_head **lists = s->private;
++ int ret;
++
++ ret = clk_pm_runtime_get_all();
++ if (ret)
++ return ret;
+
+ seq_putc(s, '{');
++
+ clk_prepare_lock();
+
+ for (; *lists; lists++) {
+@@ -3407,6 +3416,7 @@ static int clk_dump_show(struct seq_file *s, void *data)
+ }
+
+ clk_prepare_unlock();
++ clk_pm_runtime_put_all();
+
+ seq_puts(s, "}\n");
+ return 0;
+--
+2.43.0
+
--- /dev/null
+From add4ef5fecd25e1ead273e1d6b4db31581c090fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Mar 2024 11:41:57 -0700
+Subject: clk: Initialize struct clk_core kref earlier
+
+From: Stephen Boyd <sboyd@kernel.org>
+
+[ Upstream commit 9d05ae531c2cff20d5d527f04e28d28e04379929 ]
+
+Initialize this kref once we allocate memory for the struct clk_core so
+that we can reuse the release function to free any memory associated
+with the structure. This mostly consolidates code, but also clarifies
+that the kref lifetime exists once the container structure (struct
+clk_core) is allocated instead of leaving it in a half-baked state for
+most of __clk_core_init().
+
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Link: https://lore.kernel.org/r/20240325184204.745706-4-sboyd@kernel.org
+Stable-dep-of: e581cf5d2162 ("clk: Get runtime PM before walking tree during disable_unused")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/clk.c | 28 +++++++++++++---------------
+ 1 file changed, 13 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
+index ac5be561ccdc9..56b8f540e8abe 100644
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -3919,8 +3919,6 @@ static int __clk_core_init(struct clk_core *core)
+ }
+
+ clk_core_reparent_orphans_nolock();
+-
+- kref_init(&core->ref);
+ out:
+ clk_pm_runtime_put(core);
+ unlock:
+@@ -4149,6 +4147,16 @@ static void clk_core_free_parent_map(struct clk_core *core)
+ kfree(core->parents);
+ }
+
++/* Free memory allocated for a struct clk_core */
++static void __clk_release(struct kref *ref)
++{
++ struct clk_core *core = container_of(ref, struct clk_core, ref);
++
++ clk_core_free_parent_map(core);
++ kfree_const(core->name);
++ kfree(core);
++}
++
+ static struct clk *
+ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
+ {
+@@ -4169,6 +4177,8 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
+ goto fail_out;
+ }
+
++ kref_init(&core->ref);
++
+ core->name = kstrdup_const(init->name, GFP_KERNEL);
+ if (!core->name) {
+ ret = -ENOMEM;
+@@ -4223,12 +4233,10 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
+ hw->clk = NULL;
+
+ fail_create_clk:
+- clk_core_free_parent_map(core);
+ fail_parents:
+ fail_ops:
+- kfree_const(core->name);
+ fail_name:
+- kfree(core);
++ kref_put(&core->ref, __clk_release);
+ fail_out:
+ return ERR_PTR(ret);
+ }
+@@ -4308,16 +4316,6 @@ int of_clk_hw_register(struct device_node *node, struct clk_hw *hw)
+ }
+ EXPORT_SYMBOL_GPL(of_clk_hw_register);
+
+-/* Free memory allocated for a clock. */
+-static void __clk_release(struct kref *ref)
+-{
+- struct clk_core *core = container_of(ref, struct clk_core, ref);
+-
+- clk_core_free_parent_map(core);
+- kfree_const(core->name);
+- kfree(core);
+-}
+-
+ /*
+ * Empty clk_ops for unregistered clocks. These are used temporarily
+ * after clk_unregister() was called on a clock and until last clock
+--
+2.43.0
+
--- /dev/null
+From 48e47292742c39b19ee238d3b09443d27a88123d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Mar 2024 19:51:55 +0800
+Subject: clk: mediatek: Do a runtime PM get on controllers during probe
+
+From: Pin-yen Lin <treapking@chromium.org>
+
+[ Upstream commit 2f7b1d8b5505efb0057cd1ab85fca206063ea4c3 ]
+
+mt8183-mfgcfg has a mutual dependency with genpd during the probing
+stage, which leads to a deadlock in the following call stack:
+
+CPU0: genpd_lock --> clk_prepare_lock
+genpd_power_off_work_fn()
+ genpd_lock()
+ generic_pm_domain::power_off()
+ clk_unprepare()
+ clk_prepare_lock()
+
+CPU1: clk_prepare_lock --> genpd_lock
+clk_register()
+ __clk_core_init()
+ clk_prepare_lock()
+ clk_pm_runtime_get()
+ genpd_lock()
+
+Do a runtime PM get at the probe function to make sure clk_register()
+won't acquire the genpd lock. Instead of only modifying mt8183-mfgcfg,
+do this on all mediatek clock controller probings because we don't
+believe this would cause any regression.
+
+Verified on MT8183 and MT8192 Chromebooks.
+
+Fixes: acddfc2c261b ("clk: mediatek: Add MT8183 clock support")
+Signed-off-by: Pin-yen Lin <treapking@chromium.org>
+
+Link: https://lore.kernel.org/r/20240312115249.3341654-1-treapking@chromium.org
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/mediatek/clk-mtk.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
+index 2e55368dc4d82..bd37ab4d1a9bb 100644
+--- a/drivers/clk/mediatek/clk-mtk.c
++++ b/drivers/clk/mediatek/clk-mtk.c
+@@ -13,6 +13,7 @@
+ #include <linux/of.h>
+ #include <linux/of_address.h>
+ #include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
+ #include <linux/slab.h>
+
+ #include "clk-mtk.h"
+@@ -494,6 +495,16 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
+ return IS_ERR(base) ? PTR_ERR(base) : -ENOMEM;
+ }
+
++
++ devm_pm_runtime_enable(&pdev->dev);
++ /*
++ * Do a pm_runtime_resume_and_get() to workaround a possible
++ * deadlock between clk_register() and the genpd framework.
++ */
++ r = pm_runtime_resume_and_get(&pdev->dev);
++ if (r)
++ return r;
++
+ /* Calculate how many clk_hw_onecell_data entries to allocate */
+ num_clks = mcd->num_clks + mcd->num_composite_clks;
+ num_clks += mcd->num_fixed_clks + mcd->num_factor_clks;
+@@ -574,6 +585,8 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
+ goto unregister_clks;
+ }
+
++ pm_runtime_put(&pdev->dev);
++
+ return r;
+
+ unregister_clks:
+@@ -604,6 +617,8 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
+ free_base:
+ if (mcd->shared_io && base)
+ iounmap(base);
++
++ pm_runtime_put(&pdev->dev);
+ return r;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 2deb3754e80187eadbd2e3a2604264173d94d784 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 Mar 2024 11:41:55 -0700
+Subject: clk: Remove prepare_lock hold assertion in __clk_release()
+
+From: Stephen Boyd <sboyd@kernel.org>
+
+[ Upstream commit 8358a76cfb47c9a5af627a0c4e7168aa14fa25f6 ]
+
+Removing this assertion lets us move the kref_put() call outside the
+prepare_lock section. We don't need to hold the prepare_lock here to
+free memory and destroy the clk_core structure. We've already unlinked
+the clk from the clk tree and by the time the release function runs
+nothing holds a reference to the clk_core anymore so anything with the
+pointer can't access the memory that's being freed anyway. Way back in
+commit 496eadf821c2 ("clk: Use lockdep asserts to find missing hold of
+prepare_lock") we didn't need to have this assertion either.
+
+Fixes: 496eadf821c2 ("clk: Use lockdep asserts to find missing hold of prepare_lock")
+Cc: Krzysztof Kozlowski <krzk@kernel.org>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Link: https://lore.kernel.org/r/20240325184204.745706-2-sboyd@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/clk.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
+index 50228cb0c5590..ac5be561ccdc9 100644
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -4313,8 +4313,6 @@ static void __clk_release(struct kref *ref)
+ {
+ struct clk_core *core = container_of(ref, struct clk_core, ref);
+
+- lockdep_assert_held(&prepare_lock);
+-
+ clk_core_free_parent_map(core);
+ kfree_const(core->name);
+ kfree(core);
+--
+2.43.0
+
--- /dev/null
+From f7deca7e1681741a0c477e4408cbda438dc7715d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Nov 2022 22:53:19 +0530
+Subject: clk: Show active consumers of clocks in debugfs
+
+From: Vishal Badole <badolevishal1116@gmail.com>
+
+[ Upstream commit dcce5cc7826e9c6b3a2443e5e6b7f8d02a103c35 ]
+
+This feature lists the clock consumer's name and respective connection
+id. Using this feature user can easily check that which user has
+acquired and enabled a particular clock.
+
+Usage:
+>> cat /sys/kernel/debug/clk/clk_summary
+ enable prepare protect
+ duty hardware Connection
+ clock count count count rate accuracy phase cycle enable consumer Id
+------------------------------------------------------------------------------------------------------------------------------
+ clk_mcasp0_fixed 0 0 0 24576000 0 0 50000 Y deviceless of_clk_get_from_provider
+ deviceless no_connection_id
+ clk_mcasp0 0 0 0 24576000 0 0 50000 N simple-audio-card,cpu no_connection_id
+ deviceless no_connection_id
+
+Co-developed-by: Chinmoy Ghosh <chinmoyghosh2001@gmail.com>
+Signed-off-by: Chinmoy Ghosh <chinmoyghosh2001@gmail.com>
+Co-developed-by: Mintu Patel <mintupatel89@gmail.com>
+Signed-off-by: Mintu Patel <mintupatel89@gmail.com>
+Co-developed-by: Vimal Kumar <vimal.kumar32@gmail.com>
+Signed-off-by: Vimal Kumar <vimal.kumar32@gmail.com>
+Signed-off-by: Vishal Badole <badolevishal1116@gmail.com>
+Link: https://lore.kernel.org/r/1669569799-8526-1-git-send-email-badolevishal1116@gmail.com
+Signed-off-by: Stephen Boyd <sboyd@kernel.org>
+Stable-dep-of: 9d1e795f754d ("clk: Get runtime PM before walking tree for clk_summary")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/clk.c | 34 ++++++++++++++++++++++++----------
+ 1 file changed, 24 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
+index 7c87a8084df76..011e7632541fa 100644
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -3279,28 +3279,41 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
+ int level)
+ {
+ int phase;
++ struct clk *clk_user;
++ int multi_node = 0;
+
+- seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu ",
++ seq_printf(s, "%*s%-*s %-7d %-8d %-8d %-11lu %-10lu ",
+ level * 3 + 1, "",
+- 30 - level * 3, c->name,
++ 35 - level * 3, c->name,
+ c->enable_count, c->prepare_count, c->protect_count,
+ clk_core_get_rate_recalc(c),
+ clk_core_get_accuracy_recalc(c));
+
+ phase = clk_core_get_phase(c);
+ if (phase >= 0)
+- seq_printf(s, "%5d", phase);
++ seq_printf(s, "%-5d", phase);
+ else
+ seq_puts(s, "-----");
+
+- seq_printf(s, " %6d", clk_core_get_scaled_duty_cycle(c, 100000));
++ seq_printf(s, " %-6d", clk_core_get_scaled_duty_cycle(c, 100000));
+
+ if (c->ops->is_enabled)
+- seq_printf(s, " %9c\n", clk_core_is_enabled(c) ? 'Y' : 'N');
++ seq_printf(s, " %5c ", clk_core_is_enabled(c) ? 'Y' : 'N');
+ else if (!c->ops->enable)
+- seq_printf(s, " %9c\n", 'Y');
++ seq_printf(s, " %5c ", 'Y');
+ else
+- seq_printf(s, " %9c\n", '?');
++ seq_printf(s, " %5c ", '?');
++
++ hlist_for_each_entry(clk_user, &c->clks, clks_node) {
++ seq_printf(s, "%*s%-*s %-25s\n",
++ level * 3 + 2 + 105 * multi_node, "",
++ 30,
++ clk_user->dev_id ? clk_user->dev_id : "deviceless",
++ clk_user->con_id ? clk_user->con_id : "no_connection_id");
++
++ multi_node = 1;
++ }
++
+ }
+
+ static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
+@@ -3321,9 +3334,10 @@ static int clk_summary_show(struct seq_file *s, void *data)
+ struct clk_core *c;
+ struct hlist_head **lists = s->private;
+
+- seq_puts(s, " enable prepare protect duty hardware\n");
+- seq_puts(s, " clock count count count rate accuracy phase cycle enable\n");
+- seq_puts(s, "-------------------------------------------------------------------------------------------------------\n");
++ seq_puts(s, " enable prepare protect duty hardware connection\n");
++ seq_puts(s, " clock count count count rate accuracy phase cycle enable consumer id\n");
++ seq_puts(s, "---------------------------------------------------------------------------------------------------------------------------------------------\n");
++
+
+ clk_prepare_lock();
+
+--
+2.43.0
+
--- /dev/null
+From 985e3b77f8754a181adba14ba97ecda7839f468e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Nov 2023 23:38:59 +0000
+Subject: drm: panel-orientation-quirks: Add quirk for Lenovo Legion Go
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Brenton Simpson <appsforartists@google.com>
+
+[ Upstream commit 430143b0d3611f4a9c8434319e5e504244749e79 ]
+
+The Legion Go has a 2560x1600 portrait screen, with the native "up" facing
+the right controller (90° CW from the rest of the device).
+
+Signed-off-by: Brenton Simpson <appsforartists@google.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20231114233859.274189-1-appsforartists@google.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_panel_orientation_quirks.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+index 3fe5e6439c401..aa93129c3397e 100644
+--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
++++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+@@ -348,6 +348,12 @@ static const struct dmi_system_id orientation_data[] = {
+ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Duet 3 10IGL5"),
+ },
+ .driver_data = (void *)&lcd1200x1920_rightside_up,
++ }, { /* Lenovo Legion Go 8APU1 */
++ .matches = {
++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++ DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Legion Go 8APU1"),
++ },
++ .driver_data = (void *)&lcd1600x2560_leftside_up,
+ }, { /* Lenovo Yoga Book X90F / X90L */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+--
+2.43.0
+
--- /dev/null
+From a94dd5aee55f39a2f6df40f401fc583c5a7e27ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Mar 2024 14:56:52 -0800
+Subject: interconnect: Don't access req_list while it's being manipulated
+
+From: Mike Tipton <quic_mdtipton@quicinc.com>
+
+[ Upstream commit de1bf25b6d771abdb52d43546cf57ad775fb68a1 ]
+
+The icc_lock mutex was split into separate icc_lock and icc_bw_lock
+mutexes in [1] to avoid lockdep splats. However, this didn't adequately
+protect access to icc_node::req_list.
+
+The icc_set_bw() function will eventually iterate over req_list while
+only holding icc_bw_lock, but req_list can be modified while only
+holding icc_lock. This causes races between icc_set_bw(), of_icc_get(),
+and icc_put().
+
+Example A:
+
+ CPU0 CPU1
+ ---- ----
+ icc_set_bw(path_a)
+ mutex_lock(&icc_bw_lock);
+ icc_put(path_b)
+ mutex_lock(&icc_lock);
+ aggregate_requests()
+ hlist_for_each_entry(r, ...
+ hlist_del(...
+ <r = invalid pointer>
+
+Example B:
+
+ CPU0 CPU1
+ ---- ----
+ icc_set_bw(path_a)
+ mutex_lock(&icc_bw_lock);
+ path_b = of_icc_get()
+ of_icc_get_by_index()
+ mutex_lock(&icc_lock);
+ path_find()
+ path_init()
+ aggregate_requests()
+ hlist_for_each_entry(r, ...
+ hlist_add_head(...
+ <r = invalid pointer>
+
+Fix this by ensuring icc_bw_lock is always held before manipulating
+icc_node::req_list. The additional places icc_bw_lock is held don't
+perform any memory allocations, so we should still be safe from the
+original lockdep splats that motivated the separate locks.
+
+[1] commit af42269c3523 ("interconnect: Fix locking for runpm vs reclaim")
+
+Signed-off-by: Mike Tipton <quic_mdtipton@quicinc.com>
+Fixes: af42269c3523 ("interconnect: Fix locking for runpm vs reclaim")
+Reviewed-by: Rob Clark <robdclark@chromium.org>
+Link: https://lore.kernel.org/r/20240305225652.22872-1-quic_mdtipton@quicinc.com
+Signed-off-by: Georgi Djakov <djakov@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/interconnect/core.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
+index 50bac2d79d9b5..68edb07d4443e 100644
+--- a/drivers/interconnect/core.c
++++ b/drivers/interconnect/core.c
+@@ -176,6 +176,8 @@ static struct icc_path *path_init(struct device *dev, struct icc_node *dst,
+
+ path->num_nodes = num_nodes;
+
++ mutex_lock(&icc_bw_lock);
++
+ for (i = num_nodes - 1; i >= 0; i--) {
+ node->provider->users++;
+ hlist_add_head(&path->reqs[i].req_node, &node->req_list);
+@@ -186,6 +188,8 @@ static struct icc_path *path_init(struct device *dev, struct icc_node *dst,
+ node = node->reverse;
+ }
+
++ mutex_unlock(&icc_bw_lock);
++
+ return path;
+ }
+
+@@ -792,12 +796,16 @@ void icc_put(struct icc_path *path)
+ pr_err("%s: error (%d)\n", __func__, ret);
+
+ mutex_lock(&icc_lock);
++ mutex_lock(&icc_bw_lock);
++
+ for (i = 0; i < path->num_nodes; i++) {
+ node = path->reqs[i].node;
+ hlist_del(&path->reqs[i].req_node);
+ if (!WARN_ON(!node->provider->users))
+ node->provider->users--;
+ }
++
++ mutex_unlock(&icc_bw_lock);
+ mutex_unlock(&icc_lock);
+
+ kfree_const(path->name);
+--
+2.43.0
+
--- /dev/null
+From 364b460e7117f64ad97ab29ba0a81ed0aa71aad2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Oct 2023 15:52:59 +0300
+Subject: PCI: Add PCI_HEADER_TYPE_MFD definition
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+
+[ Upstream commit bdca03a271f2de2c24ea56756fd9bbcff35173fb ]
+
+Add PCI_HEADER_TYPE_MFD so we can replace literals in the code.
+
+Link: https://lore.kernel.org/r/20231003125300.5541-3-ilpo.jarvinen@linux.intel.com
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Stable-dep-of: 83c088148c8e ("PCI: Use PCI_HEADER_TYPE_* instead of literals")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/uapi/linux/pci_regs.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
+index e5f558d964939..06df65f11c396 100644
+--- a/include/uapi/linux/pci_regs.h
++++ b/include/uapi/linux/pci_regs.h
+@@ -80,6 +80,7 @@
+ #define PCI_HEADER_TYPE_NORMAL 0
+ #define PCI_HEADER_TYPE_BRIDGE 1
+ #define PCI_HEADER_TYPE_CARDBUS 2
++#define PCI_HEADER_TYPE_MFD 0x80 /* Multi-Function Device (possible) */
+
+ #define PCI_BIST 0x0f /* 8 bits */
+ #define PCI_BIST_CODE_MASK 0x0f /* Return result */
+--
+2.43.0
+
--- /dev/null
+From c681bf711459e12cc5f0a38c2024452ef5dfee57 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 Oct 2023 14:32:51 +0300
+Subject: PCI/DPC: Use FIELD_GET()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+[ Upstream commit 9a9eec4765737b9b2a8d6ae03de6480a5f12dd5c ]
+
+Use FIELD_GET() to remove dependencies on the field position, i.e., the
+shift value. No functional change intended.
+
+Link: https://lore.kernel.org/r/20231018113254.17616-5-ilpo.jarvinen@linux.intel.com
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/dpc.c | 5 +++--
+ drivers/pci/quirks.c | 2 +-
+ include/uapi/linux/pci_regs.h | 1 +
+ 3 files changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c
+index b4818007788f9..a5cec2a4e057d 100644
+--- a/drivers/pci/pcie/dpc.c
++++ b/drivers/pci/pcie/dpc.c
+@@ -9,6 +9,7 @@
+ #define dev_fmt(fmt) "DPC: " fmt
+
+ #include <linux/aer.h>
++#include <linux/bitfield.h>
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
+@@ -202,7 +203,7 @@ static void dpc_process_rp_pio_error(struct pci_dev *pdev)
+
+ /* Get First Error Pointer */
+ pci_read_config_word(pdev, cap + PCI_EXP_DPC_STATUS, &dpc_status);
+- first_error = (dpc_status & 0x1f00) >> 8;
++ first_error = FIELD_GET(PCI_EXP_DPC_RP_PIO_FEP, dpc_status);
+
+ for (i = 0; i < ARRAY_SIZE(rp_pio_error_string); i++) {
+ if ((status & ~mask) & (1 << i))
+@@ -338,7 +339,7 @@ void pci_dpc_init(struct pci_dev *pdev)
+ /* Quirks may set dpc_rp_log_size if device or firmware is buggy */
+ if (!pdev->dpc_rp_log_size) {
+ pdev->dpc_rp_log_size =
+- (cap & PCI_EXP_DPC_RP_PIO_LOG_SIZE) >> 8;
++ FIELD_GET(PCI_EXP_DPC_RP_PIO_LOG_SIZE, cap);
+ if (pdev->dpc_rp_log_size < 4 || pdev->dpc_rp_log_size > 9) {
+ pci_err(pdev, "RP PIO log size %u is invalid\n",
+ pdev->dpc_rp_log_size);
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index 675f77ac1968d..e1c652b1c53a4 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -6198,7 +6198,7 @@ static void dpc_log_size(struct pci_dev *dev)
+ if (!(val & PCI_EXP_DPC_CAP_RP_EXT))
+ return;
+
+- if (!((val & PCI_EXP_DPC_RP_PIO_LOG_SIZE) >> 8)) {
++ if (FIELD_GET(PCI_EXP_DPC_RP_PIO_LOG_SIZE, val) == 0) {
+ pci_info(dev, "Overriding RP PIO Log Size to 4\n");
+ dev->dpc_rp_log_size = 4;
+ }
+diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
+index 06df65f11c396..6c31c805ac4bd 100644
+--- a/include/uapi/linux/pci_regs.h
++++ b/include/uapi/linux/pci_regs.h
+@@ -1046,6 +1046,7 @@
+ #define PCI_EXP_DPC_STATUS_INTERRUPT 0x0008 /* Interrupt Status */
+ #define PCI_EXP_DPC_RP_BUSY 0x0010 /* Root Port Busy */
+ #define PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT 0x0060 /* Trig Reason Extension */
++#define PCI_EXP_DPC_RP_PIO_FEP 0x1f00 /* RP PIO First Err Ptr */
+
+ #define PCI_EXP_DPC_SOURCE_ID 0x0A /* DPC Source Identifier */
+
+--
+2.43.0
+
--- /dev/null
+From b79500383c8b70476a81c5898ce40f191503b128 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 26 Oct 2023 15:19:23 +0300
+Subject: PCI: Simplify pcie_capability_clear_and_set_word() to
+ ..._clear_word()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+
+[ Upstream commit 0fce6e5c87faec2c8bf28d2abc8cb595f4e244b6 ]
+
+When using pcie_capability_clear_and_set_word() but not actually *setting*
+anything, use pcie_capability_clear_word() instead.
+
+Link: https://lore.kernel.org/r/20231026121924.2164-1-ilpo.jarvinen@linux.intel.com
+Link: https://lore.kernel.org/r/20231026121924.2164-2-ilpo.jarvinen@linux.intel.com
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+[bhelgaas: squash]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/aspm.c | 8 ++++----
+ drivers/pci/quirks.c | 6 +++---
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
+index 7e3b342215e5b..19a673aa08eb2 100644
+--- a/drivers/pci/pcie/aspm.c
++++ b/drivers/pci/pcie/aspm.c
+@@ -689,10 +689,10 @@ static void pcie_config_aspm_l1ss(struct pcie_link_state *link, u32 state)
+ * in pcie_config_aspm_link().
+ */
+ if (enable_req & (ASPM_STATE_L1_1 | ASPM_STATE_L1_2)) {
+- pcie_capability_clear_and_set_word(child, PCI_EXP_LNKCTL,
+- PCI_EXP_LNKCTL_ASPM_L1, 0);
+- pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL,
+- PCI_EXP_LNKCTL_ASPM_L1, 0);
++ pcie_capability_clear_word(child, PCI_EXP_LNKCTL,
++ PCI_EXP_LNKCTL_ASPM_L1);
++ pcie_capability_clear_word(parent, PCI_EXP_LNKCTL,
++ PCI_EXP_LNKCTL_ASPM_L1);
+ }
+
+ val = 0;
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index e1c652b1c53a4..fa770601c655a 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -4571,9 +4571,9 @@ static void quirk_disable_root_port_attributes(struct pci_dev *pdev)
+
+ pci_info(root_port, "Disabling No Snoop/Relaxed Ordering Attributes to avoid PCIe Completion erratum in %s\n",
+ dev_name(&pdev->dev));
+- pcie_capability_clear_and_set_word(root_port, PCI_EXP_DEVCTL,
+- PCI_EXP_DEVCTL_RELAX_EN |
+- PCI_EXP_DEVCTL_NOSNOOP_EN, 0);
++ pcie_capability_clear_word(root_port, PCI_EXP_DEVCTL,
++ PCI_EXP_DEVCTL_RELAX_EN |
++ PCI_EXP_DEVCTL_NOSNOOP_EN);
+ }
+
+ /*
+--
+2.43.0
+
--- /dev/null
+From 47a6faa3158d5013c24f05c59c3d3b84f273d9dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 3 Oct 2023 15:53:00 +0300
+Subject: PCI: Use PCI_HEADER_TYPE_* instead of literals
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+
+[ Upstream commit 83c088148c8e5c439eec6c7651692f797547e1a8 ]
+
+Replace literals under drivers/pci/ with PCI_HEADER_TYPE_MASK,
+PCI_HEADER_TYPE_NORMAL, and PCI_HEADER_TYPE_MFD.
+
+Also replace !! boolean conversions with FIELD_GET().
+
+Link: https://lore.kernel.org/r/20231003125300.5541-4-ilpo.jarvinen@linux.intel.com
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com> # for Renesas R-Car
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/dwc/pci-layerscape.c | 2 +-
+ .../controller/mobiveil/pcie-mobiveil-host.c | 2 +-
+ drivers/pci/controller/pcie-iproc.c | 2 +-
+ drivers/pci/controller/pcie-rcar-ep.c | 2 +-
+ drivers/pci/controller/pcie-rcar-host.c | 2 +-
+ drivers/pci/controller/vmd.c | 2 +-
+ drivers/pci/hotplug/cpqphp_ctrl.c | 6 ++---
+ drivers/pci/hotplug/cpqphp_pci.c | 22 +++++++++----------
+ drivers/pci/hotplug/ibmphp.h | 5 +++--
+ drivers/pci/hotplug/ibmphp_pci.c | 2 +-
+ drivers/pci/pci.c | 2 +-
+ drivers/pci/quirks.c | 6 ++---
+ 12 files changed, 28 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/pci/controller/dwc/pci-layerscape.c b/drivers/pci/controller/dwc/pci-layerscape.c
+index b931d597656f6..37956e09c65bd 100644
+--- a/drivers/pci/controller/dwc/pci-layerscape.c
++++ b/drivers/pci/controller/dwc/pci-layerscape.c
+@@ -58,7 +58,7 @@ static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
+ u32 header_type;
+
+ header_type = ioread8(pci->dbi_base + PCI_HEADER_TYPE);
+- header_type &= 0x7f;
++ header_type &= PCI_HEADER_TYPE_MASK;
+
+ return header_type == PCI_HEADER_TYPE_BRIDGE;
+ }
+diff --git a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
+index 45b97a4b14dbd..32951f7d6d6d6 100644
+--- a/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
++++ b/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
+@@ -539,7 +539,7 @@ static bool mobiveil_pcie_is_bridge(struct mobiveil_pcie *pcie)
+ u32 header_type;
+
+ header_type = mobiveil_csr_readb(pcie, PCI_HEADER_TYPE);
+- header_type &= 0x7f;
++ header_type &= PCI_HEADER_TYPE_MASK;
+
+ return header_type == PCI_HEADER_TYPE_BRIDGE;
+ }
+diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c
+index bd1c98b688516..97f739a2c9f8f 100644
+--- a/drivers/pci/controller/pcie-iproc.c
++++ b/drivers/pci/controller/pcie-iproc.c
+@@ -783,7 +783,7 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie)
+
+ /* make sure we are not in EP mode */
+ iproc_pci_raw_config_read32(pcie, 0, PCI_HEADER_TYPE, 1, &hdr_type);
+- if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) {
++ if ((hdr_type & PCI_HEADER_TYPE_MASK) != PCI_HEADER_TYPE_BRIDGE) {
+ dev_err(dev, "in EP mode, hdr=%#02x\n", hdr_type);
+ return -EFAULT;
+ }
+diff --git a/drivers/pci/controller/pcie-rcar-ep.c b/drivers/pci/controller/pcie-rcar-ep.c
+index f9682df1da619..7034c0ff23d0d 100644
+--- a/drivers/pci/controller/pcie-rcar-ep.c
++++ b/drivers/pci/controller/pcie-rcar-ep.c
+@@ -43,7 +43,7 @@ static void rcar_pcie_ep_hw_init(struct rcar_pcie *pcie)
+ rcar_rmw32(pcie, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
+ rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS),
+ PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ENDPOINT << 4);
+- rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f,
++ rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), PCI_HEADER_TYPE_MASK,
+ PCI_HEADER_TYPE_NORMAL);
+
+ /* Write out the physical slot number = 0 */
+diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c
+index 88975e40ee2fb..bf7cc0b6a6957 100644
+--- a/drivers/pci/controller/pcie-rcar-host.c
++++ b/drivers/pci/controller/pcie-rcar-host.c
+@@ -460,7 +460,7 @@ static int rcar_pcie_hw_init(struct rcar_pcie *pcie)
+ rcar_rmw32(pcie, REXPCAP(0), 0xff, PCI_CAP_ID_EXP);
+ rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS),
+ PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4);
+- rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f,
++ rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), PCI_HEADER_TYPE_MASK,
+ PCI_HEADER_TYPE_BRIDGE);
+
+ /* Enable data link layer active state reporting */
+diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
+index 6ac0afae0ca18..2af46e6587aff 100644
+--- a/drivers/pci/controller/vmd.c
++++ b/drivers/pci/controller/vmd.c
+@@ -527,7 +527,7 @@ static void vmd_domain_reset(struct vmd_dev *vmd)
+
+ hdr_type = readb(base + PCI_HEADER_TYPE);
+
+- functions = (hdr_type & 0x80) ? 8 : 1;
++ functions = (hdr_type & PCI_HEADER_TYPE_MFD) ? 8 : 1;
+ for (fn = 0; fn < functions; fn++) {
+ base = vmd->cfgbar + PCIE_ECAM_OFFSET(bus,
+ PCI_DEVFN(dev, fn), 0);
+diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
+index e429ecddc8feb..c01968ef0bd7b 100644
+--- a/drivers/pci/hotplug/cpqphp_ctrl.c
++++ b/drivers/pci/hotplug/cpqphp_ctrl.c
+@@ -2059,7 +2059,7 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func)
+ return rc;
+
+ /* If it's a bridge, check the VGA Enable bit */
+- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
++ if ((header_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) {
+ rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
+ if (rc)
+ return rc;
+@@ -2342,7 +2342,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
+ if (rc)
+ return rc;
+
+- if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
++ if ((temp_byte & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) {
+ /* set Primary bus */
+ dbg("set Primary bus = %d\n", func->bus);
+ rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
+@@ -2739,7 +2739,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
+ * PCI_BRIDGE_CTL_SERR |
+ * PCI_BRIDGE_CTL_NO_ISA */
+ rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+- } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
++ } else if ((temp_byte & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_NORMAL) {
+ /* Standard device */
+ rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code);
+
+diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
+index 3b248426a9f42..e9f1fb333a718 100644
+--- a/drivers/pci/hotplug/cpqphp_pci.c
++++ b/drivers/pci/hotplug/cpqphp_pci.c
+@@ -363,7 +363,7 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug)
+ return rc;
+
+ /* If multi-function device, set max_functions to 8 */
+- if (header_type & 0x80)
++ if (header_type & PCI_HEADER_TYPE_MFD)
+ max_functions = 8;
+ else
+ max_functions = 1;
+@@ -372,7 +372,7 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug)
+
+ do {
+ DevError = 0;
+- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
++ if ((header_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) {
+ /* Recurse the subordinate bus
+ * get the subordinate bus number
+ */
+@@ -487,13 +487,13 @@ int cpqhp_save_slot_config(struct controller *ctrl, struct pci_func *new_slot)
+ pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), 0x0B, &class_code);
+ pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, 0), PCI_HEADER_TYPE, &header_type);
+
+- if (header_type & 0x80) /* Multi-function device */
++ if (header_type & PCI_HEADER_TYPE_MFD)
+ max_functions = 8;
+ else
+ max_functions = 1;
+
+ while (function < max_functions) {
+- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
++ if ((header_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) {
+ /* Recurse the subordinate bus */
+ pci_bus_read_config_byte(ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_SECONDARY_BUS, &secondary_bus);
+
+@@ -571,7 +571,7 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func *func)
+ /* Check for Bridge */
+ pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+
+- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
++ if ((header_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) {
+ pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
+
+ sub_bus = (int) secondary_bus;
+@@ -625,7 +625,7 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func *func)
+
+ } /* End of base register loop */
+
+- } else if ((header_type & 0x7F) == 0x00) {
++ } else if ((header_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_NORMAL) {
+ /* Figure out IO and memory base lengths */
+ for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
+ temp_register = 0xFFFFFFFF;
+@@ -723,7 +723,7 @@ int cpqhp_save_used_resources(struct controller *ctrl, struct pci_func *func)
+ /* Check for Bridge */
+ pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+
+- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
++ if ((header_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) {
+ /* Clear Bridge Control Register */
+ command = 0x00;
+ pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
+@@ -858,7 +858,7 @@ int cpqhp_save_used_resources(struct controller *ctrl, struct pci_func *func)
+ }
+ } /* End of base register loop */
+ /* Standard header */
+- } else if ((header_type & 0x7F) == 0x00) {
++ } else if ((header_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_NORMAL) {
+ /* Figure out IO and memory base lengths */
+ for (cloop = 0x10; cloop <= 0x24; cloop += 4) {
+ pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
+@@ -975,7 +975,7 @@ int cpqhp_configure_board(struct controller *ctrl, struct pci_func *func)
+ pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+
+ /* If this is a bridge device, restore subordinate devices */
+- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
++ if ((header_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) {
+ pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
+
+ sub_bus = (int) secondary_bus;
+@@ -1067,7 +1067,7 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func)
+ /* Check for Bridge */
+ pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
+
+- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
++ if ((header_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) {
+ /* In order to continue checking, we must program the
+ * bus registers in the bridge to respond to accesses
+ * for its subordinate bus(es)
+@@ -1090,7 +1090,7 @@ int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func)
+
+ }
+ /* Check to see if it is a standard config header */
+- else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
++ else if ((header_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_NORMAL) {
+ /* Check subsystem vendor and ID */
+ pci_bus_read_config_dword(pci_bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &temp_register);
+
+diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h
+index 41eafe511210f..c248a09be7b5d 100644
+--- a/drivers/pci/hotplug/ibmphp.h
++++ b/drivers/pci/hotplug/ibmphp.h
+@@ -17,6 +17,7 @@
+ */
+
+ #include <linux/pci_hotplug.h>
++#include <linux/pci_regs.h>
+
+ extern int ibmphp_debug;
+
+@@ -286,8 +287,8 @@ int ibmphp_register_pci(void);
+
+ /* pci specific defines */
+ #define PCI_VENDOR_ID_NOTVALID 0xFFFF
+-#define PCI_HEADER_TYPE_MULTIDEVICE 0x80
+-#define PCI_HEADER_TYPE_MULTIBRIDGE 0x81
++#define PCI_HEADER_TYPE_MULTIDEVICE (PCI_HEADER_TYPE_MFD|PCI_HEADER_TYPE_NORMAL)
++#define PCI_HEADER_TYPE_MULTIBRIDGE (PCI_HEADER_TYPE_MFD|PCI_HEADER_TYPE_BRIDGE)
+
+ #define LATENCY 0x64
+ #define CACHE 64
+diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
+index 50038e5f9ca40..eeb412cbd9fe3 100644
+--- a/drivers/pci/hotplug/ibmphp_pci.c
++++ b/drivers/pci/hotplug/ibmphp_pci.c
+@@ -1087,7 +1087,7 @@ static struct res_needed *scan_behind_bridge(struct pci_func *func, u8 busno)
+ pci_bus_read_config_dword(ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class);
+
+ debug("hdr_type behind the bridge is %x\n", hdr_type);
+- if ((hdr_type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) {
++ if ((hdr_type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) {
+ err("embedded bridges not supported for hot-plugging.\n");
+ amount->not_correct = 1;
+ return amount;
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index 06fc6f532d6c4..dae9d9e2826f0 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -534,7 +534,7 @@ u8 pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
+
+ pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type);
+
+- pos = __pci_bus_find_cap_start(bus, devfn, hdr_type & 0x7f);
++ pos = __pci_bus_find_cap_start(bus, devfn, hdr_type & PCI_HEADER_TYPE_MASK);
+ if (pos)
+ pos = __pci_find_next_cap(bus, devfn, pos, cap);
+
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index b3976dcb71f10..675f77ac1968d 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -1849,8 +1849,8 @@ static void quirk_jmicron_ata(struct pci_dev *pdev)
+
+ /* Update pdev accordingly */
+ pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr);
+- pdev->hdr_type = hdr & 0x7f;
+- pdev->multifunction = !!(hdr & 0x80);
++ pdev->hdr_type = hdr & PCI_HEADER_TYPE_MASK;
++ pdev->multifunction = FIELD_GET(PCI_HEADER_TYPE_MFD, hdr);
+
+ pci_read_config_dword(pdev, PCI_CLASS_REVISION, &class);
+ pdev->class = class >> 8;
+@@ -5710,7 +5710,7 @@ static void quirk_nvidia_hda(struct pci_dev *gpu)
+
+ /* The GPU becomes a multi-function device when the HDA is enabled */
+ pci_read_config_byte(gpu, PCI_HEADER_TYPE, &hdr_type);
+- gpu->multifunction = !!(hdr_type & 0x80);
++ gpu->multifunction = FIELD_GET(PCI_HEADER_TYPE_MFD, hdr_type);
+ }
+ DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
+ PCI_BASE_CLASS_DISPLAY, 16, quirk_nvidia_hda);
+--
+2.43.0
+
--- /dev/null
+From b37ae317311ca84849536995e9eb6239c7341dcf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Apr 2024 09:10:46 -0500
+Subject: platform/x86/amd/pmc: Extend Framework 13 quirk to more BIOSes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit f609e7b1b49e4d15cf107d2069673ee63860c398 ]
+
+BIOS 03.05 still hasn't fixed the spurious IRQ1 issue. As it's still
+being worked on there is still a possibility that it won't need to
+apply to future BIOS releases.
+
+Add a quirk for BIOS 03.05 as well.
+
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20240410141046.433-1-mario.limonciello@amd.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/amd/pmc/pmc-quirks.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/platform/x86/amd/pmc/pmc-quirks.c b/drivers/platform/x86/amd/pmc/pmc-quirks.c
+index b456370166b6b..b4f49720c87f6 100644
+--- a/drivers/platform/x86/amd/pmc/pmc-quirks.c
++++ b/drivers/platform/x86/amd/pmc/pmc-quirks.c
+@@ -208,6 +208,15 @@ static const struct dmi_system_id fwbug_list[] = {
+ DMI_MATCH(DMI_BIOS_VERSION, "03.03"),
+ }
+ },
++ {
++ .ident = "Framework Laptop 13 (Phoenix)",
++ .driver_data = &quirk_spurious_8042,
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"),
++ DMI_MATCH(DMI_BIOS_VERSION, "03.05"),
++ }
++ },
+ {}
+ };
+
+--
+2.43.0
+
drm-nv04-fix-out-of-bounds-access.patch
drm-panel-visionox-rm69299-don-t-unregister-dsi-devi.patch
drm-radeon-make-fstrict-flex-arrays-3-happy.patch
+alsa-scarlett2-move-usb-ids-out-from-device_info-str.patch
+alsa-scarlett2-add-support-for-clarett-8pre-usb.patch
+asoc-ti-convert-pandora-asoc-to-gpio-descriptors.patch
+usb-pci-quirks-group-amd-specific-quirk-code-togethe.patch
+usb-pci-quirks-handle-has_ioport-dependency-for-amd-.patch
+usb-pci-quirks-handle-has_ioport-dependency-for-uhci.patch
+pci-add-pci_header_type_mfd-definition.patch
+pci-use-pci_header_type_-instead-of-literals.patch
+alsa-scarlett2-default-mixer-driver-to-enabled.patch
+alsa-scarlett2-add-correct-product-series-name-to-me.patch
+alsa-scarlett2-add-focusrite-clarett-2pre-and-4pre-s.patch
+alsa-scarlett2-add-focusrite-clarett-2pre-and-4pre-u.patch
+pci-dpc-use-field_get.patch
+pci-simplify-pcie_capability_clear_and_set_word-to-..patch
+alsa-scarlett2-rename-scarlett_gen2-to-scarlett2.patch
+drm-panel-orientation-quirks-add-quirk-for-lenovo-le.patch
+usb-xhci-add-timeout-argument-in-address_device-usb-.patch
+usb-new-quirk-to-reduce-the-set_address-request-time.patch
+platform-x86-amd-pmc-extend-framework-13-quirk-to-mo.patch
+interconnect-don-t-access-req_list-while-it-s-being-.patch
+clk-remove-prepare_lock-hold-assertion-in-__clk_rele.patch
+clk-initialize-struct-clk_core-kref-earlier.patch
+clk-get-runtime-pm-before-walking-tree-during-disabl.patch
+clk-show-active-consumers-of-clocks-in-debugfs.patch
+clk-get-runtime-pm-before-walking-tree-for-clk_summa.patch
+clk-mediatek-do-a-runtime-pm-get-on-controllers-duri.patch
+x86-bugs-fix-bhi-retpoline-check.patch
+x86-cpufeatures-fix-dependencies-for-gfni-vaes-and-v.patch
--- /dev/null
+From 62e8bd54dc1548022c2db1bc175fa5c649f10751 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Oct 2023 17:20:29 +0200
+Subject: usb: new quirk to reduce the SET_ADDRESS request timeout
+
+From: Hardik Gajjar <hgajjar@de.adit-jv.com>
+
+[ Upstream commit 5a1ccf0c72cf917ff3ccc131d1bb8d19338ffe52 ]
+
+This patch introduces a new USB quirk,
+USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT, which modifies the timeout value
+for the SET_ADDRESS request. The standard timeout for USB request/command
+is 5000 ms, as recommended in the USB 3.2 specification (section 9.2.6.1).
+
+However, certain scenarios, such as connecting devices through an APTIV
+hub, can lead to timeout errors when the device enumerates as full speed
+initially and later switches to high speed during chirp negotiation.
+
+In such cases, USB analyzer logs reveal that the bus suspends for
+5 seconds due to incorrect chirp parsing and resumes only after two
+consecutive timeout errors trigger a hub driver reset.
+
+Packet(54) Dir(?) Full Speed J(997.100 us) Idle( 2.850 us)
+_______| Time Stamp(28 . 105 910 682)
+_______|_____________________________________________________________Ch0
+Packet(55) Dir(?) Full Speed J(997.118 us) Idle( 2.850 us)
+_______| Time Stamp(28 . 106 910 632)
+_______|_____________________________________________________________Ch0
+Packet(56) Dir(?) Full Speed J(399.650 us) Idle(222.582 us)
+_______| Time Stamp(28 . 107 910 600)
+_______|_____________________________________________________________Ch0
+Packet(57) Dir Chirp J( 23.955 ms) Idle(115.169 ms)
+_______| Time Stamp(28 . 108 532 832)
+_______|_____________________________________________________________Ch0
+Packet(58) Dir(?) Full Speed J (Suspend)( 5.347 sec) Idle( 5.366 us)
+_______| Time Stamp(28 . 247 657 600)
+_______|_____________________________________________________________Ch0
+
+This 5-second delay in device enumeration is undesirable, particularly
+in automotive applications where quick enumeration is crucial
+(ideally within 3 seconds).
+
+The newly introduced quirks provide the flexibility to align with a
+3-second time limit, as required in specific contexts like automotive
+applications.
+
+By reducing the SET_ADDRESS request timeout to 500 ms, the
+system can respond more swiftly to errors, initiate rapid recovery, and
+ensure efficient device enumeration. This change is vital for scenarios
+where rapid smartphone enumeration and screen projection are essential.
+
+To use the quirk, please write "vendor_id:product_id:p" to
+/sys/bus/usb/drivers/hub/module/parameter/quirks
+
+For example,
+echo "0x2c48:0x0132:p" > /sys/bus/usb/drivers/hub/module/parameters/quirks"
+
+Signed-off-by: Hardik Gajjar <hgajjar@de.adit-jv.com>
+Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/r/20231027152029.104363-2-hgajjar@de.adit-jv.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/admin-guide/kernel-parameters.txt | 3 +++
+ drivers/usb/core/hub.c | 15 +++++++++++++--
+ drivers/usb/core/quirks.c | 7 +++++++
+ include/linux/usb/quirks.h | 3 +++
+ 4 files changed, 26 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index 4cd15aee16c20..66dfc348043d6 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -6853,6 +6853,9 @@
+ pause after every control message);
+ o = USB_QUIRK_HUB_SLOW_RESET (Hub needs extra
+ delay after resetting its port);
++ p = USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT
++ (Reduce timeout of the SET_ADDRESS
++ request from 5000 ms to 500 ms);
+ Example: quirks=0781:5580:bk,0a5c:5834:gij
+
+ usbhid.mousepoll=
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 73ab30e0da774..7417972202b8b 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -60,6 +60,12 @@
+ #define USB_PING_RESPONSE_TIME 400 /* ns */
+ #define USB_REDUCE_FRAME_INTR_BINTERVAL 9
+
++/*
++ * The SET_ADDRESS request timeout will be 500 ms when
++ * USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT quirk flag is set.
++ */
++#define USB_SHORT_SET_ADDRESS_REQ_TIMEOUT 500 /* ms */
++
+ /* Protect struct usb_device->state and ->children members
+ * Note: Both are also protected by ->dev.sem, except that ->state can
+ * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
+@@ -4663,7 +4669,12 @@ EXPORT_SYMBOL_GPL(usb_ep0_reinit);
+ static int hub_set_address(struct usb_device *udev, int devnum)
+ {
+ int retval;
++ unsigned int timeout_ms = USB_CTRL_SET_TIMEOUT;
+ struct usb_hcd *hcd = bus_to_hcd(udev->bus);
++ struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
++
++ if (hub->hdev->quirks & USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT)
++ timeout_ms = USB_SHORT_SET_ADDRESS_REQ_TIMEOUT;
+
+ /*
+ * The host controller will choose the device address,
+@@ -4676,11 +4687,11 @@ static int hub_set_address(struct usb_device *udev, int devnum)
+ if (udev->state != USB_STATE_DEFAULT)
+ return -EINVAL;
+ if (hcd->driver->address_device)
+- retval = hcd->driver->address_device(hcd, udev, USB_CTRL_SET_TIMEOUT);
++ retval = hcd->driver->address_device(hcd, udev, timeout_ms);
+ else
+ retval = usb_control_msg(udev, usb_sndaddr0pipe(),
+ USB_REQ_SET_ADDRESS, 0, devnum, 0,
+- NULL, 0, USB_CTRL_SET_TIMEOUT);
++ NULL, 0, timeout_ms);
+ if (retval == 0) {
+ update_devnum(udev, devnum);
+ /* Device now using proper address. */
+diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
+index 15e9bd180a1d2..b4783574b8e66 100644
+--- a/drivers/usb/core/quirks.c
++++ b/drivers/usb/core/quirks.c
+@@ -138,6 +138,9 @@ static int quirks_param_set(const char *value, const struct kernel_param *kp)
+ case 'o':
+ flags |= USB_QUIRK_HUB_SLOW_RESET;
+ break;
++ case 'p':
++ flags |= USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT;
++ break;
+ /* Ignore unrecognized flag characters */
+ }
+ }
+@@ -527,6 +530,10 @@ static const struct usb_device_id usb_quirk_list[] = {
+
+ { USB_DEVICE(0x2386, 0x350e), .driver_info = USB_QUIRK_NO_LPM },
+
++ /* APTIV AUTOMOTIVE HUB */
++ { USB_DEVICE(0x2c48, 0x0132), .driver_info =
++ USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT },
++
+ /* DJI CineSSD */
+ { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM },
+
+diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h
+index eeb7c2157c72f..59409c1fc3dee 100644
+--- a/include/linux/usb/quirks.h
++++ b/include/linux/usb/quirks.h
+@@ -72,4 +72,7 @@
+ /* device has endpoints that should be ignored */
+ #define USB_QUIRK_ENDPOINT_IGNORE BIT(15)
+
++/* short SET_ADDRESS request timeout */
++#define USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT BIT(16)
++
+ #endif /* __LINUX_USB_QUIRKS_H */
+--
+2.43.0
+
--- /dev/null
+From 952f4e84ead9ecf5b11d30bdc72d08c391ef630f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Sep 2023 14:56:51 +0200
+Subject: usb: pci-quirks: group AMD specific quirk code together
+
+From: Niklas Schnelle <schnelle@linux.ibm.com>
+
+[ Upstream commit 7ca9f9ba8aa7380dee5dd8346b57bbaf198b075a ]
+
+A follow on patch will introduce CONFIG_USB_PCI_AMD governing the AMD
+quirk and adding its compile time dependency on HAS_IOPORT. In order to
+minimize the number of #ifdefs in C files and make that patch easier
+to read first group the code together. This is pure code movement
+no functional change is intended.
+
+Co-developed-by: Arnd Bergmann <arnd@kernel.org>
+Signed-off-by: Arnd Bergmann <arnd@kernel.org>
+Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
+Link: https://lore.kernel.org/r/20230911125653.1393895-2-schnelle@linux.ibm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/pci-quirks.c | 119 +++++++++++++++++-----------------
+ drivers/usb/host/pci-quirks.h | 14 ++--
+ 2 files changed, 68 insertions(+), 65 deletions(-)
+
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index 2665832f9addf..5e06fad82a228 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -60,6 +60,22 @@
+ #define EHCI_USBLEGCTLSTS 4 /* legacy control/status */
+ #define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */
+
++/* ASMEDIA quirk use */
++#define ASMT_DATA_WRITE0_REG 0xF8
++#define ASMT_DATA_WRITE1_REG 0xFC
++#define ASMT_CONTROL_REG 0xE0
++#define ASMT_CONTROL_WRITE_BIT 0x02
++#define ASMT_WRITEREG_CMD 0x10423
++#define ASMT_FLOWCTL_ADDR 0xFA30
++#define ASMT_FLOWCTL_DATA 0xBA
++#define ASMT_PSEUDO_DATA 0
++
++/* Intel quirk use */
++#define USB_INTEL_XUSB2PR 0xD0
++#define USB_INTEL_USB2PRM 0xD4
++#define USB_INTEL_USB3_PSSEN 0xD8
++#define USB_INTEL_USB3PRM 0xDC
++
+ /* AMD quirk use */
+ #define AB_REG_BAR_LOW 0xe0
+ #define AB_REG_BAR_HIGH 0xe1
+@@ -93,21 +109,6 @@
+ #define NB_PIF0_PWRDOWN_0 0x01100012
+ #define NB_PIF0_PWRDOWN_1 0x01100013
+
+-#define USB_INTEL_XUSB2PR 0xD0
+-#define USB_INTEL_USB2PRM 0xD4
+-#define USB_INTEL_USB3_PSSEN 0xD8
+-#define USB_INTEL_USB3PRM 0xDC
+-
+-/* ASMEDIA quirk use */
+-#define ASMT_DATA_WRITE0_REG 0xF8
+-#define ASMT_DATA_WRITE1_REG 0xFC
+-#define ASMT_CONTROL_REG 0xE0
+-#define ASMT_CONTROL_WRITE_BIT 0x02
+-#define ASMT_WRITEREG_CMD 0x10423
+-#define ASMT_FLOWCTL_ADDR 0xFA30
+-#define ASMT_FLOWCTL_DATA 0xBA
+-#define ASMT_PSEUDO_DATA 0
+-
+ /*
+ * amd_chipset_gen values represent AMD different chipset generations
+ */
+@@ -458,50 +459,6 @@ void usb_amd_quirk_pll_disable(void)
+ }
+ EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable);
+
+-static int usb_asmedia_wait_write(struct pci_dev *pdev)
+-{
+- unsigned long retry_count;
+- unsigned char value;
+-
+- for (retry_count = 1000; retry_count > 0; --retry_count) {
+-
+- pci_read_config_byte(pdev, ASMT_CONTROL_REG, &value);
+-
+- if (value == 0xff) {
+- dev_err(&pdev->dev, "%s: check_ready ERROR", __func__);
+- return -EIO;
+- }
+-
+- if ((value & ASMT_CONTROL_WRITE_BIT) == 0)
+- return 0;
+-
+- udelay(50);
+- }
+-
+- dev_warn(&pdev->dev, "%s: check_write_ready timeout", __func__);
+- return -ETIMEDOUT;
+-}
+-
+-void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev)
+-{
+- if (usb_asmedia_wait_write(pdev) != 0)
+- return;
+-
+- /* send command and address to device */
+- pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_WRITEREG_CMD);
+- pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_FLOWCTL_ADDR);
+- pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
+-
+- if (usb_asmedia_wait_write(pdev) != 0)
+- return;
+-
+- /* send data to device */
+- pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_FLOWCTL_DATA);
+- pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_PSEUDO_DATA);
+- pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
+-}
+-EXPORT_SYMBOL_GPL(usb_asmedia_modifyflowcontrol);
+-
+ void usb_amd_quirk_pll_enable(void)
+ {
+ usb_amd_quirk_pll(0);
+@@ -631,6 +588,50 @@ bool usb_amd_pt_check_port(struct device *device, int port)
+ }
+ EXPORT_SYMBOL_GPL(usb_amd_pt_check_port);
+
++static int usb_asmedia_wait_write(struct pci_dev *pdev)
++{
++ unsigned long retry_count;
++ unsigned char value;
++
++ for (retry_count = 1000; retry_count > 0; --retry_count) {
++
++ pci_read_config_byte(pdev, ASMT_CONTROL_REG, &value);
++
++ if (value == 0xff) {
++ dev_err(&pdev->dev, "%s: check_ready ERROR", __func__);
++ return -EIO;
++ }
++
++ if ((value & ASMT_CONTROL_WRITE_BIT) == 0)
++ return 0;
++
++ udelay(50);
++ }
++
++ dev_warn(&pdev->dev, "%s: check_write_ready timeout", __func__);
++ return -ETIMEDOUT;
++}
++
++void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev)
++{
++ if (usb_asmedia_wait_write(pdev) != 0)
++ return;
++
++ /* send command and address to device */
++ pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_WRITEREG_CMD);
++ pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_FLOWCTL_ADDR);
++ pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
++
++ if (usb_asmedia_wait_write(pdev) != 0)
++ return;
++
++ /* send data to device */
++ pci_write_config_dword(pdev, ASMT_DATA_WRITE0_REG, ASMT_FLOWCTL_DATA);
++ pci_write_config_dword(pdev, ASMT_DATA_WRITE1_REG, ASMT_PSEUDO_DATA);
++ pci_write_config_byte(pdev, ASMT_CONTROL_REG, ASMT_CONTROL_WRITE_BIT);
++}
++EXPORT_SYMBOL_GPL(usb_asmedia_modifyflowcontrol);
++
+ /*
+ * Make sure the controller is completely inactive, unable to
+ * generate interrupts or do DMA.
+diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
+index e729de21fad7a..cde2263a9d2e4 100644
+--- a/drivers/usb/host/pci-quirks.h
++++ b/drivers/usb/host/pci-quirks.h
+@@ -3,8 +3,6 @@
+ #define __LINUX_USB_PCI_QUIRKS_H
+
+ #ifdef CONFIG_USB_PCI
+-void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
+-int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
+ int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev);
+ bool usb_amd_hang_symptom_quirk(void);
+ bool usb_amd_prefetch_quirk(void);
+@@ -12,23 +10,27 @@ void usb_amd_dev_put(void);
+ bool usb_amd_quirk_pll_check(void);
+ void usb_amd_quirk_pll_disable(void);
+ void usb_amd_quirk_pll_enable(void);
++void sb800_prefetch(struct device *dev, int on);
++bool usb_amd_pt_check_port(struct device *device, int port);
++
++void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
++int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
+ void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
+ void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
+ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
+-void sb800_prefetch(struct device *dev, int on);
+-bool usb_amd_pt_check_port(struct device *device, int port);
+ #else
+ struct pci_dev;
+ static inline void usb_amd_quirk_pll_disable(void) {}
+ static inline void usb_amd_quirk_pll_enable(void) {}
+-static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}
+ static inline void usb_amd_dev_put(void) {}
+-static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
+ static inline void sb800_prefetch(struct device *dev, int on) {}
+ static inline bool usb_amd_pt_check_port(struct device *device, int port)
+ {
+ return false;
+ }
++
++static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}
++static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
+ #endif /* CONFIG_USB_PCI */
+
+ #endif /* __LINUX_USB_PCI_QUIRKS_H */
+--
+2.43.0
+
--- /dev/null
+From 0f70138cda5d225e8d81ea1d734d20e6b11e7478 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Sep 2023 14:56:52 +0200
+Subject: usb: pci-quirks: handle HAS_IOPORT dependency for AMD quirk
+
+From: Niklas Schnelle <schnelle@linux.ibm.com>
+
+[ Upstream commit 52e24f8c0a102ac76649c6b71224fadcc82bd5da ]
+
+In a future patch HAS_IOPORT=n will result in inb()/outb() and friends
+not being declared. In the pci-quirks case the I/O port acceses are
+used in the quirks for several AMD south bridges, Add a config option
+for the AMD quirks to depend on HAS_IOPORT and #ifdef the quirk code.
+
+Co-developed-by: Arnd Bergmann <arnd@kernel.org>
+Signed-off-by: Arnd Bergmann <arnd@kernel.org>
+Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
+Link: https://lore.kernel.org/r/20230911125653.1393895-3-schnelle@linux.ibm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/Kconfig | 10 ++++++++++
+ drivers/usb/core/hcd-pci.c | 3 +--
+ drivers/usb/host/pci-quirks.c | 2 ++
+ drivers/usb/host/pci-quirks.h | 30 ++++++++++++++++++++++--------
+ include/linux/usb/hcd.h | 17 +++++++++++++++++
+ 5 files changed, 52 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
+index 7f33bcc315f27..abf8c6cdea9ea 100644
+--- a/drivers/usb/Kconfig
++++ b/drivers/usb/Kconfig
+@@ -91,6 +91,16 @@ config USB_PCI
+ If you have such a device you may say N here and PCI related code
+ will not be built in the USB driver.
+
++config USB_PCI_AMD
++ bool "AMD PCI USB host support"
++ depends on USB_PCI && HAS_IOPORT
++ default X86 || MACH_LOONGSON64 || PPC_PASEMI
++ help
++ Enable workarounds for USB implementation quirks in SB600/SB700/SB800
++ and later south bridge implementations. These are common on x86 PCs
++ with AMD CPUs but rarely used elsewhere, with the exception of a few
++ powerpc and mips desktop machines.
++
+ if USB
+
+ source "drivers/usb/core/Kconfig"
+diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
+index 990280688b254..ee3156f495338 100644
+--- a/drivers/usb/core/hcd-pci.c
++++ b/drivers/usb/core/hcd-pci.c
+@@ -206,8 +206,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct hc_driver *driver)
+ goto free_irq_vectors;
+ }
+
+- hcd->amd_resume_bug = (usb_hcd_amd_remote_wakeup_quirk(dev) &&
+- driver->flags & (HCD_USB11 | HCD_USB3)) ? 1 : 0;
++ hcd->amd_resume_bug = usb_hcd_amd_resume_bug(dev, driver);
+
+ if (driver->flags & HCD_MEMORY) {
+ /* EHCI, OHCI */
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index 5e06fad82a228..10813096d00c6 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -76,6 +76,7 @@
+ #define USB_INTEL_USB3_PSSEN 0xD8
+ #define USB_INTEL_USB3PRM 0xDC
+
++#ifdef CONFIG_USB_PCI_AMD
+ /* AMD quirk use */
+ #define AB_REG_BAR_LOW 0xe0
+ #define AB_REG_BAR_HIGH 0xe1
+@@ -587,6 +588,7 @@ bool usb_amd_pt_check_port(struct device *device, int port)
+ return !(value & BIT(port_shift));
+ }
+ EXPORT_SYMBOL_GPL(usb_amd_pt_check_port);
++#endif /* CONFIG_USB_PCI_AMD */
+
+ static int usb_asmedia_wait_write(struct pci_dev *pdev)
+ {
+diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
+index cde2263a9d2e4..a5230b0b9e913 100644
+--- a/drivers/usb/host/pci-quirks.h
++++ b/drivers/usb/host/pci-quirks.h
+@@ -2,7 +2,7 @@
+ #ifndef __LINUX_USB_PCI_QUIRKS_H
+ #define __LINUX_USB_PCI_QUIRKS_H
+
+-#ifdef CONFIG_USB_PCI
++#ifdef CONFIG_USB_PCI_AMD
+ int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev);
+ bool usb_amd_hang_symptom_quirk(void);
+ bool usb_amd_prefetch_quirk(void);
+@@ -12,23 +12,37 @@ void usb_amd_quirk_pll_disable(void);
+ void usb_amd_quirk_pll_enable(void);
+ void sb800_prefetch(struct device *dev, int on);
+ bool usb_amd_pt_check_port(struct device *device, int port);
+-
+-void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
+-int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
+-void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
+-void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
+-void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
+ #else
+-struct pci_dev;
++static inline bool usb_amd_hang_symptom_quirk(void)
++{
++ return false;
++};
++static inline bool usb_amd_prefetch_quirk(void)
++{
++ return false;
++}
+ static inline void usb_amd_quirk_pll_disable(void) {}
+ static inline void usb_amd_quirk_pll_enable(void) {}
+ static inline void usb_amd_dev_put(void) {}
++static inline bool usb_amd_quirk_pll_check(void)
++{
++ return false;
++}
+ static inline void sb800_prefetch(struct device *dev, int on) {}
+ static inline bool usb_amd_pt_check_port(struct device *device, int port)
+ {
+ return false;
+ }
++#endif /* CONFIG_USB_PCI_AMD */
+
++#ifdef CONFIG_USB_PCI
++void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
++int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
++void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev);
++void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev);
++void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
++#else
++struct pci_dev;
+ static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}
+ static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
+ #endif /* CONFIG_USB_PCI */
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 61d4f0b793dcd..00724b4f6e122 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -484,8 +484,25 @@ extern int usb_hcd_pci_probe(struct pci_dev *dev,
+ extern void usb_hcd_pci_remove(struct pci_dev *dev);
+ extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
+
++#ifdef CONFIG_USB_PCI_AMD
+ extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev);
+
++static inline bool usb_hcd_amd_resume_bug(struct pci_dev *dev,
++ const struct hc_driver *driver)
++{
++ if (!usb_hcd_amd_remote_wakeup_quirk(dev))
++ return false;
++ if (driver->flags & (HCD_USB11 | HCD_USB3))
++ return true;
++ return false;
++}
++#else /* CONFIG_USB_PCI_AMD */
++static inline bool usb_hcd_amd_resume_bug(struct pci_dev *dev,
++ const struct hc_driver *driver)
++{
++ return false;
++}
++#endif
+ extern const struct dev_pm_ops usb_hcd_pci_pm_ops;
+ #endif /* CONFIG_USB_PCI */
+
+--
+2.43.0
+
--- /dev/null
+From 62308e4a79ca6840e7c164e05a067e5a9f87d504 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Sep 2023 14:56:53 +0200
+Subject: usb: pci-quirks: handle HAS_IOPORT dependency for UHCI handoff
+
+From: Niklas Schnelle <schnelle@linux.ibm.com>
+
+[ Upstream commit 358ad297e379ff548247e3e24c6619559942bfdd ]
+
+In a future patch HAS_IOPORT=n will result in inb()/outb() and friends
+not being declared. With the AMD quirk handled USB PCI quirks still use
+inw() in uhci_check_and_reset_hc() and thus indirectly in
+quirk_usb_handoff_uhci(). Handle this by conditionally compiling
+uhci_check_and_reset_hc() and stubbing out quirk_usb_handoff_uhci() when
+HAS_IOPORT is not available.
+
+Co-developed-by: Arnd Bergmann <arnd@kernel.org>
+Signed-off-by: Arnd Bergmann <arnd@kernel.org>
+Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
+Link: https://lore.kernel.org/r/20230911125653.1393895-4-schnelle@linux.ibm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/pci-quirks.c | 23 ++++++++++++++++-------
+ 1 file changed, 16 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
+index 10813096d00c6..1f9c1b1435d86 100644
+--- a/drivers/usb/host/pci-quirks.c
++++ b/drivers/usb/host/pci-quirks.c
+@@ -634,6 +634,16 @@ void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev)
+ }
+ EXPORT_SYMBOL_GPL(usb_asmedia_modifyflowcontrol);
+
++static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
++{
++ u16 cmd;
++
++ return !pci_read_config_word(pdev, PCI_COMMAND, &cmd) && (cmd & mask);
++}
++
++#define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY)
++
++#if defined(CONFIG_HAS_IOPORT) && IS_ENABLED(CONFIG_USB_UHCI_HCD)
+ /*
+ * Make sure the controller is completely inactive, unable to
+ * generate interrupts or do DMA.
+@@ -715,14 +725,7 @@ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
+ }
+ EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc);
+
+-static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
+-{
+- u16 cmd;
+- return !pci_read_config_word(pdev, PCI_COMMAND, &cmd) && (cmd & mask);
+-}
+-
+ #define pio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_IO)
+-#define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY)
+
+ static void quirk_usb_handoff_uhci(struct pci_dev *pdev)
+ {
+@@ -742,6 +745,12 @@ static void quirk_usb_handoff_uhci(struct pci_dev *pdev)
+ uhci_check_and_reset_hc(pdev, base);
+ }
+
++#else /* defined(CONFIG_HAS_IOPORT && IS_ENABLED(CONFIG_USB_UHCI_HCD) */
++
++static void quirk_usb_handoff_uhci(struct pci_dev *pdev) {}
++
++#endif /* defined(CONFIG_HAS_IOPORT && IS_ENABLED(CONFIG_USB_UHCI_HCD) */
++
+ static int mmio_resource_enabled(struct pci_dev *pdev, int idx)
+ {
+ return pci_resource_start(pdev, idx) && mmio_enabled(pdev);
+--
+2.43.0
+
--- /dev/null
+From 747b080e78dddb4c56c6991d74381a2f5a98a484 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Oct 2023 17:20:28 +0200
+Subject: usb: xhci: Add timeout argument in address_device USB HCD callback
+
+From: Hardik Gajjar <hgajjar@de.adit-jv.com>
+
+[ Upstream commit a769154c7cac037914ba375ae88aae55b2c853e0 ]
+
+- The HCD address_device callback now accepts a user-defined timeout value
+ in milliseconds, providing better control over command execution times.
+- The default timeout value for the address_device command has been set
+ to 5000 ms, aligning with the USB 3.2 specification. However, this
+ timeout can be adjusted as needed.
+- The xhci_setup_device function has been updated to accept the timeout
+ value, allowing it to specify the maximum wait time for the command
+ operation to complete.
+- The hub driver has also been updated to accommodate the newly added
+ timeout parameter during the SET_ADDRESS request.
+
+Signed-off-by: Hardik Gajjar <hgajjar@de.adit-jv.com>
+Reviewed-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20231027152029.104363-1-hgajjar@de.adit-jv.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 5a1ccf0c72cf ("usb: new quirk to reduce the SET_ADDRESS request timeout")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/core/hub.c | 2 +-
+ drivers/usb/host/xhci-mem.c | 2 ++
+ drivers/usb/host/xhci-ring.c | 11 ++++++-----
+ drivers/usb/host/xhci.c | 23 ++++++++++++++++-------
+ drivers/usb/host/xhci.h | 9 +++++++--
+ include/linux/usb/hcd.h | 5 +++--
+ 6 files changed, 35 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 9a3da5d7fe1bc..73ab30e0da774 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -4676,7 +4676,7 @@ static int hub_set_address(struct usb_device *udev, int devnum)
+ if (udev->state != USB_STATE_DEFAULT)
+ return -EINVAL;
+ if (hcd->driver->address_device)
+- retval = hcd->driver->address_device(hcd, udev);
++ retval = hcd->driver->address_device(hcd, udev, USB_CTRL_SET_TIMEOUT);
+ else
+ retval = usb_control_msg(udev, usb_sndaddr0pipe(),
+ USB_REQ_SET_ADDRESS, 0, devnum, 0,
+diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
+index 0a37f0d511cf5..b1e3fa54c6397 100644
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -1729,6 +1729,8 @@ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
+ }
+
+ command->status = 0;
++ /* set default timeout to 5000 ms */
++ command->timeout_ms = XHCI_CMD_DEFAULT_TIMEOUT;
+ INIT_LIST_HEAD(&command->cmd_list);
+ return command;
+ }
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 3ec1a2617ed7e..c959d9144baa5 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -372,9 +372,10 @@ void xhci_ring_cmd_db(struct xhci_hcd *xhci)
+ readl(&xhci->dba->doorbell[0]);
+ }
+
+-static bool xhci_mod_cmd_timer(struct xhci_hcd *xhci, unsigned long delay)
++static bool xhci_mod_cmd_timer(struct xhci_hcd *xhci)
+ {
+- return mod_delayed_work(system_wq, &xhci->cmd_timer, delay);
++ return mod_delayed_work(system_wq, &xhci->cmd_timer,
++ msecs_to_jiffies(xhci->current_cmd->timeout_ms));
+ }
+
+ static struct xhci_command *xhci_next_queued_cmd(struct xhci_hcd *xhci)
+@@ -418,7 +419,7 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,
+ if ((xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) &&
+ !(xhci->xhc_state & XHCI_STATE_DYING)) {
+ xhci->current_cmd = cur_cmd;
+- xhci_mod_cmd_timer(xhci, XHCI_CMD_DEFAULT_TIMEOUT);
++ xhci_mod_cmd_timer(xhci);
+ xhci_ring_cmd_db(xhci);
+ }
+ }
+@@ -1792,7 +1793,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
+ if (!list_is_singular(&xhci->cmd_list)) {
+ xhci->current_cmd = list_first_entry(&cmd->cmd_list,
+ struct xhci_command, cmd_list);
+- xhci_mod_cmd_timer(xhci, XHCI_CMD_DEFAULT_TIMEOUT);
++ xhci_mod_cmd_timer(xhci);
+ } else if (xhci->current_cmd == cmd) {
+ xhci->current_cmd = NULL;
+ }
+@@ -4359,7 +4360,7 @@ static int queue_command(struct xhci_hcd *xhci, struct xhci_command *cmd,
+ /* if there are no other commands queued we start the timeout timer */
+ if (list_empty(&xhci->cmd_list)) {
+ xhci->current_cmd = cmd;
+- xhci_mod_cmd_timer(xhci, XHCI_CMD_DEFAULT_TIMEOUT);
++ xhci_mod_cmd_timer(xhci);
+ }
+
+ list_add_tail(&cmd->cmd_list, &xhci->cmd_list);
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index c4c733d724bd8..573b5784d1c3d 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -4007,12 +4007,18 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
+ return 0;
+ }
+
+-/*
+- * Issue an Address Device command and optionally send a corresponding
+- * SetAddress request to the device.
++/**
++ * xhci_setup_device - issues an Address Device command to assign a unique
++ * USB bus address.
++ * @hcd: USB host controller data structure.
++ * @udev: USB dev structure representing the connected device.
++ * @setup: Enum specifying setup mode: address only or with context.
++ * @timeout_ms: Max wait time (ms) for the command operation to complete.
++ *
++ * Return: 0 if successful; otherwise, negative error code.
+ */
+ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
+- enum xhci_setup_dev setup)
++ enum xhci_setup_dev setup, unsigned int timeout_ms)
+ {
+ const char *act = setup == SETUP_CONTEXT_ONLY ? "context" : "address";
+ unsigned long flags;
+@@ -4069,6 +4075,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
+ }
+
+ command->in_ctx = virt_dev->in_ctx;
++ command->timeout_ms = timeout_ms;
+
+ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
+ ctrl_ctx = xhci_get_input_control_ctx(virt_dev->in_ctx);
+@@ -4195,14 +4202,16 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
+ return ret;
+ }
+
+-static int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
++static int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev,
++ unsigned int timeout_ms)
+ {
+- return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ADDRESS);
++ return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ADDRESS, timeout_ms);
+ }
+
+ static int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev)
+ {
+- return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ONLY);
++ return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ONLY,
++ XHCI_CMD_DEFAULT_TIMEOUT);
+ }
+
+ /*
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index 31088602c0708..be480d6ac8586 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -818,6 +818,8 @@ struct xhci_command {
+ struct completion *completion;
+ union xhci_trb *command_trb;
+ struct list_head cmd_list;
++ /* xHCI command response timeout in milliseconds */
++ unsigned int timeout_ms;
+ };
+
+ /* drop context bitmasks */
+@@ -1577,8 +1579,11 @@ struct xhci_td {
+ unsigned int num_trbs;
+ };
+
+-/* xHCI command default timeout value */
+-#define XHCI_CMD_DEFAULT_TIMEOUT (5 * HZ)
++/*
++ * xHCI command default timeout value in milliseconds.
++ * USB 3.2 spec, section 9.2.6.1
++ */
++#define XHCI_CMD_DEFAULT_TIMEOUT 5000
+
+ /* command descriptor */
+ struct xhci_cd {
+diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
+index 00724b4f6e122..cd77fc6095a15 100644
+--- a/include/linux/usb/hcd.h
++++ b/include/linux/usb/hcd.h
+@@ -372,8 +372,9 @@ struct hc_driver {
+ * or bandwidth constraints.
+ */
+ void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
+- /* Returns the hardware-chosen device address */
+- int (*address_device)(struct usb_hcd *, struct usb_device *udev);
++ /* Set the hardware-chosen device address */
++ int (*address_device)(struct usb_hcd *, struct usb_device *udev,
++ unsigned int timeout_ms);
+ /* prepares the hardware to send commands to the device */
+ int (*enable_device)(struct usb_hcd *, struct usb_device *udev);
+ /* Notifies the HCD after a hub descriptor is fetched.
+--
+2.43.0
+
--- /dev/null
+From 6913394ca254cc05bbe3f6c08fbe8be5902d6366 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Apr 2024 11:10:33 -0700
+Subject: x86/bugs: Fix BHI retpoline check
+
+From: Josh Poimboeuf <jpoimboe@kernel.org>
+
+[ Upstream commit 69129794d94c544810e68b2b4eaa7e44063f9bf2 ]
+
+Confusingly, X86_FEATURE_RETPOLINE doesn't mean retpolines are enabled,
+as it also includes the original "AMD retpoline" which isn't a retpoline
+at all.
+
+Also replace cpu_feature_enabled() with boot_cpu_has() because this is
+before alternatives are patched and cpu_feature_enabled()'s fallback
+path is slower than plain old boot_cpu_has().
+
+Fixes: ec9404e40e8f ("x86/bhi: Add BHI mitigation knob")
+Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Link: https://lore.kernel.org/r/ad3807424a3953f0323c011a643405619f2a4927.1712944776.git.jpoimboe@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/cpu/bugs.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
+index 5ff69b1d39b20..c2dc9b7426acb 100644
+--- a/arch/x86/kernel/cpu/bugs.c
++++ b/arch/x86/kernel/cpu/bugs.c
+@@ -1651,7 +1651,8 @@ static void __init bhi_select_mitigation(void)
+ return;
+
+ /* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */
+- if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) {
++ if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
++ !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE)) {
+ spec_ctrl_disable_kernel_rrsba();
+ if (rrsba_disabled)
+ return;
+@@ -2803,11 +2804,13 @@ static const char *spectre_bhi_state(void)
+ {
+ if (!boot_cpu_has_bug(X86_BUG_BHI))
+ return "; BHI: Not affected";
+- else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW))
++ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW))
+ return "; BHI: BHI_DIS_S";
+- else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
++ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
+ return "; BHI: SW loop, KVM: SW loop";
+- else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && rrsba_disabled)
++ else if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
++ !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE) &&
++ rrsba_disabled)
+ return "; BHI: Retpoline";
+ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT))
+ return "; BHI: Vulnerable, KVM: SW loop";
+--
+2.43.0
+
--- /dev/null
+From b868532f95c97854462e0bd2b3681f65c184d17d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Apr 2024 23:04:34 -0700
+Subject: x86/cpufeatures: Fix dependencies for GFNI, VAES, and VPCLMULQDQ
+
+From: Eric Biggers <ebiggers@google.com>
+
+[ Upstream commit 9543f6e26634537997b6e909c20911b7bf4876de ]
+
+Fix cpuid_deps[] to list the correct dependencies for GFNI, VAES, and
+VPCLMULQDQ. These features don't depend on AVX512, and there exist CPUs
+that support these features but not AVX512. GFNI actually doesn't even
+depend on AVX.
+
+This prevents GFNI from being unnecessarily disabled if AVX is disabled
+to mitigate the GDS vulnerability.
+
+This also prevents all three features from being unnecessarily disabled
+if AVX512VL (or its dependency AVX512F) were to be disabled, but it
+looks like there isn't any case where this happens anyway.
+
+Fixes: c128dbfa0f87 ("x86/cpufeatures: Enable new SSE/AVX/AVX512 CPU features")
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
+Link: https://lore.kernel.org/r/20240417060434.47101-1-ebiggers@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/cpu/cpuid-deps.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
+index e462c1d3800a6..6fb6d8a57ceca 100644
+--- a/arch/x86/kernel/cpu/cpuid-deps.c
++++ b/arch/x86/kernel/cpu/cpuid-deps.c
+@@ -44,7 +44,10 @@ static const struct cpuid_dep cpuid_deps[] = {
+ { X86_FEATURE_F16C, X86_FEATURE_XMM2, },
+ { X86_FEATURE_AES, X86_FEATURE_XMM2 },
+ { X86_FEATURE_SHA_NI, X86_FEATURE_XMM2 },
++ { X86_FEATURE_GFNI, X86_FEATURE_XMM2 },
+ { X86_FEATURE_FMA, X86_FEATURE_AVX },
++ { X86_FEATURE_VAES, X86_FEATURE_AVX },
++ { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX },
+ { X86_FEATURE_AVX2, X86_FEATURE_AVX, },
+ { X86_FEATURE_AVX512F, X86_FEATURE_AVX, },
+ { X86_FEATURE_AVX512IFMA, X86_FEATURE_AVX512F },
+@@ -56,9 +59,6 @@ static const struct cpuid_dep cpuid_deps[] = {
+ { X86_FEATURE_AVX512VL, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512VBMI, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512_VBMI2, X86_FEATURE_AVX512VL },
+- { X86_FEATURE_GFNI, X86_FEATURE_AVX512VL },
+- { X86_FEATURE_VAES, X86_FEATURE_AVX512VL },
+- { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_AVX512_VNNI, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_AVX512_BITALG, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_AVX512_4VNNIW, X86_FEATURE_AVX512F },
+--
+2.43.0
+