From: Sasha Levin Date: Mon, 22 Apr 2024 22:34:54 +0000 (-0400) Subject: Fixes for 6.6 X-Git-Tag: v5.15.157~50 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6194356d25f56a1a69c0655f6dd9db60d8b1b2b0;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.6 Signed-off-by: Sasha Levin --- diff --git a/queue-6.6/alsa-scarlett2-add-correct-product-series-name-to-me.patch b/queue-6.6/alsa-scarlett2-add-correct-product-series-name-to-me.patch new file mode 100644 index 00000000000..4b93b30c4b6 --- /dev/null +++ b/queue-6.6/alsa-scarlett2-add-correct-product-series-name-to-me.patch @@ -0,0 +1,220 @@ +From 1a70dc15594ae20f6c1c5695204457bee4565b90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Sep 2023 03:03:03 +0930 +Subject: ALSA: scarlett2: Add correct product series name to messages + +From: Geoffrey D. Bennett + +[ 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 +Link: https://lore.kernel.org/r/3774b9d35bf1fbdd6fdad9f3f4f97e9b82ac76bf.1694705811.git.g@b4.vu +Signed-off-by: Takashi Iwai +Stable-dep-of: b61a3acada00 ("ALSA: scarlett2: Add Focusrite Clarett+ 2Pre and 4Pre support") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/alsa-scarlett2-add-focusrite-clarett-2pre-and-4pre-s.patch b/queue-6.6/alsa-scarlett2-add-focusrite-clarett-2pre-and-4pre-s.patch new file mode 100644 index 00000000000..97ef81c749e --- /dev/null +++ b/queue-6.6/alsa-scarlett2-add-focusrite-clarett-2pre-and-4pre-s.patch @@ -0,0 +1,171 @@ +From af4a3a3cfe96790e7ada75a3a256d2298502b55f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Sep 2023 01:11:30 +0930 +Subject: ALSA: scarlett2: Add Focusrite Clarett+ 2Pre and 4Pre support + +From: Geoffrey D. Bennett + +[ 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 +Link: https://lore.kernel.org/r/ZRL7qjC3tYQllT3H@m.b4.vu +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 + * Copyright (c) 2020-2021 by Vladimir Sadovnikov +@@ -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 + diff --git a/queue-6.6/alsa-scarlett2-add-focusrite-clarett-2pre-and-4pre-u.patch b/queue-6.6/alsa-scarlett2-add-focusrite-clarett-2pre-and-4pre-u.patch new file mode 100644 index 00000000000..50c3c6d037a --- /dev/null +++ b/queue-6.6/alsa-scarlett2-add-focusrite-clarett-2pre-and-4pre-u.patch @@ -0,0 +1,78 @@ +From 93b953c99a41fb5e9660f50227a2c9def7619ad7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 7 Oct 2023 22:03:04 +1030 +Subject: ALSA: scarlett2: Add Focusrite Clarett 2Pre and 4Pre USB support + +From: Geoffrey D. Bennett + +[ 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 +Link: https://lore.kernel.org/r/ZSFB8EVTG1PK1eq/@m.b4.vu +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 +@@ -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 + diff --git a/queue-6.6/alsa-scarlett2-add-support-for-clarett-8pre-usb.patch b/queue-6.6/alsa-scarlett2-add-support-for-clarett-8pre-usb.patch new file mode 100644 index 00000000000..827b9afcb80 --- /dev/null +++ b/queue-6.6/alsa-scarlett2-add-support-for-clarett-8pre-usb.patch @@ -0,0 +1,78 @@ +From bc37874cb1330dfe64ab2dc79d81b303cb0d7203 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Sep 2023 03:02:37 +0930 +Subject: ALSA: scarlett2: Add support for Clarett 8Pre USB + +From: Geoffrey D. Bennett + +[ Upstream commit b9a98cdd3ac7b80d8ea0f6acd81c88ad3d8bcb4a ] + +The Clarett 8Pre USB works the same as the Clarett+ 8Pre, only the USB +ID is different. + +Tested-by: Philippe Perrot +Signed-off-by: Geoffrey D. Bennett +Link: https://lore.kernel.org/r/e59f47b29e2037f031b56bde10474c6e96e31ba5.1694705811.git.g@b4.vu +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 ++ * Copyright (c) 2018-2023 by Geoffrey D. Bennett + * Copyright (c) 2020-2021 by Vladimir Sadovnikov + * Copyright (c) 2022 by Christian Colglazier + * +@@ -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 + diff --git a/queue-6.6/alsa-scarlett2-default-mixer-driver-to-enabled.patch b/queue-6.6/alsa-scarlett2-default-mixer-driver-to-enabled.patch new file mode 100644 index 00000000000..27147d2a13a --- /dev/null +++ b/queue-6.6/alsa-scarlett2-default-mixer-driver-to-enabled.patch @@ -0,0 +1,82 @@ +From d7da5fd48f26e16cf88bbb8f2e9bca23d0d8ade1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Sep 2023 03:01:57 +0930 +Subject: ALSA: scarlett2: Default mixer driver to enabled + +From: Geoffrey D. Bennett + +[ 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 +Link: https://lore.kernel.org/r/89600a35b40307f2766578ad1ca2f21801286b58.1694705811.git.g@b4.vu +Signed-off-by: Takashi Iwai +Stable-dep-of: b61a3acada00 ("ALSA: scarlett2: Add Focusrite Clarett+ 2Pre and 4Pre support") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/alsa-scarlett2-move-usb-ids-out-from-device_info-str.patch b/queue-6.6/alsa-scarlett2-move-usb-ids-out-from-device_info-str.patch new file mode 100644 index 00000000000..bae86f607c0 --- /dev/null +++ b/queue-6.6/alsa-scarlett2-move-usb-ids-out-from-device_info-str.patch @@ -0,0 +1,196 @@ +From 81d93f4f95db569abab7e9be131cad9419facf17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Sep 2023 03:02:16 +0930 +Subject: ALSA: scarlett2: Move USB IDs out from device_info struct + +From: Geoffrey D. Bennett + +[ 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 +Signed-off-by: Geoffrey D. Bennett +Link: https://lore.kernel.org/r/8263368e8d49e6fcebc709817bd82ab79b404468.1694705811.git.g@b4.vu +Signed-off-by: Takashi Iwai +Stable-dep-of: b9a98cdd3ac7 ("ALSA: scarlett2: Add support for Clarett 8Pre USB") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/alsa-scarlett2-rename-scarlett_gen2-to-scarlett2.patch b/queue-6.6/alsa-scarlett2-rename-scarlett_gen2-to-scarlett2.patch new file mode 100644 index 00000000000..493bea6d5b8 --- /dev/null +++ b/queue-6.6/alsa-scarlett2-rename-scarlett_gen2-to-scarlett2.patch @@ -0,0 +1,163 @@ +From 9061ae27fb9689cb6debe89d82ec501d18aededa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Oct 2023 04:31:28 +1030 +Subject: ALSA: scarlett2: Rename scarlett_gen2 to scarlett2 + +From: Geoffrey D. Bennett + +[ 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 +Link: https://lore.kernel.org/r/e1ad7f69a1e20cdb39094164504389160c1a0a0b.1698342632.git.g@b4.vu +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 + 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 +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 + diff --git a/queue-6.6/asoc-ti-convert-pandora-asoc-to-gpio-descriptors.patch b/queue-6.6/asoc-ti-convert-pandora-asoc-to-gpio-descriptors.patch new file mode 100644 index 00000000000..98a0b32f3a5 --- /dev/null +++ b/queue-6.6/asoc-ti-convert-pandora-asoc-to-gpio-descriptors.patch @@ -0,0 +1,185 @@ +From 2d9170f123541e6e41c59b7745442b172d5e6072 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Sep 2023 15:25:32 +0200 +Subject: ASoC: ti: Convert Pandora ASoC to GPIO descriptors + +From: Linus Walleij + +[ 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 +Acked-by: Jarkko Nikula +Link: https://lore.kernel.org/r/20230926-descriptors-asoc-ti-v1-4-60cf4f8adbc5@linaro.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + #include +-#include ++#include + #include + #include + #include +@@ -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 + diff --git a/queue-6.6/clk-get-runtime-pm-before-walking-tree-during-disabl.patch b/queue-6.6/clk-get-runtime-pm-before-walking-tree-during-disabl.patch new file mode 100644 index 00000000000..16b9cafdb25 --- /dev/null +++ b/queue-6.6/clk-get-runtime-pm-before-walking-tree-during-disabl.patch @@ -0,0 +1,344 @@ +From 3412ba3e03e0c72638d059ea48241fa764ca46e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Mar 2024 11:41:58 -0700 +Subject: clk: Get runtime PM before walking tree during disable_unused + +From: Stephen Boyd + +[ 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 +Closes: https://lore.kernel.org/all/20220922084322.RFC.2.I375b6b9e0a0a5348962f004beb3dafee6a12dfbb@changeid/ [1] +Closes: https://issuetracker.google.com/328070191 +Cc: Marek Szyprowski +Cc: Ulf Hansson +Cc: Krzysztof Kozlowski +Fixes: 9a34b45397e5 ("clk: Add support for runtime PM") +Signed-off-by: Stephen Boyd +Link: https://lore.kernel.org/r/20240325184204.745706-5-sboyd@kernel.org +Reviewed-by: Douglas Anderson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/clk-get-runtime-pm-before-walking-tree-for-clk_summa.patch b/queue-6.6/clk-get-runtime-pm-before-walking-tree-for-clk_summa.patch new file mode 100644 index 00000000000..681ff7384f2 --- /dev/null +++ b/queue-6.6/clk-get-runtime-pm-before-walking-tree-for-clk_summa.patch @@ -0,0 +1,95 @@ +From 3d18d8c18eea27073229ed3c512791713a7aac50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Mar 2024 11:41:59 -0700 +Subject: clk: Get runtime PM before walking tree for clk_summary + +From: Stephen Boyd + +[ 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 +Cc: Douglas Anderson +Signed-off-by: Stephen Boyd +Link: https://lore.kernel.org/r/20240325184204.745706-6-sboyd@kernel.org +Reviewed-by: Douglas Anderson +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/clk-initialize-struct-clk_core-kref-earlier.patch b/queue-6.6/clk-initialize-struct-clk_core-kref-earlier.patch new file mode 100644 index 00000000000..6aeebfffb39 --- /dev/null +++ b/queue-6.6/clk-initialize-struct-clk_core-kref-earlier.patch @@ -0,0 +1,98 @@ +From add4ef5fecd25e1ead273e1d6b4db31581c090fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Mar 2024 11:41:57 -0700 +Subject: clk: Initialize struct clk_core kref earlier + +From: Stephen Boyd + +[ 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 +Signed-off-by: Stephen Boyd +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 +--- + 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 + diff --git a/queue-6.6/clk-mediatek-do-a-runtime-pm-get-on-controllers-duri.patch b/queue-6.6/clk-mediatek-do-a-runtime-pm-get-on-controllers-duri.patch new file mode 100644 index 00000000000..705f3d371eb --- /dev/null +++ b/queue-6.6/clk-mediatek-do-a-runtime-pm-get-on-controllers-duri.patch @@ -0,0 +1,95 @@ +From 48e47292742c39b19ee238d3b09443d27a88123d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 + +Link: https://lore.kernel.org/r/20240312115249.3341654-1-treapking@chromium.org +Reviewed-by: AngeloGioacchino Del Regno +Tested-by: AngeloGioacchino Del Regno +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + + #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 + diff --git a/queue-6.6/clk-remove-prepare_lock-hold-assertion-in-__clk_rele.patch b/queue-6.6/clk-remove-prepare_lock-hold-assertion-in-__clk_rele.patch new file mode 100644 index 00000000000..df227ad5875 --- /dev/null +++ b/queue-6.6/clk-remove-prepare_lock-hold-assertion-in-__clk_rele.patch @@ -0,0 +1,44 @@ +From 2deb3754e80187eadbd2e3a2604264173d94d784 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Mar 2024 11:41:55 -0700 +Subject: clk: Remove prepare_lock hold assertion in __clk_release() + +From: Stephen Boyd + +[ 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 +Reviewed-by: Douglas Anderson +Signed-off-by: Stephen Boyd +Link: https://lore.kernel.org/r/20240325184204.745706-2-sboyd@kernel.org +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/clk-show-active-consumers-of-clocks-in-debugfs.patch b/queue-6.6/clk-show-active-consumers-of-clocks-in-debugfs.patch new file mode 100644 index 00000000000..5808f32bb0b --- /dev/null +++ b/queue-6.6/clk-show-active-consumers-of-clocks-in-debugfs.patch @@ -0,0 +1,109 @@ +From f7deca7e1681741a0c477e4408cbda438dc7715d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 27 Nov 2022 22:53:19 +0530 +Subject: clk: Show active consumers of clocks in debugfs + +From: Vishal Badole + +[ 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 +Signed-off-by: Chinmoy Ghosh +Co-developed-by: Mintu Patel +Signed-off-by: Mintu Patel +Co-developed-by: Vimal Kumar +Signed-off-by: Vimal Kumar +Signed-off-by: Vishal Badole +Link: https://lore.kernel.org/r/1669569799-8526-1-git-send-email-badolevishal1116@gmail.com +Signed-off-by: Stephen Boyd +Stable-dep-of: 9d1e795f754d ("clk: Get runtime PM before walking tree for clk_summary") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/drm-panel-orientation-quirks-add-quirk-for-lenovo-le.patch b/queue-6.6/drm-panel-orientation-quirks-add-quirk-for-lenovo-le.patch new file mode 100644 index 00000000000..854b23902e6 --- /dev/null +++ b/queue-6.6/drm-panel-orientation-quirks-add-quirk-for-lenovo-le.patch @@ -0,0 +1,43 @@ +From 985e3b77f8754a181adba14ba97ecda7839f468e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20231114233859.274189-1-appsforartists@google.com +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/interconnect-don-t-access-req_list-while-it-s-being-.patch b/queue-6.6/interconnect-don-t-access-req_list-while-it-s-being-.patch new file mode 100644 index 00000000000..0333abe8572 --- /dev/null +++ b/queue-6.6/interconnect-don-t-access-req_list-while-it-s-being-.patch @@ -0,0 +1,106 @@ +From a94dd5aee55f39a2f6df40f401fc583c5a7e27ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Mar 2024 14:56:52 -0800 +Subject: interconnect: Don't access req_list while it's being manipulated + +From: Mike Tipton + +[ 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(... + + +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(... + + +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 +Fixes: af42269c3523 ("interconnect: Fix locking for runpm vs reclaim") +Reviewed-by: Rob Clark +Link: https://lore.kernel.org/r/20240305225652.22872-1-quic_mdtipton@quicinc.com +Signed-off-by: Georgi Djakov +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/pci-add-pci_header_type_mfd-definition.patch b/queue-6.6/pci-add-pci_header_type_mfd-definition.patch new file mode 100644 index 00000000000..57218d05f4e --- /dev/null +++ b/queue-6.6/pci-add-pci_header_type_mfd-definition.patch @@ -0,0 +1,38 @@ +From 364b460e7117f64ad97ab29ba0a81ed0aa71aad2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Bjorn Helgaas +Stable-dep-of: 83c088148c8e ("PCI: Use PCI_HEADER_TYPE_* instead of literals") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/pci-dpc-use-field_get.patch b/queue-6.6/pci-dpc-use-field_get.patch new file mode 100644 index 00000000000..1a1a2108941 --- /dev/null +++ b/queue-6.6/pci-dpc-use-field_get.patch @@ -0,0 +1,83 @@ +From c681bf711459e12cc5f0a38c2024452ef5dfee57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +--- + 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 ++#include + #include + #include + #include +@@ -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 + diff --git a/queue-6.6/pci-simplify-pcie_capability_clear_and_set_word-to-..patch b/queue-6.6/pci-simplify-pcie_capability_clear_and_set_word-to-..patch new file mode 100644 index 00000000000..4036e9b5efc --- /dev/null +++ b/queue-6.6/pci-simplify-pcie_capability_clear_and_set_word-to-..patch @@ -0,0 +1,66 @@ +From b79500383c8b70476a81c5898ce40f191503b128 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +[bhelgaas: squash] +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/pci-use-pci_header_type_-instead-of-literals.patch b/queue-6.6/pci-use-pci_header_type_-instead-of-literals.patch new file mode 100644 index 00000000000..57d252241e1 --- /dev/null +++ b/queue-6.6/pci-use-pci_header_type_-instead-of-literals.patch @@ -0,0 +1,323 @@ +From 47a6faa3158d5013c24f05c59c3d3b84f273d9dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Bjorn Helgaas +Reviewed-by: Wolfram Sang # for Renesas R-Car +Signed-off-by: Sasha Levin +--- + 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 ++#include + + 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 + diff --git a/queue-6.6/platform-x86-amd-pmc-extend-framework-13-quirk-to-mo.patch b/queue-6.6/platform-x86-amd-pmc-extend-framework-13-quirk-to-mo.patch new file mode 100644 index 00000000000..d417636b4ed --- /dev/null +++ b/queue-6.6/platform-x86-amd-pmc-extend-framework-13-quirk-to-mo.patch @@ -0,0 +1,51 @@ +From b37ae317311ca84849536995e9eb6239c7341dcf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Hans de Goede +Link: https://lore.kernel.org/r/20240410141046.433-1-mario.limonciello@amd.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/series b/queue-6.6/series index 14801d820de..6f572a6e997 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -66,3 +66,31 @@ s390-cio-fix-race-condition-during-online-processing.patch 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 diff --git a/queue-6.6/usb-new-quirk-to-reduce-the-set_address-request-time.patch b/queue-6.6/usb-new-quirk-to-reduce-the-set_address-request-time.patch new file mode 100644 index 00000000000..5517c39deae --- /dev/null +++ b/queue-6.6/usb-new-quirk-to-reduce-the-set_address-request-time.patch @@ -0,0 +1,167 @@ +From 62e8bd54dc1548022c2db1bc175fa5c649f10751 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Oct 2023 17:20:29 +0200 +Subject: usb: new quirk to reduce the SET_ADDRESS request timeout + +From: Hardik Gajjar + +[ 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 +Reviewed-by: Alan Stern +Link: https://lore.kernel.org/r/20231027152029.104363-2-hgajjar@de.adit-jv.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/usb-pci-quirks-group-amd-specific-quirk-code-togethe.patch b/queue-6.6/usb-pci-quirks-group-amd-specific-quirk-code-togethe.patch new file mode 100644 index 00000000000..9a98345478d --- /dev/null +++ b/queue-6.6/usb-pci-quirks-group-amd-specific-quirk-code-togethe.patch @@ -0,0 +1,225 @@ +From 952f4e84ead9ecf5b11d30bdc72d08c391ef630f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Sep 2023 14:56:51 +0200 +Subject: usb: pci-quirks: group AMD specific quirk code together + +From: Niklas Schnelle + +[ 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 +Signed-off-by: Arnd Bergmann +Signed-off-by: Niklas Schnelle +Link: https://lore.kernel.org/r/20230911125653.1393895-2-schnelle@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/usb-pci-quirks-handle-has_ioport-dependency-for-amd-.patch b/queue-6.6/usb-pci-quirks-handle-has_ioport-dependency-for-amd-.patch new file mode 100644 index 00000000000..18a7e1ac817 --- /dev/null +++ b/queue-6.6/usb-pci-quirks-handle-has_ioport-dependency-for-amd-.patch @@ -0,0 +1,174 @@ +From 0f70138cda5d225e8d81ea1d734d20e6b11e7478 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Sep 2023 14:56:52 +0200 +Subject: usb: pci-quirks: handle HAS_IOPORT dependency for AMD quirk + +From: Niklas Schnelle + +[ 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 +Signed-off-by: Arnd Bergmann +Signed-off-by: Niklas Schnelle +Link: https://lore.kernel.org/r/20230911125653.1393895-3-schnelle@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/usb-pci-quirks-handle-has_ioport-dependency-for-uhci.patch b/queue-6.6/usb-pci-quirks-handle-has_ioport-dependency-for-uhci.patch new file mode 100644 index 00000000000..93d134e5416 --- /dev/null +++ b/queue-6.6/usb-pci-quirks-handle-has_ioport-dependency-for-uhci.patch @@ -0,0 +1,78 @@ +From 62308e4a79ca6840e7c164e05a067e5a9f87d504 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 11 Sep 2023 14:56:53 +0200 +Subject: usb: pci-quirks: handle HAS_IOPORT dependency for UHCI handoff + +From: Niklas Schnelle + +[ 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 +Signed-off-by: Arnd Bergmann +Signed-off-by: Niklas Schnelle +Link: https://lore.kernel.org/r/20230911125653.1393895-4-schnelle@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/usb-xhci-add-timeout-argument-in-address_device-usb-.patch b/queue-6.6/usb-xhci-add-timeout-argument-in-address_device-usb-.patch new file mode 100644 index 00000000000..15ae2ff5cda --- /dev/null +++ b/queue-6.6/usb-xhci-add-timeout-argument-in-address_device-usb-.patch @@ -0,0 +1,206 @@ +From 747b080e78dddb4c56c6991d74381a2f5a98a484 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Oct 2023 17:20:28 +0200 +Subject: usb: xhci: Add timeout argument in address_device USB HCD callback + +From: Hardik Gajjar + +[ 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 +Reviewed-by: Mathias Nyman +Link: https://lore.kernel.org/r/20231027152029.104363-1-hgajjar@de.adit-jv.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 5a1ccf0c72cf ("usb: new quirk to reduce the SET_ADDRESS request timeout") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/x86-bugs-fix-bhi-retpoline-check.patch b/queue-6.6/x86-bugs-fix-bhi-retpoline-check.patch new file mode 100644 index 00000000000..36732092015 --- /dev/null +++ b/queue-6.6/x86-bugs-fix-bhi-retpoline-check.patch @@ -0,0 +1,63 @@ +From 6913394ca254cc05bbe3f6c08fbe8be5902d6366 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Apr 2024 11:10:33 -0700 +Subject: x86/bugs: Fix BHI retpoline check + +From: Josh Poimboeuf + +[ 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 +Signed-off-by: Ingo Molnar +Reviewed-by: Pawan Gupta +Cc: Borislav Petkov +Cc: Linus Torvalds +Link: https://lore.kernel.org/r/ad3807424a3953f0323c011a643405619f2a4927.1712944776.git.jpoimboe@kernel.org +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/x86-cpufeatures-fix-dependencies-for-gfni-vaes-and-v.patch b/queue-6.6/x86-cpufeatures-fix-dependencies-for-gfni-vaes-and-v.patch new file mode 100644 index 00000000000..6c64f40e335 --- /dev/null +++ b/queue-6.6/x86-cpufeatures-fix-dependencies-for-gfni-vaes-and-v.patch @@ -0,0 +1,59 @@ +From b868532f95c97854462e0bd2b3681f65c184d17d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Apr 2024 23:04:34 -0700 +Subject: x86/cpufeatures: Fix dependencies for GFNI, VAES, and VPCLMULQDQ + +From: Eric Biggers + +[ 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 +Signed-off-by: Borislav Petkov (AMD) +Acked-by: Dave Hansen +Link: https://lore.kernel.org/r/20240417060434.47101-1-ebiggers@kernel.org +Signed-off-by: Sasha Levin +--- + 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 +