--- /dev/null
+From 15a62b81175885b5adfcaf49870466e3603f06c7 Mon Sep 17 00:00:00 2001
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Date: Mon, 26 Aug 2024 07:49:34 +0200
+Subject: bus: integrator-lm: fix OF node leak in probe()
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+commit 15a62b81175885b5adfcaf49870466e3603f06c7 upstream.
+
+Driver code is leaking OF node reference from of_find_matching_node() in
+probe().
+
+Fixes: ccea5e8a5918 ("bus: Add driver for Integrator/AP logic modules")
+Cc: stable@vger.kernel.org
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Acked-by: Liviu Dudau <liviu.dudau@arm.com>
+Link: https://lore.kernel.org/20240826054934.10724-2-krzysztof.kozlowski@linaro.org
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/bus/arm-integrator-lm.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/bus/arm-integrator-lm.c
++++ b/drivers/bus/arm-integrator-lm.c
+@@ -85,6 +85,7 @@ static int integrator_ap_lm_probe(struct
+ return -ENODEV;
+ }
+ map = syscon_node_to_regmap(syscon);
++ of_node_put(syscon);
+ if (IS_ERR(map)) {
+ dev_err(dev,
+ "could not find Integrator/AP system controller\n");
--- /dev/null
+From ce3d2d6b150ba8528f3218ebf0cee2c2c572662d Mon Sep 17 00:00:00 2001
+From: Pavan Kumar Paluri <papaluri@amd.com>
+Date: Thu, 15 Aug 2024 07:25:00 -0500
+Subject: crypto: ccp - Properly unregister /dev/sev on sev PLATFORM_STATUS failure
+
+From: Pavan Kumar Paluri <papaluri@amd.com>
+
+commit ce3d2d6b150ba8528f3218ebf0cee2c2c572662d upstream.
+
+In case of sev PLATFORM_STATUS failure, sev_get_api_version() fails
+resulting in sev_data field of psp_master nulled out. This later becomes
+a problem when unloading the ccp module because the device has not been
+unregistered (via misc_deregister()) before clearing the sev_data field
+of psp_master. As a result, on reloading the ccp module, a duplicate
+device issue is encountered as can be seen from the dmesg log below.
+
+on reloading ccp module via modprobe ccp
+
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0xd7/0xf0
+ dump_stack+0x10/0x20
+ sysfs_warn_dup+0x5c/0x70
+ sysfs_create_dir_ns+0xbc/0xd
+ kobject_add_internal+0xb1/0x2f0
+ kobject_add+0x7a/0xe0
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ ? get_device_parent+0xd4/0x1e0
+ ? __pfx_klist_children_get+0x10/0x10
+ device_add+0x121/0x870
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ device_create_groups_vargs+0xdc/0x100
+ device_create_with_groups+0x3f/0x60
+ misc_register+0x13b/0x1c0
+ sev_dev_init+0x1d4/0x290 [ccp]
+ psp_dev_init+0x136/0x300 [ccp]
+ sp_init+0x6f/0x80 [ccp]
+ sp_pci_probe+0x2a6/0x310 [ccp]
+ ? srso_alias_return_thunk+0x5/0xfbef5
+ local_pci_probe+0x4b/0xb0
+ work_for_cpu_fn+0x1a/0x30
+ process_one_work+0x203/0x600
+ worker_thread+0x19e/0x350
+ ? __pfx_worker_thread+0x10/0x10
+ kthread+0xeb/0x120
+ ? __pfx_kthread+0x10/0x10
+ ret_from_fork+0x3c/0x60
+ ? __pfx_kthread+0x10/0x10
+ ret_from_fork_asm+0x1a/0x30
+ </TASK>
+ kobject: kobject_add_internal failed for sev with -EEXIST, don't try to register things with the same name in the same directory.
+ ccp 0000:22:00.1: sev initialization failed
+ ccp 0000:22:00.1: psp initialization failed
+ ccp 0000:a2:00.1: no command queues available
+ ccp 0000:a2:00.1: psp enabled
+
+Address this issue by unregistering the /dev/sev before clearing out
+sev_data in case of PLATFORM_STATUS failure.
+
+Fixes: 200664d5237f ("crypto: ccp: Add Secure Encrypted Virtualization (SEV) command support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Pavan Kumar Paluri <papaluri@amd.com>
+Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/crypto/ccp/sev-dev.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/crypto/ccp/sev-dev.c
++++ b/drivers/crypto/ccp/sev-dev.c
+@@ -1141,6 +1141,8 @@ void sev_pci_init(void)
+ return;
+
+ err:
++ sev_dev_destroy(psp_master);
++
+ psp_master->sev_data = NULL;
+ }
+
--- /dev/null
+From f0e5311aa8022107d63c54e2f03684ec097d1394 Mon Sep 17 00:00:00 2001
+From: Jann Horn <jannh@google.com>
+Date: Wed, 28 Aug 2024 01:45:48 +0200
+Subject: firmware_loader: Block path traversal
+
+From: Jann Horn <jannh@google.com>
+
+commit f0e5311aa8022107d63c54e2f03684ec097d1394 upstream.
+
+Most firmware names are hardcoded strings, or are constructed from fairly
+constrained format strings where the dynamic parts are just some hex
+numbers or such.
+
+However, there are a couple codepaths in the kernel where firmware file
+names contain string components that are passed through from a device or
+semi-privileged userspace; the ones I could find (not counting interfaces
+that require root privileges) are:
+
+ - lpfc_sli4_request_firmware_update() seems to construct the firmware
+ filename from "ModelName", a string that was previously parsed out of
+ some descriptor ("Vital Product Data") in lpfc_fill_vpd()
+ - nfp_net_fw_find() seems to construct a firmware filename from a model
+ name coming from nfp_hwinfo_lookup(pf->hwinfo, "nffw.partno"), which I
+ think parses some descriptor that was read from the device.
+ (But this case likely isn't exploitable because the format string looks
+ like "netronome/nic_%s", and there shouldn't be any *folders* starting
+ with "netronome/nic_". The previous case was different because there,
+ the "%s" is *at the start* of the format string.)
+ - module_flash_fw_schedule() is reachable from the
+ ETHTOOL_MSG_MODULE_FW_FLASH_ACT netlink command, which is marked as
+ GENL_UNS_ADMIN_PERM (meaning CAP_NET_ADMIN inside a user namespace is
+ enough to pass the privilege check), and takes a userspace-provided
+ firmware name.
+ (But I think to reach this case, you need to have CAP_NET_ADMIN over a
+ network namespace that a special kind of ethernet device is mapped into,
+ so I think this is not a viable attack path in practice.)
+
+Fix it by rejecting any firmware names containing ".." path components.
+
+For what it's worth, I went looking and haven't found any USB device
+drivers that use the firmware loader dangerously.
+
+Cc: stable@vger.kernel.org
+Reviewed-by: Danilo Krummrich <dakr@kernel.org>
+Fixes: abb139e75c2c ("firmware: teach the kernel to load firmware files directly from the filesystem")
+Signed-off-by: Jann Horn <jannh@google.com>
+Acked-by: Luis Chamberlain <mcgrof@kernel.org>
+Link: https://lore.kernel.org/r/20240828-firmware-traversal-v3-1-c76529c63b5f@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/base/firmware_loader/main.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+--- a/drivers/base/firmware_loader/main.c
++++ b/drivers/base/firmware_loader/main.c
+@@ -788,6 +788,26 @@ static void fw_abort_batch_reqs(struct f
+ mutex_unlock(&fw_lock);
+ }
+
++/*
++ * Reject firmware file names with ".." path components.
++ * There are drivers that construct firmware file names from device-supplied
++ * strings, and we don't want some device to be able to tell us "I would like to
++ * be sent my firmware from ../../../etc/shadow, please".
++ *
++ * Search for ".." surrounded by either '/' or start/end of string.
++ *
++ * This intentionally only looks at the firmware name, not at the firmware base
++ * directory or at symlink contents.
++ */
++static bool name_contains_dotdot(const char *name)
++{
++ size_t name_len = strlen(name);
++
++ return strcmp(name, "..") == 0 || strncmp(name, "../", 3) == 0 ||
++ strstr(name, "/../") != NULL ||
++ (name_len >= 3 && strcmp(name+name_len-3, "/..") == 0);
++}
++
+ /* called from request_firmware() and request_firmware_work_func() */
+ static int
+ _request_firmware(const struct firmware **firmware_p, const char *name,
+@@ -808,6 +828,14 @@ _request_firmware(const struct firmware
+ goto out;
+ }
+
++ if (name_contains_dotdot(name)) {
++ dev_warn(device,
++ "Firmware load for '%s' refused, path contains '..' component\n",
++ name);
++ ret = -EINVAL;
++ goto out;
++ }
++
+ ret = _request_firmware_prepare(&fw, name, device, buf, size,
+ offset, opt_flags);
+ if (ret <= 0) /* error or already assigned */
+@@ -878,6 +906,8 @@ _request_firmware(const struct firmware
+ * @name will be used as $FIRMWARE in the uevent environment and
+ * should be distinctive enough not to be confused with any other
+ * firmware image for this or any other device.
++ * It must not contain any ".." path components - "foo/bar..bin" is
++ * allowed, but "foo/../bar.bin" is not.
+ *
+ * Caller must hold the reference count of @device.
+ *
--- /dev/null
+From 5551bc30e4a69ad86d0d008e2f56cd59b6583476 Mon Sep 17 00:00:00 2001
+From: Finn Thain <fthain@linux-m68k.org>
+Date: Wed, 7 Aug 2024 13:36:28 +1000
+Subject: scsi: mac_scsi: Disallow bus errors during PDMA send
+
+From: Finn Thain <fthain@linux-m68k.org>
+
+commit 5551bc30e4a69ad86d0d008e2f56cd59b6583476 upstream.
+
+SD cards can produce write latency spikes on the order of a hundred
+milliseconds. If the target firmware does not hide that latency during DATA
+IN and OUT phases it can cause the PDMA circuitry to raise a processor bus
+fault which in turn leads to an unreliable byte count and a DMA overrun.
+
+The Last Byte Sent flag is used to detect the overrun but this mechanism is
+unreliable on some systems. Instead, set a DID_ERROR result whenever there
+is a bus fault during a PDMA send, unless the cause was a phase mismatch.
+
+Cc: stable@vger.kernel.org # 5.15+
+Reported-and-tested-by: Stan Johnson <userm57@yahoo.com>
+Fixes: 7c1f3e3447a1 ("scsi: mac_scsi: Treat Last Byte Sent time-out as failure")
+Signed-off-by: Finn Thain <fthain@linux-m68k.org>
+Link: https://lore.kernel.org/r/cc38df687ace2c4ffc375a683b2502fc476b600d.1723001788.git.fthain@linux-m68k.org
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/mac_scsi.c | 44 +++++++++++++++++++-------------------------
+ 1 file changed, 19 insertions(+), 25 deletions(-)
+
+--- a/drivers/scsi/mac_scsi.c
++++ b/drivers/scsi/mac_scsi.c
+@@ -102,11 +102,15 @@ __setup("mac5380=", mac_scsi_setup);
+ * Linux SCSI drivers lack knowledge of the timing behaviour of SCSI targets
+ * so bus errors are unavoidable.
+ *
+- * If a MOVE.B instruction faults, we assume that zero bytes were transferred
+- * and simply retry. That assumption probably depends on target behaviour but
+- * seems to hold up okay. The NOP provides synchronization: without it the
+- * fault can sometimes occur after the program counter has moved past the
+- * offending instruction. Post-increment addressing can't be used.
++ * If a MOVE.B instruction faults during a receive operation, we assume the
++ * target sent nothing and try again. That assumption probably depends on
++ * target firmware but it seems to hold up okay. If a fault happens during a
++ * send operation, the target may or may not have seen /ACK and got the byte.
++ * It's uncertain so the whole SCSI command gets retried.
++ *
++ * The NOP is needed for synchronization because the fault address in the
++ * exception stack frame may or may not be the instruction that actually
++ * caused the bus error. Post-increment addressing can't be used.
+ */
+
+ #define MOVE_BYTE(operands) \
+@@ -243,22 +247,21 @@ static inline int mac_pdma_send(unsigned
+ if (n >= 1) {
+ MOVE_BYTE("%0@,%3@");
+ if (result)
+- goto out;
++ return -1;
+ }
+ if (n >= 1 && ((unsigned long)addr & 1)) {
+ MOVE_BYTE("%0@,%3@");
+ if (result)
+- goto out;
++ return -2;
+ }
+ while (n >= 32)
+ MOVE_16_WORDS("%0@+,%3@");
+ while (n >= 2)
+ MOVE_WORD("%0@+,%3@");
+ if (result)
+- return start - addr; /* Negated to indicate uncertain length */
++ return start - addr - 1; /* Negated to indicate uncertain length */
+ if (n == 1)
+ MOVE_BYTE("%0@,%3@");
+-out:
+ return addr - start;
+ }
+
+@@ -307,7 +310,6 @@ static inline int macscsi_pread(struct N
+ {
+ u8 __iomem *s = hostdata->pdma_io + (INPUT_DATA_REG << 4);
+ unsigned char *d = dst;
+- int result = 0;
+
+ hostdata->pdma_residual = len;
+
+@@ -343,11 +345,12 @@ static inline int macscsi_pread(struct N
+ if (bytes == 0)
+ continue;
+
+- result = -1;
++ if (macscsi_wait_for_drq(hostdata) <= 0)
++ set_host_byte(hostdata->connected, DID_ERROR);
+ break;
+ }
+
+- return result;
++ return 0;
+ }
+
+ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata,
+@@ -355,7 +358,6 @@ static inline int macscsi_pwrite(struct
+ {
+ unsigned char *s = src;
+ u8 __iomem *d = hostdata->pdma_io + (OUTPUT_DATA_REG << 4);
+- int result = 0;
+
+ hostdata->pdma_residual = len;
+
+@@ -377,17 +379,8 @@ static inline int macscsi_pwrite(struct
+ hostdata->pdma_residual -= bytes;
+ }
+
+- if (hostdata->pdma_residual == 0) {
+- if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG,
+- TCR_LAST_BYTE_SENT,
+- TCR_LAST_BYTE_SENT,
+- 0) < 0) {
+- scmd_printk(KERN_ERR, hostdata->connected,
+- "%s: Last Byte Sent timeout\n", __func__);
+- result = -1;
+- }
++ if (hostdata->pdma_residual == 0)
+ break;
+- }
+
+ if (bytes > 0)
+ continue;
+@@ -400,11 +393,12 @@ static inline int macscsi_pwrite(struct
+ if (bytes == 0)
+ continue;
+
+- result = -1;
++ if (macscsi_wait_for_drq(hostdata) <= 0)
++ set_host_byte(hostdata->connected, DID_ERROR);
+ break;
+ }
+
+- return result;
++ return 0;
+ }
+
+ static int macscsi_dma_xfer_len(struct NCR5380_hostdata *hostdata,
--- /dev/null
+From 5545c3165cbc98615fe65a44f41167cbb557e410 Mon Sep 17 00:00:00 2001
+From: Finn Thain <fthain@linux-m68k.org>
+Date: Wed, 7 Aug 2024 13:36:28 +1000
+Subject: scsi: mac_scsi: Refactor polling loop
+
+From: Finn Thain <fthain@linux-m68k.org>
+
+commit 5545c3165cbc98615fe65a44f41167cbb557e410 upstream.
+
+Before the error handling can be revised, some preparation is needed.
+Refactor the polling loop with a new function, macscsi_wait_for_drq().
+This function will gain more call sites in the next patch.
+
+Cc: stable@vger.kernel.org # 5.15+
+Tested-by: Stan Johnson <userm57@yahoo.com>
+Signed-off-by: Finn Thain <fthain@linux-m68k.org>
+Link: https://lore.kernel.org/r/6a5ffabb4290c0d138c6d285fda8fa3902e926f0.1723001788.git.fthain@linux-m68k.org
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/mac_scsi.c | 80 +++++++++++++++++++++--------------------
+ 1 file changed, 42 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
+index e67b038a3577..99a2008f8752 100644
+--- a/drivers/scsi/mac_scsi.c
++++ b/drivers/scsi/mac_scsi.c
+@@ -208,8 +208,6 @@ __setup("mac5380=", mac_scsi_setup);
+ ".previous \n" \
+ : "+a" (addr), "+r" (n), "+r" (result) : "a" (io))
+
+-#define MAC_PDMA_DELAY 32
+-
+ static inline int mac_pdma_recv(void __iomem *io, unsigned char *start, int n)
+ {
+ unsigned char *addr = start;
+@@ -274,6 +272,36 @@ static inline void write_ctrl_reg(struct NCR5380_hostdata *hostdata, u32 value)
+ out_be32(hostdata->io + (CTRL_REG << 4), value);
+ }
+
++static inline int macscsi_wait_for_drq(struct NCR5380_hostdata *hostdata)
++{
++ unsigned int n = 1; /* effectively multiplies NCR5380_REG_POLL_TIME */
++ unsigned char basr;
++
++again:
++ basr = NCR5380_read(BUS_AND_STATUS_REG);
++
++ if (!(basr & BASR_PHASE_MATCH))
++ return 1;
++
++ if (basr & BASR_IRQ)
++ return -1;
++
++ if (basr & BASR_DRQ)
++ return 0;
++
++ if (n-- == 0) {
++ NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host);
++ dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host,
++ "%s: DRQ timeout\n", __func__);
++ return -1;
++ }
++
++ NCR5380_poll_politely2(hostdata,
++ BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ,
++ BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, 0);
++ goto again;
++}
++
+ static inline int macscsi_pread(struct NCR5380_hostdata *hostdata,
+ unsigned char *dst, int len)
+ {
+@@ -283,9 +311,7 @@ static inline int macscsi_pread(struct NCR5380_hostdata *hostdata,
+
+ hostdata->pdma_residual = len;
+
+- while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
+- BASR_DRQ | BASR_PHASE_MATCH,
+- BASR_DRQ | BASR_PHASE_MATCH, 0)) {
++ while (macscsi_wait_for_drq(hostdata) == 0) {
+ int bytes, chunk_bytes;
+
+ if (macintosh_config->ident == MAC_MODEL_IIFX)
+@@ -295,19 +321,16 @@ static inline int macscsi_pread(struct NCR5380_hostdata *hostdata,
+ chunk_bytes = min(hostdata->pdma_residual, 512);
+ bytes = mac_pdma_recv(s, d, chunk_bytes);
+
++ if (macintosh_config->ident == MAC_MODEL_IIFX)
++ write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE);
++
+ if (bytes > 0) {
+ d += bytes;
+ hostdata->pdma_residual -= bytes;
+ }
+
+ if (hostdata->pdma_residual == 0)
+- goto out;
+-
+- if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH))
+- goto out;
+-
+- if (bytes == 0)
+- udelay(MAC_PDMA_DELAY);
++ break;
+
+ if (bytes > 0)
+ continue;
+@@ -321,16 +344,9 @@ static inline int macscsi_pread(struct NCR5380_hostdata *hostdata,
+ continue;
+
+ result = -1;
+- goto out;
++ break;
+ }
+
+- scmd_printk(KERN_ERR, hostdata->connected,
+- "%s: phase mismatch or !DRQ\n", __func__);
+- NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host);
+- result = -1;
+-out:
+- if (macintosh_config->ident == MAC_MODEL_IIFX)
+- write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE);
+ return result;
+ }
+
+@@ -343,9 +359,7 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata,
+
+ hostdata->pdma_residual = len;
+
+- while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
+- BASR_DRQ | BASR_PHASE_MATCH,
+- BASR_DRQ | BASR_PHASE_MATCH, 0)) {
++ while (macscsi_wait_for_drq(hostdata) == 0) {
+ int bytes, chunk_bytes;
+
+ if (macintosh_config->ident == MAC_MODEL_IIFX)
+@@ -355,6 +369,9 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata,
+ chunk_bytes = min(hostdata->pdma_residual, 512);
+ bytes = mac_pdma_send(s, d, chunk_bytes);
+
++ if (macintosh_config->ident == MAC_MODEL_IIFX)
++ write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE);
++
+ if (bytes > 0) {
+ s += bytes;
+ hostdata->pdma_residual -= bytes;
+@@ -369,15 +386,9 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata,
+ "%s: Last Byte Sent timeout\n", __func__);
+ result = -1;
+ }
+- goto out;
++ break;
+ }
+
+- if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH))
+- goto out;
+-
+- if (bytes == 0)
+- udelay(MAC_PDMA_DELAY);
+-
+ if (bytes > 0)
+ continue;
+
+@@ -390,16 +401,9 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata,
+ continue;
+
+ result = -1;
+- goto out;
++ break;
+ }
+
+- scmd_printk(KERN_ERR, hostdata->connected,
+- "%s: phase mismatch or !DRQ\n", __func__);
+- NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host);
+- result = -1;
+-out:
+- if (macintosh_config->ident == MAC_MODEL_IIFX)
+- write_ctrl_reg(hostdata, CTRL_INTERRUPTS_ENABLE);
+ return result;
+ }
+
+--
+2.46.2
+
--- /dev/null
+From 5ec4f820cb9766e4583df947150a6febce8da794 Mon Sep 17 00:00:00 2001
+From: Finn Thain <fthain@linux-m68k.org>
+Date: Wed, 7 Aug 2024 13:36:28 +1000
+Subject: scsi: mac_scsi: Revise printk(KERN_DEBUG ...) messages
+
+From: Finn Thain <fthain@linux-m68k.org>
+
+commit 5ec4f820cb9766e4583df947150a6febce8da794 upstream.
+
+After a bus fault, capture and log the chip registers immediately, if the
+NDEBUG_PSEUDO_DMA macro is defined. Remove some printk(KERN_DEBUG ...)
+messages that aren't needed any more. Don't skip the debug message when
+bytes == 0. Show all of the byte counters in the debug messages.
+
+Cc: stable@vger.kernel.org # 5.15+
+Tested-by: Stan Johnson <userm57@yahoo.com>
+Signed-off-by: Finn Thain <fthain@linux-m68k.org>
+Link: https://lore.kernel.org/r/7573c79f4e488fc00af2b8a191e257ca945e0409.1723001788.git.fthain@linux-m68k.org
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/mac_scsi.c | 42 +++++++++++++++++++++--------------------
+ 1 file changed, 22 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
+index 53ee8f84d094..e67b038a3577 100644
+--- a/drivers/scsi/mac_scsi.c
++++ b/drivers/scsi/mac_scsi.c
+@@ -286,13 +286,14 @@ static inline int macscsi_pread(struct NCR5380_hostdata *hostdata,
+ while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
+ BASR_DRQ | BASR_PHASE_MATCH,
+ BASR_DRQ | BASR_PHASE_MATCH, 0)) {
+- int bytes;
++ int bytes, chunk_bytes;
+
+ if (macintosh_config->ident == MAC_MODEL_IIFX)
+ write_ctrl_reg(hostdata, CTRL_HANDSHAKE_MODE |
+ CTRL_INTERRUPTS_ENABLE);
+
+- bytes = mac_pdma_recv(s, d, min(hostdata->pdma_residual, 512));
++ chunk_bytes = min(hostdata->pdma_residual, 512);
++ bytes = mac_pdma_recv(s, d, chunk_bytes);
+
+ if (bytes > 0) {
+ d += bytes;
+@@ -302,23 +303,23 @@ static inline int macscsi_pread(struct NCR5380_hostdata *hostdata,
+ if (hostdata->pdma_residual == 0)
+ goto out;
+
+- if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ,
+- BUS_AND_STATUS_REG, BASR_ACK,
+- BASR_ACK, 0) < 0)
+- scmd_printk(KERN_DEBUG, hostdata->connected,
+- "%s: !REQ and !ACK\n", __func__);
+ if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH))
+ goto out;
+
+ if (bytes == 0)
+ udelay(MAC_PDMA_DELAY);
+
+- if (bytes >= 0)
++ if (bytes > 0)
+ continue;
+
+- dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host,
+- "%s: bus error (%d/%d)\n", __func__, d - dst, len);
+ NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host);
++ dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host,
++ "%s: bus error [%d/%d] (%d/%d)\n",
++ __func__, d - dst, len, bytes, chunk_bytes);
++
++ if (bytes == 0)
++ continue;
++
+ result = -1;
+ goto out;
+ }
+@@ -345,13 +346,14 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata,
+ while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
+ BASR_DRQ | BASR_PHASE_MATCH,
+ BASR_DRQ | BASR_PHASE_MATCH, 0)) {
+- int bytes;
++ int bytes, chunk_bytes;
+
+ if (macintosh_config->ident == MAC_MODEL_IIFX)
+ write_ctrl_reg(hostdata, CTRL_HANDSHAKE_MODE |
+ CTRL_INTERRUPTS_ENABLE);
+
+- bytes = mac_pdma_send(s, d, min(hostdata->pdma_residual, 512));
++ chunk_bytes = min(hostdata->pdma_residual, 512);
++ bytes = mac_pdma_send(s, d, chunk_bytes);
+
+ if (bytes > 0) {
+ s += bytes;
+@@ -370,23 +372,23 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata,
+ goto out;
+ }
+
+- if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ,
+- BUS_AND_STATUS_REG, BASR_ACK,
+- BASR_ACK, 0) < 0)
+- scmd_printk(KERN_DEBUG, hostdata->connected,
+- "%s: !REQ and !ACK\n", __func__);
+ if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH))
+ goto out;
+
+ if (bytes == 0)
+ udelay(MAC_PDMA_DELAY);
+
+- if (bytes >= 0)
++ if (bytes > 0)
+ continue;
+
+- dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host,
+- "%s: bus error (%d/%d)\n", __func__, s - src, len);
+ NCR5380_dprint(NDEBUG_PSEUDO_DMA, hostdata->host);
++ dsprintk(NDEBUG_PSEUDO_DMA, hostdata->host,
++ "%s: bus error [%d/%d] (%d/%d)\n",
++ __func__, s - src, len, bytes, chunk_bytes);
++
++ if (bytes == 0)
++ continue;
++
+ result = -1;
+ goto out;
+ }
+--
+2.46.2
+
input-i8042-add-another-board-name-for-tuxedo-stellaris-gen5-amd-line.patch
drm-amd-display-round-calculated-vtotal.patch
drm-amd-display-validate-backlight-caps-are-sane.patch
+scsi-mac_scsi-revise-printk-kern_debug-...-messages.patch
+scsi-mac_scsi-refactor-polling-loop.patch
+scsi-mac_scsi-disallow-bus-errors-during-pdma-send.patch
+usbnet-fix-cyclical-race-on-disconnect-with-work-queue.patch
+usb-appledisplay-close-race-between-probe-and-completion-handler.patch
+usb-misc-cypress_cy7c63-check-for-short-transfer.patch
+usb-class-cdc-acm-fix-race-between-get_serial-and-set_serial.patch
+usb-cdnsp-fix-incorrect-usb_request-status.patch
+usb-dwc2-drd-fix-clock-gating-on-usb-role-switch.patch
+bus-integrator-lm-fix-of-node-leak-in-probe.patch
+firmware_loader-block-path-traversal.patch
+tty-rp2-fix-reset-with-non-forgiving-pcie-host-bridges.patch
+xhci-set-quirky-xhc-pci-hosts-to-d3-_after_-stopping-and-freeing-them.patch
+crypto-ccp-properly-unregister-dev-sev-on-sev-platform_status-failure.patch
--- /dev/null
+From f16dd10ba342c429b1e36ada545fb36d4d1f0e63 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian.fainelli@broadcom.com>
+Date: Fri, 6 Sep 2024 15:54:33 -0700
+Subject: tty: rp2: Fix reset with non forgiving PCIe host bridges
+
+From: Florian Fainelli <florian.fainelli@broadcom.com>
+
+commit f16dd10ba342c429b1e36ada545fb36d4d1f0e63 upstream.
+
+The write to RP2_GLOBAL_CMD followed by an immediate read of
+RP2_GLOBAL_CMD in rp2_reset_asic() is intented to flush out the write,
+however by then the device is already in reset and cannot respond to a
+memory cycle access.
+
+On platforms such as the Raspberry Pi 4 and others using the
+pcie-brcmstb.c driver, any memory access to a device that cannot respond
+is met with a fatal system error, rather than being substituted with all
+1s as is usually the case on PC platforms.
+
+Swapping the delay and the read ensures that the device has finished
+resetting before we attempt to read from it.
+
+Fixes: 7d9f49afa451 ("serial: rp2: New driver for Comtrol RocketPort 2 cards")
+Cc: stable <stable@kernel.org>
+Suggested-by: Jim Quinlan <james.quinlan@broadcom.com>
+Signed-off-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://lore.kernel.org/r/20240906225435.707837-1-florian.fainelli@broadcom.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/rp2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/tty/serial/rp2.c
++++ b/drivers/tty/serial/rp2.c
+@@ -598,8 +598,8 @@ static void rp2_reset_asic(struct rp2_ca
+ u32 clk_cfg;
+
+ writew(1, base + RP2_GLOBAL_CMD);
+- readw(base + RP2_GLOBAL_CMD);
+ msleep(100);
++ readw(base + RP2_GLOBAL_CMD);
+ writel(0, base + RP2_CLK_PRESCALER);
+
+ /* TDM clock configuration */
--- /dev/null
+From 8265d06b7794493d82c5c21a12d7ba43eccc30cb Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oneukum@suse.com>
+Date: Thu, 12 Sep 2024 14:32:59 +0200
+Subject: USB: appledisplay: close race between probe and completion handler
+
+From: Oliver Neukum <oneukum@suse.com>
+
+commit 8265d06b7794493d82c5c21a12d7ba43eccc30cb upstream.
+
+There is a small window during probing when IO is running
+but the backlight is not registered. Processing events
+during that time will crash. The completion handler
+needs to check for a backlight before scheduling work.
+
+The bug is as old as the driver.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+CC: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20240912123317.1026049-1-oneukum@suse.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/misc/appledisplay.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/misc/appledisplay.c
++++ b/drivers/usb/misc/appledisplay.c
+@@ -107,7 +107,12 @@ static void appledisplay_complete(struct
+ case ACD_BTN_BRIGHT_UP:
+ case ACD_BTN_BRIGHT_DOWN:
+ pdata->button_pressed = 1;
+- schedule_delayed_work(&pdata->work, 0);
++ /*
++ * there is a window during which no device
++ * is registered
++ */
++ if (pdata->bd )
++ schedule_delayed_work(&pdata->work, 0);
+ break;
+ case ACD_BTN_NONE:
+ default:
+@@ -202,6 +207,7 @@ static int appledisplay_probe(struct usb
+ const struct usb_device_id *id)
+ {
+ struct backlight_properties props;
++ struct backlight_device *backlight;
+ struct appledisplay *pdata;
+ struct usb_device *udev = interface_to_usbdev(iface);
+ struct usb_endpoint_descriptor *endpoint;
+@@ -272,13 +278,14 @@ static int appledisplay_probe(struct usb
+ memset(&props, 0, sizeof(struct backlight_properties));
+ props.type = BACKLIGHT_RAW;
+ props.max_brightness = 0xff;
+- pdata->bd = backlight_device_register(bl_name, NULL, pdata,
++ backlight = backlight_device_register(bl_name, NULL, pdata,
+ &appledisplay_bl_data, &props);
+- if (IS_ERR(pdata->bd)) {
++ if (IS_ERR(backlight)) {
+ dev_err(&iface->dev, "Backlight registration failed\n");
+- retval = PTR_ERR(pdata->bd);
++ retval = PTR_ERR(backlight);
+ goto error;
+ }
++ pdata->bd = backlight;
+
+ /* Try to get brightness */
+ brightness = appledisplay_bl_get_brightness(pdata->bd);
--- /dev/null
+From 1702bec4477cc7d31adb4a760d14d33fac928b7a Mon Sep 17 00:00:00 2001
+From: Pawel Laszczak <pawell@cadence.com>
+Date: Fri, 6 Sep 2024 06:48:54 +0000
+Subject: usb: cdnsp: Fix incorrect usb_request status
+
+From: Pawel Laszczak <pawell@cadence.com>
+
+commit 1702bec4477cc7d31adb4a760d14d33fac928b7a upstream.
+
+Fix changes incorrect usb_request->status returned during disabling
+endpoints. Before fix the status returned during dequeuing requests
+while disabling endpoint was ECONNRESET.
+Patch change it to ESHUTDOWN.
+
+Patch fixes issue detected during testing UVC gadget.
+During stopping streaming the class starts dequeuing usb requests and
+controller driver returns the -ECONNRESET status. After completion
+requests the class or application "uvc-gadget" try to queue this
+request again. Changing this status to ESHUTDOWN cause that UVC assumes
+that endpoint is disabled, or device is disconnected and stops
+re-queuing usb requests.
+
+Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver")
+cc: stable@vger.kernel.org
+Signed-off-by: Pawel Laszczak <pawell@cadence.com>
+Reviewed-by: Peter Chen <peter.chen@kernel.org>
+Link: https://lore.kernel.org/r/PH7PR07MB9538E8CA7A2096AAF6A3718FDD9E2@PH7PR07MB9538.namprd07.prod.outlook.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/cdns3/cdnsp-ring.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/cdns3/cdnsp-ring.c
++++ b/drivers/usb/cdns3/cdnsp-ring.c
+@@ -718,7 +718,8 @@ int cdnsp_remove_request(struct cdnsp_de
+ seg = cdnsp_trb_in_td(pdev, cur_td->start_seg, cur_td->first_trb,
+ cur_td->last_trb, hw_deq);
+
+- if (seg && (pep->ep_state & EP_ENABLED))
++ if (seg && (pep->ep_state & EP_ENABLED) &&
++ !(pep->ep_state & EP_DIS_IN_RROGRESS))
+ cdnsp_find_new_dequeue_state(pdev, pep, preq->request.stream_id,
+ cur_td, &deq_state);
+ else
+@@ -736,7 +737,8 @@ int cdnsp_remove_request(struct cdnsp_de
+ * During disconnecting all endpoint will be disabled so we don't
+ * have to worry about updating dequeue pointer.
+ */
+- if (pdev->cdnsp_state & CDNSP_STATE_DISCONNECT_PENDING) {
++ if (pdev->cdnsp_state & CDNSP_STATE_DISCONNECT_PENDING ||
++ pep->ep_state & EP_DIS_IN_RROGRESS) {
+ status = -ESHUTDOWN;
+ ret = cdnsp_cmd_set_deq(pdev, pep, &deq_state);
+ }
--- /dev/null
+From b41c1fa155ba56d125885b0191aabaf3c508d0a3 Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oneukum@suse.com>
+Date: Thu, 12 Sep 2024 16:19:06 +0200
+Subject: USB: class: CDC-ACM: fix race between get_serial and set_serial
+
+From: Oliver Neukum <oneukum@suse.com>
+
+commit b41c1fa155ba56d125885b0191aabaf3c508d0a3 upstream.
+
+TIOCGSERIAL is an ioctl. Thus it must be atomic. It returns
+two values. Racing with set_serial it can return an inconsistent
+result. The mutex must be taken.
+
+In terms of logic the bug is as old as the driver. In terms of
+code it goes back to the conversion to the get_serial and
+set_serial methods.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+Cc: stable <stable@kernel.org>
+Fixes: 99f75a1fcd865 ("cdc-acm: switch to ->[sg]et_serial()")
+Link: https://lore.kernel.org/r/20240912141916.1044393-1-oneukum@suse.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/class/cdc-acm.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -942,10 +942,12 @@ static int get_serial_info(struct tty_st
+ struct acm *acm = tty->driver_data;
+
+ ss->line = acm->minor;
++ mutex_lock(&acm->port.mutex);
+ ss->close_delay = jiffies_to_msecs(acm->port.close_delay) / 10;
+ ss->closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
+ ASYNC_CLOSING_WAIT_NONE :
+ jiffies_to_msecs(acm->port.closing_wait) / 10;
++ mutex_unlock(&acm->port.mutex);
+ return 0;
+ }
+
--- /dev/null
+From 2c6b6afa59e78bebcb65bbc8a76b3459f139547c Mon Sep 17 00:00:00 2001
+From: Tomas Marek <tomas.marek@elrest.cz>
+Date: Fri, 6 Sep 2024 07:50:25 +0200
+Subject: usb: dwc2: drd: fix clock gating on USB role switch
+
+From: Tomas Marek <tomas.marek@elrest.cz>
+
+commit 2c6b6afa59e78bebcb65bbc8a76b3459f139547c upstream.
+
+The dwc2_handle_usb_suspend_intr() function disables gadget clocks in USB
+peripheral mode when no other power-down mode is available (introduced by
+commit 0112b7ce68ea ("usb: dwc2: Update dwc2_handle_usb_suspend_intr function.")).
+However, the dwc2_drd_role_sw_set() USB role update handler attempts to
+read DWC2 registers if the USB role has changed while the USB is in suspend
+mode (when the clocks are gated). This causes the system to hang.
+
+Release the gadget clocks before handling the USB role update.
+
+Fixes: 0112b7ce68ea ("usb: dwc2: Update dwc2_handle_usb_suspend_intr function.")
+Cc: stable@vger.kernel.org
+Signed-off-by: Tomas Marek <tomas.marek@elrest.cz>
+Link: https://lore.kernel.org/r/20240906055025.25057-1-tomas.marek@elrest.cz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc2/drd.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/usb/dwc2/drd.c
++++ b/drivers/usb/dwc2/drd.c
+@@ -105,6 +105,15 @@ static int dwc2_drd_role_sw_set(struct u
+
+ spin_lock_irqsave(&hsotg->lock, flags);
+
++ if ((IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) ||
++ IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)) &&
++ dwc2_is_device_mode(hsotg) &&
++ hsotg->lx_state == DWC2_L2 &&
++ hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE &&
++ hsotg->bus_suspended &&
++ !hsotg->params.no_clock_gating)
++ dwc2_gadget_exit_clock_gating(hsotg, 0);
++
+ if (role == USB_ROLE_HOST) {
+ already = dwc2_ovr_avalid(hsotg, true);
+ } else if (role == USB_ROLE_DEVICE) {
--- /dev/null
+From 49cd2f4d747eeb3050b76245a7f72aa99dbd3310 Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oneukum@suse.com>
+Date: Thu, 12 Sep 2024 14:54:43 +0200
+Subject: USB: misc: cypress_cy7c63: check for short transfer
+
+From: Oliver Neukum <oneukum@suse.com>
+
+commit 49cd2f4d747eeb3050b76245a7f72aa99dbd3310 upstream.
+
+As we process the second byte of a control transfer, transfers
+of less than 2 bytes must be discarded.
+
+This bug is as old as the driver.
+
+SIgned-off-by: Oliver Neukum <oneukum@suse.com>
+CC: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20240912125449.1030536-1-oneukum@suse.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/misc/cypress_cy7c63.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/usb/misc/cypress_cy7c63.c
++++ b/drivers/usb/misc/cypress_cy7c63.c
+@@ -88,6 +88,9 @@ static int vendor_command(struct cypress
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+ address, data, iobuf, CYPRESS_MAX_REQSIZE,
+ USB_CTRL_GET_TIMEOUT);
++ /* we must not process garbage */
++ if (retval < 2)
++ goto err_buf;
+
+ /* store returned data (more READs to be added) */
+ switch (request) {
+@@ -107,6 +110,7 @@ static int vendor_command(struct cypress
+ break;
+ }
+
++err_buf:
+ kfree(iobuf);
+ error:
+ return retval;
--- /dev/null
+From 04e906839a053f092ef53f4fb2d610983412b904 Mon Sep 17 00:00:00 2001
+From: Oliver Neukum <oneukum@suse.com>
+Date: Thu, 19 Sep 2024 14:33:42 +0200
+Subject: usbnet: fix cyclical race on disconnect with work queue
+
+From: Oliver Neukum <oneukum@suse.com>
+
+commit 04e906839a053f092ef53f4fb2d610983412b904 upstream.
+
+The work can submit URBs and the URBs can schedule the work.
+This cycle needs to be broken, when a device is to be stopped.
+Use a flag to do so.
+This is a design issue as old as the driver.
+
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+CC: stable@vger.kernel.org
+Link: https://patch.msgid.link/20240919123525.688065-1-oneukum@suse.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/usb/usbnet.c | 37 ++++++++++++++++++++++++++++---------
+ include/linux/usb/usbnet.h | 15 +++++++++++++++
+ 2 files changed, 43 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/usb/usbnet.c
++++ b/drivers/net/usb/usbnet.c
+@@ -467,10 +467,15 @@ static enum skb_state defer_bh(struct us
+ void usbnet_defer_kevent (struct usbnet *dev, int work)
+ {
+ set_bit (work, &dev->flags);
+- if (!schedule_work (&dev->kevent))
+- netdev_dbg(dev->net, "kevent %s may have been dropped\n", usbnet_event_names[work]);
+- else
+- netdev_dbg(dev->net, "kevent %s scheduled\n", usbnet_event_names[work]);
++ if (!usbnet_going_away(dev)) {
++ if (!schedule_work(&dev->kevent))
++ netdev_dbg(dev->net,
++ "kevent %s may have been dropped\n",
++ usbnet_event_names[work]);
++ else
++ netdev_dbg(dev->net,
++ "kevent %s scheduled\n", usbnet_event_names[work]);
++ }
+ }
+ EXPORT_SYMBOL_GPL(usbnet_defer_kevent);
+
+@@ -538,7 +543,8 @@ static int rx_submit (struct usbnet *dev
+ tasklet_schedule (&dev->bh);
+ break;
+ case 0:
+- __usbnet_queue_skb(&dev->rxq, skb, rx_start);
++ if (!usbnet_going_away(dev))
++ __usbnet_queue_skb(&dev->rxq, skb, rx_start);
+ }
+ } else {
+ netif_dbg(dev, ifdown, dev->net, "rx: stopped\n");
+@@ -848,9 +854,18 @@ int usbnet_stop (struct net_device *net)
+
+ /* deferred work (timer, softirq, task) must also stop */
+ dev->flags = 0;
+- del_timer_sync (&dev->delay);
+- tasklet_kill (&dev->bh);
++ del_timer_sync(&dev->delay);
++ tasklet_kill(&dev->bh);
+ cancel_work_sync(&dev->kevent);
++
++ /* We have cyclic dependencies. Those calls are needed
++ * to break a cycle. We cannot fall into the gaps because
++ * we have a flag
++ */
++ tasklet_kill(&dev->bh);
++ del_timer_sync(&dev->delay);
++ cancel_work_sync(&dev->kevent);
++
+ if (!pm)
+ usb_autopm_put_interface(dev->intf);
+
+@@ -1176,7 +1191,8 @@ fail_halt:
+ status);
+ } else {
+ clear_bit (EVENT_RX_HALT, &dev->flags);
+- tasklet_schedule (&dev->bh);
++ if (!usbnet_going_away(dev))
++ tasklet_schedule(&dev->bh);
+ }
+ }
+
+@@ -1201,7 +1217,8 @@ fail_halt:
+ usb_autopm_put_interface(dev->intf);
+ fail_lowmem:
+ if (resched)
+- tasklet_schedule (&dev->bh);
++ if (!usbnet_going_away(dev))
++ tasklet_schedule(&dev->bh);
+ }
+ }
+
+@@ -1557,6 +1574,7 @@ static void usbnet_bh (struct timer_list
+ } else if (netif_running (dev->net) &&
+ netif_device_present (dev->net) &&
+ netif_carrier_ok(dev->net) &&
++ !usbnet_going_away(dev) &&
+ !timer_pending(&dev->delay) &&
+ !test_bit(EVENT_RX_PAUSED, &dev->flags) &&
+ !test_bit(EVENT_RX_HALT, &dev->flags)) {
+@@ -1604,6 +1622,7 @@ void usbnet_disconnect (struct usb_inter
+ usb_set_intfdata(intf, NULL);
+ if (!dev)
+ return;
++ usbnet_mark_going_away(dev);
+
+ xdev = interface_to_usbdev (intf);
+
+--- a/include/linux/usb/usbnet.h
++++ b/include/linux/usb/usbnet.h
+@@ -84,8 +84,23 @@ struct usbnet {
+ # define EVENT_LINK_CHANGE 11
+ # define EVENT_SET_RX_MODE 12
+ # define EVENT_NO_IP_ALIGN 13
++/* This one is special, as it indicates that the device is going away
++ * there are cyclic dependencies between tasklet, timer and bh
++ * that must be broken
++ */
++# define EVENT_UNPLUG 31
+ };
+
++static inline bool usbnet_going_away(struct usbnet *ubn)
++{
++ return test_bit(EVENT_UNPLUG, &ubn->flags);
++}
++
++static inline void usbnet_mark_going_away(struct usbnet *ubn)
++{
++ set_bit(EVENT_UNPLUG, &ubn->flags);
++}
++
+ static inline struct usb_driver *driver_of(struct usb_interface *intf)
+ {
+ return to_usb_driver(intf->dev.driver);
--- /dev/null
+From f81dfa3b57c624c56f2bff171c431bc7f5b558f2 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Thu, 5 Sep 2024 17:32:59 +0300
+Subject: xhci: Set quirky xHC PCI hosts to D3 _after_ stopping and freeing them.
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit f81dfa3b57c624c56f2bff171c431bc7f5b558f2 upstream.
+
+PCI xHC host should be stopped and xhci driver memory freed before putting
+host to PCI D3 state during PCI remove callback.
+
+Hosts with XHCI_SPURIOUS_WAKEUP quirk did this the wrong way around
+and set the host to D3 before calling usb_hcd_pci_remove(dev), which will
+access the host to stop it, and then free xhci.
+
+Fixes: f1f6d9a8b540 ("xhci: don't dereference a xhci member after removing xhci")
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20240905143300.1959279-12-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/host/xhci-pci.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -535,8 +535,10 @@ put_runtime_pm:
+ static void xhci_pci_remove(struct pci_dev *dev)
+ {
+ struct xhci_hcd *xhci;
++ bool set_power_d3;
+
+ xhci = hcd_to_xhci(pci_get_drvdata(dev));
++ set_power_d3 = xhci->quirks & XHCI_SPURIOUS_WAKEUP;
+
+ xhci->xhc_state |= XHCI_STATE_REMOVING;
+
+@@ -549,11 +551,11 @@ static void xhci_pci_remove(struct pci_d
+ xhci->shared_hcd = NULL;
+ }
+
++ usb_hcd_pci_remove(dev);
++
+ /* Workaround for spurious wakeups at shutdown with HSW */
+- if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
++ if (set_power_d3)
+ pci_set_power_state(dev, PCI_D3hot);
+-
+- usb_hcd_pci_remove(dev);
+ }
+
+ #ifdef CONFIG_PM