--- /dev/null
+From d0031edcb841638bb995afdc6f0514421a48b5d0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2020 15:02:01 +0300
+Subject: iio: dac: ad5592r-base: Replace indio_dev->mlock with own device lock
+
+From: Sergiu Cuciurean <sergiu.cuciurean@analog.com>
+
+[ Upstream commit 33c53cbf8f7bc8d62f6146a19da97c8594376ff0 ]
+
+As part of the general cleanup of indio_dev->mlock, this change replaces
+it with a local lock on the device's state structure.
+This also removes unused iio_dev pointers.
+
+Signed-off-by: Sergiu Cuciurean <sergiu.cuciurean@analog.com>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 279428df8883 ("iio: dac: ad5592r: fix temperature channel scaling value")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/dac/ad5592r-base.c | 30 +++++++++++++++---------------
+ drivers/iio/dac/ad5592r-base.h | 1 +
+ 2 files changed, 16 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c
+index 8011245a01d77..87824c03c0124 100644
+--- a/drivers/iio/dac/ad5592r-base.c
++++ b/drivers/iio/dac/ad5592r-base.c
+@@ -158,7 +158,6 @@ static void ad5592r_gpio_cleanup(struct ad5592r_state *st)
+ static int ad5592r_reset(struct ad5592r_state *st)
+ {
+ struct gpio_desc *gpio;
+- struct iio_dev *iio_dev = iio_priv_to_dev(st);
+
+ gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(gpio))
+@@ -168,10 +167,10 @@ static int ad5592r_reset(struct ad5592r_state *st)
+ udelay(1);
+ gpiod_set_value(gpio, 1);
+ } else {
+- mutex_lock(&iio_dev->mlock);
++ mutex_lock(&st->lock);
+ /* Writing this magic value resets the device */
+ st->ops->reg_write(st, AD5592R_REG_RESET, 0xdac);
+- mutex_unlock(&iio_dev->mlock);
++ mutex_unlock(&st->lock);
+ }
+
+ udelay(250);
+@@ -199,7 +198,6 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
+ const struct ad5592r_rw_ops *ops = st->ops;
+ int ret;
+ unsigned i;
+- struct iio_dev *iio_dev = iio_priv_to_dev(st);
+ u8 pulldown = 0, tristate = 0, dac = 0, adc = 0;
+ u16 read_back;
+
+@@ -249,7 +247,7 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
+ }
+ }
+
+- mutex_lock(&iio_dev->mlock);
++ mutex_lock(&st->lock);
+
+ /* Pull down unused pins to GND */
+ ret = ops->reg_write(st, AD5592R_REG_PULLDOWN, pulldown);
+@@ -287,7 +285,7 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
+ ret = -EIO;
+
+ err_unlock:
+- mutex_unlock(&iio_dev->mlock);
++ mutex_unlock(&st->lock);
+ return ret;
+ }
+
+@@ -316,11 +314,11 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev,
+ if (!chan->output)
+ return -EINVAL;
+
+- mutex_lock(&iio_dev->mlock);
++ mutex_lock(&st->lock);
+ ret = st->ops->write_dac(st, chan->channel, val);
+ if (!ret)
+ st->cached_dac[chan->channel] = val;
+- mutex_unlock(&iio_dev->mlock);
++ mutex_unlock(&st->lock);
+ return ret;
+ case IIO_CHAN_INFO_SCALE:
+ if (chan->type == IIO_VOLTAGE) {
+@@ -335,12 +333,12 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev,
+ else
+ return -EINVAL;
+
+- mutex_lock(&iio_dev->mlock);
++ mutex_lock(&st->lock);
+
+ ret = st->ops->reg_read(st, AD5592R_REG_CTRL,
+ &st->cached_gp_ctrl);
+ if (ret < 0) {
+- mutex_unlock(&iio_dev->mlock);
++ mutex_unlock(&st->lock);
+ return ret;
+ }
+
+@@ -362,7 +360,7 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev,
+
+ ret = st->ops->reg_write(st, AD5592R_REG_CTRL,
+ st->cached_gp_ctrl);
+- mutex_unlock(&iio_dev->mlock);
++ mutex_unlock(&st->lock);
+
+ return ret;
+ }
+@@ -384,7 +382,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
+
+ switch (m) {
+ case IIO_CHAN_INFO_RAW:
+- mutex_lock(&iio_dev->mlock);
++ mutex_lock(&st->lock);
+
+ if (!chan->output) {
+ ret = st->ops->read_adc(st, chan->channel, &read_val);
+@@ -421,7 +419,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
+ } else {
+ int mult;
+
+- mutex_lock(&iio_dev->mlock);
++ mutex_lock(&st->lock);
+
+ if (chan->output)
+ mult = !!(st->cached_gp_ctrl &
+@@ -439,7 +437,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
+ case IIO_CHAN_INFO_OFFSET:
+ ret = ad5592r_get_vref(st);
+
+- mutex_lock(&iio_dev->mlock);
++ mutex_lock(&st->lock);
+
+ if (st->cached_gp_ctrl & AD5592R_REG_CTRL_ADC_RANGE)
+ *val = (-34365 * 25) / ret;
+@@ -452,7 +450,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
+ }
+
+ unlock:
+- mutex_unlock(&iio_dev->mlock);
++ mutex_unlock(&st->lock);
+ return ret;
+ }
+
+@@ -627,6 +625,8 @@ int ad5592r_probe(struct device *dev, const char *name,
+ iio_dev->info = &ad5592r_info;
+ iio_dev->modes = INDIO_DIRECT_MODE;
+
++ mutex_init(&st->lock);
++
+ ad5592r_init_scales(st, ad5592r_get_vref(st));
+
+ ret = ad5592r_reset(st);
+diff --git a/drivers/iio/dac/ad5592r-base.h b/drivers/iio/dac/ad5592r-base.h
+index 841457e93f851..046936068b638 100644
+--- a/drivers/iio/dac/ad5592r-base.h
++++ b/drivers/iio/dac/ad5592r-base.h
+@@ -53,6 +53,7 @@ struct ad5592r_state {
+ struct regulator *reg;
+ struct gpio_chip gpiochip;
+ struct mutex gpio_lock; /* Protect cached gpio_out, gpio_val, etc. */
++ struct mutex lock;
+ unsigned int num_channels;
+ const struct ad5592r_rw_ops *ops;
+ int scale_avail[2][2];
+--
+2.43.0
+
--- /dev/null
+From 2ede9689d47b3f1a4b74f776d8cc8eab16afdf88 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 1 May 2024 11:05:54 -0400
+Subject: iio: dac: ad5592r: fix temperature channel scaling value
+
+From: Marc Ferland <marc.ferland@sonatest.com>
+
+[ Upstream commit 279428df888319bf68f2686934897301a250bb84 ]
+
+The scale value for the temperature channel is (assuming Vref=2.5 and
+the datasheet):
+
+ 376.7897513
+
+When calculating both val and val2 for the temperature scale we
+use (3767897513/25) and multiply it by Vref (here I assume 2500mV) to
+obtain:
+
+ 2500 * (3767897513/25) ==> 376789751300
+
+Finally we divide with remainder by 10^9 to get:
+
+ val = 376
+ val2 = 789751300
+
+However, we return IIO_VAL_INT_PLUS_MICRO (should have been NANO) as
+the scale type. So when converting the raw temperature value to the
+'processed' temperature value we will get (assuming raw=810,
+offset=-753):
+
+ processed = (raw + offset) * scale_val
+ = (810 + -753) * 376
+ = 21432
+
+ processed += div((raw + offset) * scale_val2, 10^6)
+ += div((810 + -753) * 789751300, 10^6)
+ += 45015
+ ==> 66447
+ ==> 66.4 Celcius
+
+instead of the expected 21.5 Celsius.
+
+Fix this issue by changing IIO_VAL_INT_PLUS_MICRO to
+IIO_VAL_INT_PLUS_NANO.
+
+Fixes: 56ca9db862bf ("iio: dac: Add support for the AD5592R/AD5593R ADCs/DACs")
+Signed-off-by: Marc Ferland <marc.ferland@sonatest.com>
+Link: https://lore.kernel.org/r/20240501150554.1871390-1-marc.ferland@sonatest.com
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/dac/ad5592r-base.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c
+index 427946be41872..414134412a5f8 100644
+--- a/drivers/iio/dac/ad5592r-base.c
++++ b/drivers/iio/dac/ad5592r-base.c
+@@ -415,7 +415,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
+ s64 tmp = *val * (3767897513LL / 25LL);
+ *val = div_s64_rem(tmp, 1000000000LL, val2);
+
+- return IIO_VAL_INT_PLUS_MICRO;
++ return IIO_VAL_INT_PLUS_NANO;
+ }
+
+ mutex_lock(&st->lock);
+--
+2.43.0
+
--- /dev/null
+From a73e7ea06cd10a0061499754927891928f635dc0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Jul 2020 14:02:58 +0300
+Subject: iio: dac: ad5592r: un-indent code-block for scale read
+
+From: Alexandru Ardelean <alexandru.ardelean@analog.com>
+
+[ Upstream commit b004fe33034cc64f72c20923be71cf1e6c9a624c ]
+
+The next rework may require an unindentation of a code block in
+ad5592r_read_raw(), which would make review a bit more difficult.
+
+This change unindents the code block for reading the scale of the
+non-temperature channels.
+
+Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
+Link: https://lore.kernel.org/r/20200706110259.23947-2-alexandru.ardelean@analog.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 279428df8883 ("iio: dac: ad5592r: fix temperature channel scaling value")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/dac/ad5592r-base.c | 26 ++++++++++++--------------
+ 1 file changed, 12 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c
+index 87824c03c0124..427946be41872 100644
+--- a/drivers/iio/dac/ad5592r-base.c
++++ b/drivers/iio/dac/ad5592r-base.c
+@@ -378,7 +378,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
+ {
+ struct ad5592r_state *st = iio_priv(iio_dev);
+ u16 read_val;
+- int ret;
++ int ret, mult;
+
+ switch (m) {
+ case IIO_CHAN_INFO_RAW:
+@@ -416,23 +416,21 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
+ *val = div_s64_rem(tmp, 1000000000LL, val2);
+
+ return IIO_VAL_INT_PLUS_MICRO;
+- } else {
+- int mult;
++ }
+
+- mutex_lock(&st->lock);
++ mutex_lock(&st->lock);
+
+- if (chan->output)
+- mult = !!(st->cached_gp_ctrl &
+- AD5592R_REG_CTRL_DAC_RANGE);
+- else
+- mult = !!(st->cached_gp_ctrl &
+- AD5592R_REG_CTRL_ADC_RANGE);
++ if (chan->output)
++ mult = !!(st->cached_gp_ctrl &
++ AD5592R_REG_CTRL_DAC_RANGE);
++ else
++ mult = !!(st->cached_gp_ctrl &
++ AD5592R_REG_CTRL_ADC_RANGE);
+
+- *val *= ++mult;
++ *val *= ++mult;
+
+- *val2 = chan->scan_type.realbits;
+- ret = IIO_VAL_FRACTIONAL_LOG2;
+- }
++ *val2 = chan->scan_type.realbits;
++ ret = IIO_VAL_FRACTIONAL_LOG2;
+ break;
+ case IIO_CHAN_INFO_OFFSET:
+ ret = ad5592r_get_vref(st);
+--
+2.43.0
+
--- /dev/null
+From d57f56efe757cf1ca1ab585b8542bb9964e46b3d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Jun 2020 15:56:53 -0700
+Subject: mm: memblock: replace dereferences of memblock_region.nid with API
+ calls
+
+From: Mike Rapoport <rppt@linux.ibm.com>
+
+[ Upstream commit d622abf74f3d81365e41c3bfdbbda50ecd99ba3d ]
+
+Patch series "mm: rework free_area_init*() funcitons".
+
+After the discussion [1] about removal of CONFIG_NODES_SPAN_OTHER_NODES
+and CONFIG_HAVE_MEMBLOCK_NODE_MAP options, I took it a bit further and
+updated the node/zone initialization.
+
+Since all architectures have memblock, it is possible to use only the
+newer version of free_area_init_node() that calculates the zone and node
+boundaries based on memblock node mapping and architectural limits on
+possible zone PFNs.
+
+The architectures that still determined zone and hole sizes can be
+switched to the generic code and the old code that took those zone and
+hole sizes can be simply removed.
+
+And, since it all started from the removal of
+CONFIG_NODES_SPAN_OTHER_NODES, the memmap_init() is now updated to iterate
+over memblocks and so it does not need to perform early_pfn_to_nid() query
+for every PFN.
+
+[1] https://lore.kernel.org/lkml/1585420282-25630-1-git-send-email-Hoan@os.amperecomputing.com
+
+This patch (of 21):
+
+There are several places in the code that directly dereference
+memblock_region.nid despite this field being defined only when
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y.
+
+Replace these with calls to memblock_get_region_nid() to improve code
+robustness and to avoid possible breakage when
+CONFIG_HAVE_MEMBLOCK_NODE_MAP will be removed.
+
+Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Tested-by: Hoan Tran <hoan@os.amperecomputing.com> [arm64]
+Reviewed-by: Baoquan He <bhe@redhat.com>
+Cc: Brian Cain <bcain@codeaurora.org>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: Geert Uytterhoeven <geert@linux-m68k.org>
+Cc: Greentime Hu <green.hu@gmail.com>
+Cc: Greg Ungerer <gerg@linux-m68k.org>
+Cc: Guan Xuetao <gxt@pku.edu.cn>
+Cc: Guo Ren <guoren@kernel.org>
+Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
+Cc: Helge Deller <deller@gmx.de>
+Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
+Cc: Jonathan Corbet <corbet@lwn.net>
+Cc: Ley Foon Tan <ley.foon.tan@intel.com>
+Cc: Mark Salter <msalter@redhat.com>
+Cc: Matt Turner <mattst88@gmail.com>
+Cc: Max Filippov <jcmvbkbc@gmail.com>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: Michal Hocko <mhocko@kernel.org>
+Cc: Michal Simek <monstr@monstr.eu>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Nick Hu <nickhu@andestech.com>
+Cc: Paul Walmsley <paul.walmsley@sifive.com>
+Cc: Richard Weinberger <richard@nod.at>
+Cc: Rich Felker <dalias@libc.org>
+Cc: Russell King <linux@armlinux.org.uk>
+Cc: Stafford Horne <shorne@gmail.com>
+Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Cc: Tony Luck <tony.luck@intel.com>
+Cc: Vineet Gupta <vgupta@synopsys.com>
+Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
+Link: http://lkml.kernel.org/r/20200412194859.12663-1-rppt@kernel.org
+Link: http://lkml.kernel.org/r/20200412194859.12663-2-rppt@kernel.org
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Stable-dep-of: 3ac36aa73073 ("x86/mm/numa: Use NUMA_NO_NODE when calling memblock_set_node()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/mm/numa.c | 9 ++++++---
+ arch/x86/mm/numa.c | 6 ++++--
+ mm/memblock.c | 8 +++++---
+ mm/page_alloc.c | 4 ++--
+ 4 files changed, 17 insertions(+), 10 deletions(-)
+
+diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
+index 15eaf1e09d0ca..f2f4c056822a7 100644
+--- a/arch/arm64/mm/numa.c
++++ b/arch/arm64/mm/numa.c
+@@ -365,13 +365,16 @@ static int __init numa_register_nodes(void)
+ struct memblock_region *mblk;
+
+ /* Check that valid nid is set to memblks */
+- for_each_memblock(memory, mblk)
+- if (mblk->nid == NUMA_NO_NODE || mblk->nid >= MAX_NUMNODES) {
++ for_each_memblock(memory, mblk) {
++ int mblk_nid = memblock_get_region_node(mblk);
++
++ if (mblk_nid == NUMA_NO_NODE || mblk_nid >= MAX_NUMNODES) {
+ pr_warn("Warning: invalid memblk node %d [mem %#010Lx-%#010Lx]\n",
+- mblk->nid, mblk->base,
++ mblk_nid, mblk->base,
+ mblk->base + mblk->size - 1);
+ return -EINVAL;
+ }
++ }
+
+ /* Finally register nodes. */
+ for_each_node_mask(nid, numa_nodes_parsed) {
+diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
+index a830d49341ecc..411ded8664a9e 100644
+--- a/arch/x86/mm/numa.c
++++ b/arch/x86/mm/numa.c
+@@ -506,8 +506,10 @@ static void __init numa_clear_kernel_node_hotplug(void)
+ * reserve specific pages for Sandy Bridge graphics. ]
+ */
+ for_each_memblock(reserved, mb_region) {
+- if (mb_region->nid != MAX_NUMNODES)
+- node_set(mb_region->nid, reserved_nodemask);
++ int nid = memblock_get_region_node(mb_region);
++
++ if (nid != MAX_NUMNODES)
++ node_set(nid, reserved_nodemask);
+ }
+
+ /*
+diff --git a/mm/memblock.c b/mm/memblock.c
+index 4d471da3cc479..0510d6c7ad14c 100644
+--- a/mm/memblock.c
++++ b/mm/memblock.c
+@@ -1147,13 +1147,15 @@ void __init_memblock __next_mem_pfn_range(int *idx, int nid,
+ {
+ struct memblock_type *type = &memblock.memory;
+ struct memblock_region *r;
++ int r_nid;
+
+ while (++*idx < type->cnt) {
+ r = &type->regions[*idx];
++ r_nid = memblock_get_region_node(r);
+
+ if (PFN_UP(r->base) >= PFN_DOWN(r->base + r->size))
+ continue;
+- if (nid == MAX_NUMNODES || nid == r->nid)
++ if (nid == MAX_NUMNODES || nid == r_nid)
+ break;
+ }
+ if (*idx >= type->cnt) {
+@@ -1166,7 +1168,7 @@ void __init_memblock __next_mem_pfn_range(int *idx, int nid,
+ if (out_end_pfn)
+ *out_end_pfn = PFN_DOWN(r->base + r->size);
+ if (out_nid)
+- *out_nid = r->nid;
++ *out_nid = r_nid;
+ }
+
+ /**
+@@ -1714,7 +1716,7 @@ int __init_memblock memblock_search_pfn_nid(unsigned long pfn,
+ *start_pfn = PFN_DOWN(type->regions[mid].base);
+ *end_pfn = PFN_DOWN(type->regions[mid].base + type->regions[mid].size);
+
+- return type->regions[mid].nid;
++ return memblock_get_region_node(&type->regions[mid]);
+ }
+ #endif
+
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 147b67d31431d..b8cccd1a9965e 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -6743,7 +6743,7 @@ static void __init find_zone_movable_pfns_for_nodes(void)
+ if (!memblock_is_hotpluggable(r))
+ continue;
+
+- nid = r->nid;
++ nid = memblock_get_region_node(r);
+
+ usable_startpfn = PFN_DOWN(r->base);
+ zone_movable_pfn[nid] = zone_movable_pfn[nid] ?
+@@ -6764,7 +6764,7 @@ static void __init find_zone_movable_pfns_for_nodes(void)
+ if (memblock_is_mirror(r))
+ continue;
+
+- nid = r->nid;
++ nid = memblock_get_region_node(r);
+
+ usable_startpfn = memblock_region_memory_base_pfn(r);
+
+--
+2.43.0
+
--- /dev/null
+From cb46c1bbc6ca0b6ddf0fc572b9a533bec68e056d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Sep 2018 08:01:08 -0700
+Subject: scsi: mpt3sas: Add ioc_<level> logging macros
+
+From: Joe Perches <joe@perches.com>
+
+[ Upstream commit 645a20c6821cd1ab58af8a1f99659e619c216efd ]
+
+These macros can help identify specific logging uses and eventually perhaps
+reduce object sizes.
+
+Signed-off-by: Joe Perches <joe@perches.com>
+Acked-by: Suganath Prabu <suganath-prabu.subramani@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: 4254dfeda82f ("scsi: mpt3sas: Avoid test/set_bit() operating in non-allocated memory")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/mpt3sas/mpt3sas_base.h | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
+index 96dc15e90bd83..941a4faf20be0 100644
+--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
++++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
+@@ -160,6 +160,15 @@ struct mpt3sas_nvme_cmd {
+ */
+ #define MPT3SAS_FMT "%s: "
+
++#define ioc_err(ioc, fmt, ...) \
++ pr_err("%s: " fmt, (ioc)->name, ##__VA_ARGS__)
++#define ioc_notice(ioc, fmt, ...) \
++ pr_notice("%s: " fmt, (ioc)->name, ##__VA_ARGS__)
++#define ioc_warn(ioc, fmt, ...) \
++ pr_warn("%s: " fmt, (ioc)->name, ##__VA_ARGS__)
++#define ioc_info(ioc, fmt, ...) \
++ pr_info("%s: " fmt, (ioc)->name, ##__VA_ARGS__)
++
+ /*
+ * WarpDrive Specific Log codes
+ */
+--
+2.43.0
+
--- /dev/null
+From a4769c3002e64f7127afd2d5b79cded80dacd4be Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Jun 2024 01:55:29 -0700
+Subject: scsi: mpt3sas: Avoid test/set_bit() operating in non-allocated memory
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit 4254dfeda82f20844299dca6c38cbffcfd499f41 ]
+
+There is a potential out-of-bounds access when using test_bit() on a single
+word. The test_bit() and set_bit() functions operate on long values, and
+when testing or setting a single word, they can exceed the word
+boundary. KASAN detects this issue and produces a dump:
+
+ BUG: KASAN: slab-out-of-bounds in _scsih_add_device.constprop.0 (./arch/x86/include/asm/bitops.h:60 ./include/asm-generic/bitops/instrumented-atomic.h:29 drivers/scsi/mpt3sas/mpt3sas_scsih.c:7331) mpt3sas
+
+ Write of size 8 at addr ffff8881d26e3c60 by task kworker/u1536:2/2965
+
+For full log, please look at [1].
+
+Make the allocation at least the size of sizeof(unsigned long) so that
+set_bit() and test_bit() have sufficient room for read/write operations
+without overwriting unallocated memory.
+
+[1] Link: https://lore.kernel.org/all/ZkNcALr3W3KGYYJG@gmail.com/
+
+Fixes: c696f7b83ede ("scsi: mpt3sas: Implement device_remove_in_progress check in IOCTL path")
+Cc: stable@vger.kernel.org
+Suggested-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Link: https://lore.kernel.org/r/20240605085530.499432-1-leitao@debian.org
+Reviewed-by: Keith Busch <kbusch@kernel.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/mpt3sas/mpt3sas_base.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
+index 54faddb637c46..b4495023edb71 100644
+--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
++++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
+@@ -6612,6 +6612,12 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
+ ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8);
+ if (ioc->facts.MaxDevHandle % 8)
+ ioc->pd_handles_sz++;
++ /*
++ * pd_handles_sz should have, at least, the minimal room for
++ * set_bit()/test_bit(), otherwise out-of-memory touch may occur.
++ */
++ ioc->pd_handles_sz = ALIGN(ioc->pd_handles_sz, sizeof(unsigned long));
++
+ ioc->pd_handles = kzalloc(ioc->pd_handles_sz,
+ GFP_KERNEL);
+ if (!ioc->pd_handles) {
+@@ -6629,6 +6635,13 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
+ ioc->pend_os_device_add_sz = (ioc->facts.MaxDevHandle / 8);
+ if (ioc->facts.MaxDevHandle % 8)
+ ioc->pend_os_device_add_sz++;
++
++ /*
++ * pend_os_device_add_sz should have, at least, the minimal room for
++ * set_bit()/test_bit(), otherwise out-of-memory may occur.
++ */
++ ioc->pend_os_device_add_sz = ALIGN(ioc->pend_os_device_add_sz,
++ sizeof(unsigned long));
+ ioc->pend_os_device_add = kzalloc(ioc->pend_os_device_add_sz,
+ GFP_KERNEL);
+ if (!ioc->pend_os_device_add) {
+@@ -6911,6 +6924,12 @@ _base_check_ioc_facts_changes(struct MPT3SAS_ADAPTER *ioc)
+ if (ioc->facts.MaxDevHandle % 8)
+ pd_handles_sz++;
+
++ /*
++ * pd_handles should have, at least, the minimal room for
++ * set_bit()/test_bit(), otherwise out-of-memory touch may
++ * occur.
++ */
++ pd_handles_sz = ALIGN(pd_handles_sz, sizeof(unsigned long));
+ pd_handles = krealloc(ioc->pd_handles, pd_handles_sz,
+ GFP_KERNEL);
+ if (!pd_handles) {
+--
+2.43.0
+
--- /dev/null
+From 320ce11c45ce39043c4159989e715a3f1c2e1891 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 3 Aug 2019 09:59:48 -0400
+Subject: scsi: mpt3sas: Gracefully handle online firmware update
+
+From: Suganath Prabu <suganath-prabu.subramani@broadcom.com>
+
+[ Upstream commit ffedeae1fa545a1d07e6827180c3923bf67af59f ]
+
+Issue:
+
+During online Firmware upgrade operations it is possible that MaxDevHandles
+filled in IOCFacts may change with new FW. With this we may observe kernel
+panics when driver try to access the pd_handles or blocking_handles buffers
+at offset greater than the old firmware's MaxDevHandle value.
+
+Fix:
+
+_base_check_ioc_facts_changes() looks for increase/decrease in IOCFacts
+attributes during online firmware upgrade and increases the pd_handles,
+blocking_handles, etc buffer sizes to new firmware's MaxDevHandle value if
+this new firmware's MaxDevHandle value is greater than the old firmware's
+MaxDevHandle value.
+
+Signed-off-by: Suganath Prabu <suganath-prabu.subramani@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: 4254dfeda82f ("scsi: mpt3sas: Avoid test/set_bit() operating in non-allocated memory")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/mpt3sas/mpt3sas_base.c | 93 +++++++++++++++++++++++++++++
+ drivers/scsi/mpt3sas/mpt3sas_base.h | 2 +
+ 2 files changed, 95 insertions(+)
+
+diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
+index 7588c2c11a879..54faddb637c46 100644
+--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
++++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
+@@ -6719,6 +6719,13 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
+ if (r)
+ goto out_free_resources;
+
++ /*
++ * Copy current copy of IOCFacts in prev_fw_facts
++ * and it will be used during online firmware upgrade.
++ */
++ memcpy(&ioc->prev_fw_facts, &ioc->facts,
++ sizeof(struct mpt3sas_facts));
++
+ ioc->non_operational_loop = 0;
+ ioc->got_task_abort_from_ioctl = 0;
+ return 0;
+@@ -6884,6 +6891,85 @@ mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc)
+ wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ);
+ }
+
++/**
++ * _base_check_ioc_facts_changes - Look for increase/decrease of IOCFacts
++ * attributes during online firmware upgrade and update the corresponding
++ * IOC variables accordingly.
++ *
++ * @ioc: Pointer to MPT_ADAPTER structure
++ */
++static int
++_base_check_ioc_facts_changes(struct MPT3SAS_ADAPTER *ioc)
++{
++ u16 pd_handles_sz;
++ void *pd_handles = NULL, *blocking_handles = NULL;
++ void *pend_os_device_add = NULL, *device_remove_in_progress = NULL;
++ struct mpt3sas_facts *old_facts = &ioc->prev_fw_facts;
++
++ if (ioc->facts.MaxDevHandle > old_facts->MaxDevHandle) {
++ pd_handles_sz = (ioc->facts.MaxDevHandle / 8);
++ if (ioc->facts.MaxDevHandle % 8)
++ pd_handles_sz++;
++
++ pd_handles = krealloc(ioc->pd_handles, pd_handles_sz,
++ GFP_KERNEL);
++ if (!pd_handles) {
++ ioc_info(ioc,
++ "Unable to allocate the memory for pd_handles of sz: %d\n",
++ pd_handles_sz);
++ return -ENOMEM;
++ }
++ memset(pd_handles + ioc->pd_handles_sz, 0,
++ (pd_handles_sz - ioc->pd_handles_sz));
++ ioc->pd_handles = pd_handles;
++
++ blocking_handles = krealloc(ioc->blocking_handles,
++ pd_handles_sz, GFP_KERNEL);
++ if (!blocking_handles) {
++ ioc_info(ioc,
++ "Unable to allocate the memory for "
++ "blocking_handles of sz: %d\n",
++ pd_handles_sz);
++ return -ENOMEM;
++ }
++ memset(blocking_handles + ioc->pd_handles_sz, 0,
++ (pd_handles_sz - ioc->pd_handles_sz));
++ ioc->blocking_handles = blocking_handles;
++ ioc->pd_handles_sz = pd_handles_sz;
++
++ pend_os_device_add = krealloc(ioc->pend_os_device_add,
++ pd_handles_sz, GFP_KERNEL);
++ if (!pend_os_device_add) {
++ ioc_info(ioc,
++ "Unable to allocate the memory for pend_os_device_add of sz: %d\n",
++ pd_handles_sz);
++ return -ENOMEM;
++ }
++ memset(pend_os_device_add + ioc->pend_os_device_add_sz, 0,
++ (pd_handles_sz - ioc->pend_os_device_add_sz));
++ ioc->pend_os_device_add = pend_os_device_add;
++ ioc->pend_os_device_add_sz = pd_handles_sz;
++
++ device_remove_in_progress = krealloc(
++ ioc->device_remove_in_progress, pd_handles_sz, GFP_KERNEL);
++ if (!device_remove_in_progress) {
++ ioc_info(ioc,
++ "Unable to allocate the memory for "
++ "device_remove_in_progress of sz: %d\n "
++ , pd_handles_sz);
++ return -ENOMEM;
++ }
++ memset(device_remove_in_progress +
++ ioc->device_remove_in_progress_sz, 0,
++ (pd_handles_sz - ioc->device_remove_in_progress_sz));
++ ioc->device_remove_in_progress = device_remove_in_progress;
++ ioc->device_remove_in_progress_sz = pd_handles_sz;
++ }
++
++ memcpy(&ioc->prev_fw_facts, &ioc->facts, sizeof(struct mpt3sas_facts));
++ return 0;
++}
++
+ /**
+ * mpt3sas_base_hard_reset_handler - reset controller
+ * @ioc: Pointer to MPT_ADAPTER structure
+@@ -6949,6 +7035,13 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc,
+ if (r)
+ goto out;
+
++ r = _base_check_ioc_facts_changes(ioc);
++ if (r) {
++ ioc_info(ioc,
++ "Some of the parameters got changed in this new firmware"
++ " image and it requires system reboot\n");
++ goto out;
++ }
+ if (ioc->rdpq_array_enable && !ioc->rdpq_array_capable)
+ panic("%s: Issue occurred with flashing controller firmware."
+ "Please reboot the system and ensure that the correct"
+diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
+index 941a4faf20be0..b0297a9c92389 100644
+--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
++++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
+@@ -1032,6 +1032,7 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
+ * @event_log: event log pointer
+ * @event_masks: events that are masked
+ * @facts: static facts data
++ * @prev_fw_facts: previous fw facts data
+ * @pfacts: static port facts data
+ * @manu_pg0: static manufacturing page 0
+ * @manu_pg10: static manufacturing page 10
+@@ -1235,6 +1236,7 @@ struct MPT3SAS_ADAPTER {
+
+ /* static config pages */
+ struct mpt3sas_facts facts;
++ struct mpt3sas_facts prev_fw_facts;
+ struct mpt3sas_port_facts *pfacts;
+ Mpi2ManufacturingPage0_t manu_pg0;
+ struct Mpi2ManufacturingPage10_t manu_pg10;
+--
+2.43.0
+
perf-core-fix-missing-wakeup-when-waiting-for-contex.patch
pci-add-pci_error_response-and-related-definitions.patch
x86-amd_nb-check-for-invalid-smn-reads.patch
+iio-dac-ad5592r-base-replace-indio_dev-mlock-with-ow.patch
+iio-dac-ad5592r-un-indent-code-block-for-scale-read.patch
+iio-dac-ad5592r-fix-temperature-channel-scaling-valu.patch
+scsi-mpt3sas-add-ioc_-level-logging-macros.patch
+scsi-mpt3sas-gracefully-handle-online-firmware-updat.patch
+scsi-mpt3sas-avoid-test-set_bit-operating-in-non-all.patch
+mm-memblock-replace-dereferences-of-memblock_region..patch
+x86-mm-numa-use-numa_no_node-when-calling-memblock_s.patch
+xhci-use-soft-retry-to-recover-faster-from-transacti.patch
+xhci-set-correct-transferred-length-for-cancelled-bu.patch
--- /dev/null
+From d6322292e8cd794c12927256eb1390d2415370ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 May 2024 09:42:05 +0200
+Subject: x86/mm/numa: Use NUMA_NO_NODE when calling memblock_set_node()
+
+From: Jan Beulich <jbeulich@suse.com>
+
+[ Upstream commit 3ac36aa7307363b7247ccb6f6a804e11496b2b36 ]
+
+memblock_set_node() warns about using MAX_NUMNODES, see
+
+ e0eec24e2e19 ("memblock: make memblock_set_node() also warn about use of MAX_NUMNODES")
+
+for details.
+
+Reported-by: Narasimhan V <Narasimhan.V@amd.com>
+Signed-off-by: Jan Beulich <jbeulich@suse.com>
+Cc: stable@vger.kernel.org
+[bp: commit message]
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Mike Rapoport (IBM) <rppt@kernel.org>
+Tested-by: Paul E. McKenney <paulmck@kernel.org>
+Link: https://lore.kernel.org/r/20240603141005.23261-1-bp@kernel.org
+Link: https://lore.kernel.org/r/abadb736-a239-49e4-ab42-ace7acdd4278@suse.com
+Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/numa.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
+index 411ded8664a9e..b018eac5e4191 100644
+--- a/arch/x86/mm/numa.c
++++ b/arch/x86/mm/numa.c
+@@ -508,7 +508,7 @@ static void __init numa_clear_kernel_node_hotplug(void)
+ for_each_memblock(reserved, mb_region) {
+ int nid = memblock_get_region_node(mb_region);
+
+- if (nid != MAX_NUMNODES)
++ if (nid != NUMA_NO_NODE)
+ node_set(nid, reserved_nodemask);
+ }
+
+@@ -628,9 +628,9 @@ static int __init numa_init(int (*init_func)(void))
+ nodes_clear(node_online_map);
+ memset(&numa_meminfo, 0, sizeof(numa_meminfo));
+ WARN_ON(memblock_set_node(0, ULLONG_MAX, &memblock.memory,
+- MAX_NUMNODES));
++ NUMA_NO_NODE));
+ WARN_ON(memblock_set_node(0, ULLONG_MAX, &memblock.reserved,
+- MAX_NUMNODES));
++ NUMA_NO_NODE));
+ /* In case that parsing SRAT failed. */
+ WARN_ON(memblock_clear_hotplug(0, ULLONG_MAX));
+ numa_reset_distance();
+--
+2.43.0
+
--- /dev/null
+From 01e13cbf55110bb2d791e9ce7cee087b7725edbb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jun 2024 15:06:07 +0300
+Subject: xhci: Set correct transferred length for cancelled bulk transfers
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit f0260589b439e2637ad54a2b25f00a516ef28a57 ]
+
+The transferred length is set incorrectly for cancelled bulk
+transfer TDs in case the bulk transfer ring stops on the last transfer
+block with a 'Stop - Length Invalid' completion code.
+
+length essentially ends up being set to the requested length:
+urb->actual_length = urb->transfer_buffer_length
+
+Length for 'Stop - Length Invalid' cases should be the sum of all
+TRB transfer block lengths up to the one the ring stopped on,
+_excluding_ the one stopped on.
+
+Fix this by always summing up TRB lengths for 'Stop - Length Invalid'
+bulk cases.
+
+This issue was discovered by Alan Stern while debugging
+https://bugzilla.kernel.org/show_bug.cgi?id=218890, but does not
+solve that bug. Issue is older than 4.10 kernel but fix won't apply
+to those due to major reworks in that area.
+
+Tested-by: Pierre Tomon <pierretom+12@ik.me>
+Cc: stable@vger.kernel.org # v4.10+
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20240611120610.3264502-2-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-ring.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 614fb89ddef61..26e57a9918995 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2288,9 +2288,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ goto finish_td;
+ case COMP_STOPPED_LENGTH_INVALID:
+ /* stopped on ep trb with invalid length, exclude it */
+- ep_trb_len = 0;
+- remaining = 0;
+- break;
++ td->urb->actual_length = sum_trb_lengths(xhci, ep_ring, ep_trb);
++ goto finish_td;
+ case COMP_USB_TRANSACTION_ERROR:
+ if ((ep_ring->err_count++ > MAX_SOFT_RETRY) ||
+ le32_to_cpu(slot_ctx->tt_info) & TT_SLOT)
+--
+2.43.0
+
--- /dev/null
+From 295e0a3fdaff1ed32450d4fcab20c59c550c4ec2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Sep 2018 19:13:37 +0300
+Subject: xhci: Use soft retry to recover faster from transaction errors
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit f8f80be501aa2f10669585c3e328fad079d8cb3a ]
+
+Use soft retry to recover from a USB Transaction Errors that are caused by
+temporary error conditions. The USB device is not aware that the xHC
+has halted the endpoint, and will be waiting for another retry
+
+A Soft Retry perform additional retries and recover from an error which has
+caused the xHC to halt an endpoint.
+
+Soft retry has some limitations:
+Soft Retry attempts shall not be performed on Isoch endpoints
+Soft Retry attempts shall not be performed if the device is behind a TT in
+a HS Hub
+
+Software shall limit the number of unsuccessful Soft Retry attempts to
+prevent an infinite loop.
+
+For more details on Soft retry see xhci specs 4.6.8.1
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: f0260589b439 ("xhci: Set correct transferred length for cancelled bulk transfers")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-ring.c | 19 +++++++++++++++++++
+ drivers/usb/host/xhci.h | 2 ++
+ 2 files changed, 21 insertions(+)
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 8723c7f1c24fe..614fb89ddef61 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1213,6 +1213,10 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
+ /* Clear our internal halted state */
+ ep->ep_state &= ~EP_HALTED;
+ }
++
++ /* if this was a soft reset, then restart */
++ if ((le32_to_cpu(trb->generic.field[3])) & TRB_TSP)
++ ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
+ }
+
+ static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id,
+@@ -2245,10 +2249,16 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ union xhci_trb *ep_trb, struct xhci_transfer_event *event,
+ struct xhci_virt_ep *ep, int *status)
+ {
++ struct xhci_slot_ctx *slot_ctx;
+ struct xhci_ring *ep_ring;
+ u32 trb_comp_code;
+ u32 remaining, requested, ep_trb_len;
++ unsigned int slot_id;
++ int ep_index;
+
++ slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
++ slot_ctx = xhci_get_slot_ctx(xhci, xhci->devs[slot_id]->out_ctx);
++ ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
+ ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
+ trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
+ remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+@@ -2257,6 +2267,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+
+ switch (trb_comp_code) {
+ case COMP_SUCCESS:
++ ep_ring->err_count = 0;
+ /* handle success with untransferred data as short packet */
+ if (ep_trb != td->last_trb || remaining) {
+ xhci_warn(xhci, "WARN Successful completion on short TX\n");
+@@ -2280,6 +2291,14 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ ep_trb_len = 0;
+ remaining = 0;
+ break;
++ case COMP_USB_TRANSACTION_ERROR:
++ if ((ep_ring->err_count++ > MAX_SOFT_RETRY) ||
++ le32_to_cpu(slot_ctx->tt_info) & TT_SLOT)
++ break;
++ *status = 0;
++ xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
++ ep_ring->stream_id, td, EP_SOFT_RESET);
++ return 0;
+ default:
+ /* do nothing */
+ break;
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index f2bf3431cd6f4..cd5eb506ddd18 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1517,6 +1517,7 @@ static inline const char *xhci_trb_type_string(u8 type)
+ /* How much data is left before the 64KB boundary? */
+ #define TRB_BUFF_LEN_UP_TO_BOUNDARY(addr) (TRB_MAX_BUFF_SIZE - \
+ (addr & (TRB_MAX_BUFF_SIZE - 1)))
++#define MAX_SOFT_RETRY 3
+
+ struct xhci_segment {
+ union xhci_trb *trbs;
+@@ -1604,6 +1605,7 @@ struct xhci_ring {
+ * if we own the TRB (if we are the consumer). See section 4.9.1.
+ */
+ u32 cycle_state;
++ unsigned int err_count;
+ unsigned int stream_id;
+ unsigned int num_segs;
+ unsigned int num_trbs_free;
+--
+2.43.0
+