]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 13 Aug 2023 20:46:05 +0000 (22:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 13 Aug 2023 20:46:05 +0000 (22:46 +0200)
added patches:
alpha-remove-__init-annotation-from-exported-page_is_ram.patch
sch_netem-fix-issues-in-netem_change-vs-get_dist_table.patch
scsi-53c700-check-that-command-slot-is-not-null.patch
scsi-core-fix-legacy-proc-parsing-buffer-overflow.patch
scsi-core-fix-possible-memory-leak-if-device_add-fails.patch
scsi-fnic-replace-return-codes-in-fnic_clean_pending_aborts.patch
scsi-qedf-fix-firmware-halt-over-suspend-and-resume.patch
scsi-qedi-fix-firmware-halt-over-suspend-and-resume.patch
scsi-snic-fix-possible-memory-leak-if-device_add-fails.patch
scsi-storvsc-fix-handling-of-virtual-fibre-channel-timeouts.patch
tick-detect-and-fix-jiffies-update-stall.patch
timers-nohz-last-resort-update-jiffies-on-nohz_full-irq-entry.patch
timers-nohz-switch-to-oneshot_stopped-in-the-low-res-handler-when-the-tick-is-stopped.patch

14 files changed:
queue-5.15/alpha-remove-__init-annotation-from-exported-page_is_ram.patch [new file with mode: 0644]
queue-5.15/sch_netem-fix-issues-in-netem_change-vs-get_dist_table.patch [new file with mode: 0644]
queue-5.15/scsi-53c700-check-that-command-slot-is-not-null.patch [new file with mode: 0644]
queue-5.15/scsi-core-fix-legacy-proc-parsing-buffer-overflow.patch [new file with mode: 0644]
queue-5.15/scsi-core-fix-possible-memory-leak-if-device_add-fails.patch [new file with mode: 0644]
queue-5.15/scsi-fnic-replace-return-codes-in-fnic_clean_pending_aborts.patch [new file with mode: 0644]
queue-5.15/scsi-qedf-fix-firmware-halt-over-suspend-and-resume.patch [new file with mode: 0644]
queue-5.15/scsi-qedi-fix-firmware-halt-over-suspend-and-resume.patch [new file with mode: 0644]
queue-5.15/scsi-snic-fix-possible-memory-leak-if-device_add-fails.patch [new file with mode: 0644]
queue-5.15/scsi-storvsc-fix-handling-of-virtual-fibre-channel-timeouts.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/tick-detect-and-fix-jiffies-update-stall.patch [new file with mode: 0644]
queue-5.15/timers-nohz-last-resort-update-jiffies-on-nohz_full-irq-entry.patch [new file with mode: 0644]
queue-5.15/timers-nohz-switch-to-oneshot_stopped-in-the-low-res-handler-when-the-tick-is-stopped.patch [new file with mode: 0644]

diff --git a/queue-5.15/alpha-remove-__init-annotation-from-exported-page_is_ram.patch b/queue-5.15/alpha-remove-__init-annotation-from-exported-page_is_ram.patch
new file mode 100644 (file)
index 0000000..73f9cf5
--- /dev/null
@@ -0,0 +1,40 @@
+From 6ccbd7fd474674654019a20177c943359469103a Mon Sep 17 00:00:00 2001
+From: Masahiro Yamada <masahiroy@kernel.org>
+Date: Sat, 29 Jul 2023 16:42:23 +0900
+Subject: alpha: remove __init annotation from exported page_is_ram()
+
+From: Masahiro Yamada <masahiroy@kernel.org>
+
+commit 6ccbd7fd474674654019a20177c943359469103a upstream.
+
+EXPORT_SYMBOL and __init is a bad combination because the .init.text
+section is freed up after the initialization.
+
+Commit c5a130325f13 ("ACPI/APEI: Add parameter check before error
+injection") exported page_is_ram(), hence the __init annotation should
+be removed.
+
+This fixes the modpost warning in ARCH=alpha builds:
+
+  WARNING: modpost: vmlinux: page_is_ram: EXPORT_SYMBOL used for init symbol. Remove __init or EXPORT_SYMBOL.
+
+Fixes: c5a130325f13 ("ACPI/APEI: Add parameter check before error injection")
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Reviewed-by: Randy Dunlap <rdunlap@infradead.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/alpha/kernel/setup.c |    3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/arch/alpha/kernel/setup.c
++++ b/arch/alpha/kernel/setup.c
+@@ -385,8 +385,7 @@ setup_memory(void *kernel_end)
+ #endif /* CONFIG_BLK_DEV_INITRD */
+ }
+-int __init
+-page_is_ram(unsigned long pfn)
++int page_is_ram(unsigned long pfn)
+ {
+       struct memclust_struct * cluster;
+       struct memdesc_struct * memdesc;
diff --git a/queue-5.15/sch_netem-fix-issues-in-netem_change-vs-get_dist_table.patch b/queue-5.15/sch_netem-fix-issues-in-netem_change-vs-get_dist_table.patch
new file mode 100644 (file)
index 0000000..e062fba
--- /dev/null
@@ -0,0 +1,148 @@
+From 11b73313c12403f617b47752db0ab3deef201af7 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Thu, 22 Jun 2023 18:15:03 +0000
+Subject: sch_netem: fix issues in netem_change() vs get_dist_table()
+
+From: Eric Dumazet <edumazet@google.com>
+
+commit 11b73313c12403f617b47752db0ab3deef201af7 upstream.
+
+In blamed commit, I missed that get_dist_table() was allocating
+memory using GFP_KERNEL, and acquiring qdisc lock to perform
+the swap of newly allocated table with current one.
+
+In this patch, get_dist_table() is allocating memory and
+copy user data before we acquire the qdisc lock.
+
+Then we perform swap operations while being protected by the lock.
+
+Note that after this patch netem_change() no longer can do partial changes.
+If an error is returned, qdisc conf is left unchanged.
+
+Fixes: 2174a08db80d ("sch_netem: acquire qdisc lock in netem_change()")
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Stephen Hemminger <stephen@networkplumber.org>
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Link: https://lore.kernel.org/r/20230622181503.2327695-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sched/sch_netem.c |   59 +++++++++++++++++++++-----------------------------
+ 1 file changed, 25 insertions(+), 34 deletions(-)
+
+--- a/net/sched/sch_netem.c
++++ b/net/sched/sch_netem.c
+@@ -773,12 +773,10 @@ static void dist_free(struct disttable *
+  * signed 16 bit values.
+  */
+-static int get_dist_table(struct Qdisc *sch, struct disttable **tbl,
+-                        const struct nlattr *attr)
++static int get_dist_table(struct disttable **tbl, const struct nlattr *attr)
+ {
+       size_t n = nla_len(attr)/sizeof(__s16);
+       const __s16 *data = nla_data(attr);
+-      spinlock_t *root_lock;
+       struct disttable *d;
+       int i;
+@@ -793,13 +791,7 @@ static int get_dist_table(struct Qdisc *
+       for (i = 0; i < n; i++)
+               d->table[i] = data[i];
+-      root_lock = qdisc_root_sleeping_lock(sch);
+-
+-      spin_lock_bh(root_lock);
+-      swap(*tbl, d);
+-      spin_unlock_bh(root_lock);
+-
+-      dist_free(d);
++      *tbl = d;
+       return 0;
+ }
+@@ -956,6 +948,8 @@ static int netem_change(struct Qdisc *sc
+ {
+       struct netem_sched_data *q = qdisc_priv(sch);
+       struct nlattr *tb[TCA_NETEM_MAX + 1];
++      struct disttable *delay_dist = NULL;
++      struct disttable *slot_dist = NULL;
+       struct tc_netem_qopt *qopt;
+       struct clgstate old_clg;
+       int old_loss_model = CLG_RANDOM;
+@@ -969,6 +963,18 @@ static int netem_change(struct Qdisc *sc
+       if (ret < 0)
+               return ret;
++      if (tb[TCA_NETEM_DELAY_DIST]) {
++              ret = get_dist_table(&delay_dist, tb[TCA_NETEM_DELAY_DIST]);
++              if (ret)
++                      goto table_free;
++      }
++
++      if (tb[TCA_NETEM_SLOT_DIST]) {
++              ret = get_dist_table(&slot_dist, tb[TCA_NETEM_SLOT_DIST]);
++              if (ret)
++                      goto table_free;
++      }
++
+       sch_tree_lock(sch);
+       /* backup q->clg and q->loss_model */
+       old_clg = q->clg;
+@@ -978,26 +984,17 @@ static int netem_change(struct Qdisc *sc
+               ret = get_loss_clg(q, tb[TCA_NETEM_LOSS]);
+               if (ret) {
+                       q->loss_model = old_loss_model;
++                      q->clg = old_clg;
+                       goto unlock;
+               }
+       } else {
+               q->loss_model = CLG_RANDOM;
+       }
+-      if (tb[TCA_NETEM_DELAY_DIST]) {
+-              ret = get_dist_table(sch, &q->delay_dist,
+-                                   tb[TCA_NETEM_DELAY_DIST]);
+-              if (ret)
+-                      goto get_table_failure;
+-      }
+-
+-      if (tb[TCA_NETEM_SLOT_DIST]) {
+-              ret = get_dist_table(sch, &q->slot_dist,
+-                                   tb[TCA_NETEM_SLOT_DIST]);
+-              if (ret)
+-                      goto get_table_failure;
+-      }
+-
++      if (delay_dist)
++              swap(q->delay_dist, delay_dist);
++      if (slot_dist)
++              swap(q->slot_dist, slot_dist);
+       sch->limit = qopt->limit;
+       q->latency = PSCHED_TICKS2NS(qopt->latency);
+@@ -1047,17 +1044,11 @@ static int netem_change(struct Qdisc *sc
+ unlock:
+       sch_tree_unlock(sch);
+-      return ret;
+-get_table_failure:
+-      /* recover clg and loss_model, in case of
+-       * q->clg and q->loss_model were modified
+-       * in get_loss_clg()
+-       */
+-      q->clg = old_clg;
+-      q->loss_model = old_loss_model;
+-
+-      goto unlock;
++table_free:
++      dist_free(delay_dist);
++      dist_free(slot_dist);
++      return ret;
+ }
+ static int netem_init(struct Qdisc *sch, struct nlattr *opt,
diff --git a/queue-5.15/scsi-53c700-check-that-command-slot-is-not-null.patch b/queue-5.15/scsi-53c700-check-that-command-slot-is-not-null.patch
new file mode 100644 (file)
index 0000000..439d76b
--- /dev/null
@@ -0,0 +1,36 @@
+From 8366d1f1249a0d0bba41d0bd1298d63e5d34c7f7 Mon Sep 17 00:00:00 2001
+From: Alexandra Diupina <adiupina@astralinux.ru>
+Date: Fri, 28 Jul 2023 15:35:21 +0300
+Subject: scsi: 53c700: Check that command slot is not NULL
+
+From: Alexandra Diupina <adiupina@astralinux.ru>
+
+commit 8366d1f1249a0d0bba41d0bd1298d63e5d34c7f7 upstream.
+
+Add a check for the command slot value to avoid dereferencing a NULL
+pointer.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Co-developed-by: Vladimir Telezhnikov <vtelezhnikov@astralinux.ru>
+Signed-off-by: Vladimir Telezhnikov <vtelezhnikov@astralinux.ru>
+Signed-off-by: Alexandra Diupina <adiupina@astralinux.ru>
+Link: https://lore.kernel.org/r/20230728123521.18293-1-adiupina@astralinux.ru
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/53c700.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/scsi/53c700.c
++++ b/drivers/scsi/53c700.c
+@@ -1599,7 +1599,7 @@ NCR_700_intr(int irq, void *dev_id)
+                               printk("scsi%d (%d:%d) PHASE MISMATCH IN SEND MESSAGE %d remain, return %p[%04x], phase %s\n", host->host_no, pun, lun, count, (void *)temp, temp - hostdata->pScript, sbcl_to_string(NCR_700_readb(host, SBCL_REG)));
+ #endif
+                               resume_offset = hostdata->pScript + Ent_SendMessagePhaseMismatch;
+-                      } else if(dsp >= to32bit(&slot->pSG[0].ins) &&
++                      } else if (slot && dsp >= to32bit(&slot->pSG[0].ins) &&
+                                 dsp <= to32bit(&slot->pSG[NCR_700_SG_SEGMENTS].ins)) {
+                               int data_transfer = NCR_700_readl(host, DBC_REG) & 0xffffff;
+                               int SGcount = (dsp - to32bit(&slot->pSG[0].ins))/sizeof(struct NCR_700_SG_List);
diff --git a/queue-5.15/scsi-core-fix-legacy-proc-parsing-buffer-overflow.patch b/queue-5.15/scsi-core-fix-legacy-proc-parsing-buffer-overflow.patch
new file mode 100644 (file)
index 0000000..e4ad8d3
--- /dev/null
@@ -0,0 +1,106 @@
+From 9426d3cef5000824e5f24f80ed5f42fb935f2488 Mon Sep 17 00:00:00 2001
+From: Tony Battersby <tonyb@cybernetics.com>
+Date: Mon, 24 Jul 2023 14:25:40 -0400
+Subject: scsi: core: Fix legacy /proc parsing buffer overflow
+
+From: Tony Battersby <tonyb@cybernetics.com>
+
+commit 9426d3cef5000824e5f24f80ed5f42fb935f2488 upstream.
+
+(lightly modified commit message mostly by Linus Torvalds)
+
+The parsing code for /proc/scsi/scsi is disgusting and broken.  We should
+have just used 'sscanf()' or something simple like that, but the logic may
+actually predate our kernel sscanf library routine for all I know.  It
+certainly predates both git and BK histories.
+
+And we can't change it to be something sane like that now, because the
+string matching at the start is done case-insensitively, and the separator
+parsing between numbers isn't done at all, so *any* separator will work,
+including a possible terminating NUL character.
+
+This interface is root-only, and entirely for legacy use, so there is
+absolutely no point in trying to tighten up the parsing.  Because any
+separator has traditionally worked, it's entirely possible that people have
+used random characters rather than the suggested space.
+
+So don't bother to try to pretty it up, and let's just make a minimal patch
+that can be back-ported and we can forget about this whole sorry thing for
+another two decades.
+
+Just make it at least not read past the end of the supplied data.
+
+Link: https://lore.kernel.org/linux-scsi/b570f5fe-cb7c-863a-6ed9-f6774c219b88@cybernetics.com/
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: Martin K Petersen <martin.petersen@oracle.com>
+Cc: James Bottomley <jejb@linux.ibm.com>
+Cc: Willy Tarreau <w@1wt.eu>
+Cc: stable@kernel.org
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
+Signed-off-by: Martin K Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/scsi_proc.c |   30 +++++++++++++++++-------------
+ 1 file changed, 17 insertions(+), 13 deletions(-)
+
+--- a/drivers/scsi/scsi_proc.c
++++ b/drivers/scsi/scsi_proc.c
+@@ -311,7 +311,7 @@ static ssize_t proc_scsi_write(struct fi
+                              size_t length, loff_t *ppos)
+ {
+       int host, channel, id, lun;
+-      char *buffer, *p;
++      char *buffer, *end, *p;
+       int err;
+       if (!buf || length > PAGE_SIZE)
+@@ -326,10 +326,14 @@ static ssize_t proc_scsi_write(struct fi
+               goto out;
+       err = -EINVAL;
+-      if (length < PAGE_SIZE)
+-              buffer[length] = '\0';
+-      else if (buffer[PAGE_SIZE-1])
+-              goto out;
++      if (length < PAGE_SIZE) {
++              end = buffer + length;
++              *end = '\0';
++      } else {
++              end = buffer + PAGE_SIZE - 1;
++              if (*end)
++                      goto out;
++      }
+       /*
+        * Usage: echo "scsi add-single-device 0 1 2 3" >/proc/scsi/scsi
+@@ -338,10 +342,10 @@ static ssize_t proc_scsi_write(struct fi
+       if (!strncmp("scsi add-single-device", buffer, 22)) {
+               p = buffer + 23;
+-              host = simple_strtoul(p, &p, 0);
+-              channel = simple_strtoul(p + 1, &p, 0);
+-              id = simple_strtoul(p + 1, &p, 0);
+-              lun = simple_strtoul(p + 1, &p, 0);
++              host    = (p     < end) ? simple_strtoul(p, &p, 0) : 0;
++              channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
++              id      = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
++              lun     = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
+               err = scsi_add_single_device(host, channel, id, lun);
+@@ -352,10 +356,10 @@ static ssize_t proc_scsi_write(struct fi
+       } else if (!strncmp("scsi remove-single-device", buffer, 25)) {
+               p = buffer + 26;
+-              host = simple_strtoul(p, &p, 0);
+-              channel = simple_strtoul(p + 1, &p, 0);
+-              id = simple_strtoul(p + 1, &p, 0);
+-              lun = simple_strtoul(p + 1, &p, 0);
++              host    = (p     < end) ? simple_strtoul(p, &p, 0) : 0;
++              channel = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
++              id      = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
++              lun     = (p + 1 < end) ? simple_strtoul(p + 1, &p, 0) : 0;
+               err = scsi_remove_single_device(host, channel, id, lun);
+       }
diff --git a/queue-5.15/scsi-core-fix-possible-memory-leak-if-device_add-fails.patch b/queue-5.15/scsi-core-fix-possible-memory-leak-if-device_add-fails.patch
new file mode 100644 (file)
index 0000000..eadcc32
--- /dev/null
@@ -0,0 +1,34 @@
+From 04b5b5cb0136ce970333a9c6cec7e46adba1ea3a Mon Sep 17 00:00:00 2001
+From: Zhu Wang <wangzhu9@huawei.com>
+Date: Thu, 3 Aug 2023 10:02:30 +0800
+Subject: scsi: core: Fix possible memory leak if device_add() fails
+
+From: Zhu Wang <wangzhu9@huawei.com>
+
+commit 04b5b5cb0136ce970333a9c6cec7e46adba1ea3a upstream.
+
+If device_add() returns error, the name allocated by dev_set_name() needs
+be freed. As the comment of device_add() says, put_device() should be used
+to decrease the reference count in the error path. So fix this by calling
+put_device(), then the name can be freed in kobject_cleanp().
+
+Fixes: ee959b00c335 ("SCSI: convert struct class_device to struct device")
+Signed-off-by: Zhu Wang <wangzhu9@huawei.com>
+Link: https://lore.kernel.org/r/20230803020230.226903-1-wangzhu9@huawei.com
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/raid_class.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/scsi/raid_class.c
++++ b/drivers/scsi/raid_class.c
+@@ -248,6 +248,7 @@ int raid_component_add(struct raid_templ
+       return 0;
+ err_out:
++      put_device(&rc->dev);
+       list_del(&rc->node);
+       rd->component_count--;
+       put_device(component_dev);
diff --git a/queue-5.15/scsi-fnic-replace-return-codes-in-fnic_clean_pending_aborts.patch b/queue-5.15/scsi-fnic-replace-return-codes-in-fnic_clean_pending_aborts.patch
new file mode 100644 (file)
index 0000000..33a3d16
--- /dev/null
@@ -0,0 +1,48 @@
+From 5a43b07a87835660f91d88a4db11abfea8c523b7 Mon Sep 17 00:00:00 2001
+From: Karan Tilak Kumar <kartilak@cisco.com>
+Date: Thu, 27 Jul 2023 12:39:19 -0700
+Subject: scsi: fnic: Replace return codes in fnic_clean_pending_aborts()
+
+From: Karan Tilak Kumar <kartilak@cisco.com>
+
+commit 5a43b07a87835660f91d88a4db11abfea8c523b7 upstream.
+
+fnic_clean_pending_aborts() was returning a non-zero value irrespective of
+failure or success.  This caused the caller of this function to assume that
+the device reset had failed, even though it would succeed in most cases. As
+a consequence, a successful device reset would escalate to host reset.
+
+Reviewed-by: Sesidhar Baddela <sebaddel@cisco.com>
+Tested-by: Karan Tilak Kumar <kartilak@cisco.com>
+Signed-off-by: Karan Tilak Kumar <kartilak@cisco.com>
+Link: https://lore.kernel.org/r/20230727193919.2519-1-kartilak@cisco.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/fnic/fnic_scsi.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/scsi/fnic/fnic_scsi.c
++++ b/drivers/scsi/fnic/fnic_scsi.c
+@@ -2172,7 +2172,7 @@ static int fnic_clean_pending_aborts(str
+                                    bool new_sc)
+ {
+-      int ret = SUCCESS;
++      int ret = 0;
+       struct fnic_pending_aborts_iter_data iter_data = {
+               .fnic = fnic,
+               .lun_dev = lr_sc->device,
+@@ -2192,9 +2192,11 @@ static int fnic_clean_pending_aborts(str
+       /* walk again to check, if IOs are still pending in fw */
+       if (fnic_is_abts_pending(fnic, lr_sc))
+-              ret = FAILED;
++              ret = 1;
+ clean_pending_aborts_end:
++      FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
++                      "%s: exit status: %d\n", __func__, ret);
+       return ret;
+ }
diff --git a/queue-5.15/scsi-qedf-fix-firmware-halt-over-suspend-and-resume.patch b/queue-5.15/scsi-qedf-fix-firmware-halt-over-suspend-and-resume.patch
new file mode 100644 (file)
index 0000000..cf20c98
--- /dev/null
@@ -0,0 +1,71 @@
+From ef222f551e7c4e2008fc442ffc9edcd1a7fd8f63 Mon Sep 17 00:00:00 2001
+From: Nilesh Javali <njavali@marvell.com>
+Date: Mon, 7 Aug 2023 15:07:24 +0530
+Subject: scsi: qedf: Fix firmware halt over suspend and resume
+
+From: Nilesh Javali <njavali@marvell.com>
+
+commit ef222f551e7c4e2008fc442ffc9edcd1a7fd8f63 upstream.
+
+While performing certain power-off sequences, PCI drivers are called to
+suspend and resume their underlying devices through PCI PM (power
+management) interface. However the hardware does not support PCI PM
+suspend/resume operations so system wide suspend/resume leads to bad MFW
+(management firmware) state which causes various follow-up errors in driver
+when communicating with the device/firmware.
+
+To fix this driver implements PCI PM suspend handler to indicate
+unsupported operation to the PCI subsystem explicitly, thus avoiding system
+to go into suspended/standby mode.
+
+Fixes: 61d8658b4a43 ("scsi: qedf: Add QLogic FastLinQ offload FCoE driver framework.")
+Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20230807093725.46829-1-njavali@marvell.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/qedf/qedf_main.c |   18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/drivers/scsi/qedf/qedf_main.c
++++ b/drivers/scsi/qedf/qedf_main.c
+@@ -31,6 +31,7 @@ static void qedf_remove(struct pci_dev *
+ static void qedf_shutdown(struct pci_dev *pdev);
+ static void qedf_schedule_recovery_handler(void *dev);
+ static void qedf_recovery_handler(struct work_struct *work);
++static int qedf_suspend(struct pci_dev *pdev, pm_message_t state);
+ /*
+  * Driver module parameters.
+@@ -3276,6 +3277,7 @@ static struct pci_driver qedf_pci_driver
+       .probe = qedf_probe,
+       .remove = qedf_remove,
+       .shutdown = qedf_shutdown,
++      .suspend = qedf_suspend,
+ };
+ static int __qedf_probe(struct pci_dev *pdev, int mode)
+@@ -4005,6 +4007,22 @@ static void qedf_shutdown(struct pci_dev
+       __qedf_remove(pdev, QEDF_MODE_NORMAL);
+ }
++static int qedf_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++      struct qedf_ctx *qedf;
++
++      if (!pdev) {
++              QEDF_ERR(NULL, "pdev is NULL.\n");
++              return -ENODEV;
++      }
++
++      qedf = pci_get_drvdata(pdev);
++
++      QEDF_ERR(&qedf->dbg_ctx, "%s: Device does not support suspend operation\n", __func__);
++
++      return -EPERM;
++}
++
+ /*
+  * Recovery handler code
+  */
diff --git a/queue-5.15/scsi-qedi-fix-firmware-halt-over-suspend-and-resume.patch b/queue-5.15/scsi-qedi-fix-firmware-halt-over-suspend-and-resume.patch
new file mode 100644 (file)
index 0000000..2cad62c
--- /dev/null
@@ -0,0 +1,70 @@
+From 1516ee035df32115197cd93ae3619dba7b020986 Mon Sep 17 00:00:00 2001
+From: Nilesh Javali <njavali@marvell.com>
+Date: Mon, 7 Aug 2023 15:07:25 +0530
+Subject: scsi: qedi: Fix firmware halt over suspend and resume
+
+From: Nilesh Javali <njavali@marvell.com>
+
+commit 1516ee035df32115197cd93ae3619dba7b020986 upstream.
+
+While performing certain power-off sequences, PCI drivers are called to
+suspend and resume their underlying devices through PCI PM (power
+management) interface. However the hardware does not support PCI PM
+suspend/resume operations so system wide suspend/resume leads to bad MFW
+(management firmware) state which causes various follow-up errors in driver
+when communicating with the device/firmware.
+
+To fix this driver implements PCI PM suspend handler to indicate
+unsupported operation to the PCI subsystem explicitly, thus avoiding system
+to go into suspended/standby mode.
+
+Fixes: ace7f46ba5fd ("scsi: qedi: Add QLogic FastLinQ offload iSCSI driver framework.")
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Link: https://lore.kernel.org/r/20230807093725.46829-2-njavali@marvell.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/qedi/qedi_main.c |   18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/drivers/scsi/qedi/qedi_main.c
++++ b/drivers/scsi/qedi/qedi_main.c
+@@ -69,6 +69,7 @@ static struct nvm_iscsi_block *qedi_get_
+ static void qedi_recovery_handler(struct work_struct *work);
+ static void qedi_schedule_hw_err_handler(void *dev,
+                                        enum qed_hw_err_type err_type);
++static int qedi_suspend(struct pci_dev *pdev, pm_message_t state);
+ static int qedi_iscsi_event_cb(void *context, u8 fw_event_code, void *fw_handle)
+ {
+@@ -2515,6 +2516,22 @@ static void qedi_shutdown(struct pci_dev
+       __qedi_remove(pdev, QEDI_MODE_SHUTDOWN);
+ }
++static int qedi_suspend(struct pci_dev *pdev, pm_message_t state)
++{
++      struct qedi_ctx *qedi;
++
++      if (!pdev) {
++              QEDI_ERR(NULL, "pdev is NULL.\n");
++              return -ENODEV;
++      }
++
++      qedi = pci_get_drvdata(pdev);
++
++      QEDI_ERR(&qedi->dbg_ctx, "%s: Device does not support suspend operation\n", __func__);
++
++      return -EPERM;
++}
++
+ static int __qedi_probe(struct pci_dev *pdev, int mode)
+ {
+       struct qedi_ctx *qedi;
+@@ -2873,6 +2890,7 @@ static struct pci_driver qedi_pci_driver
+       .remove = qedi_remove,
+       .shutdown = qedi_shutdown,
+       .err_handler = &qedi_err_handler,
++      .suspend = qedi_suspend,
+ };
+ static int __init qedi_init(void)
diff --git a/queue-5.15/scsi-snic-fix-possible-memory-leak-if-device_add-fails.patch b/queue-5.15/scsi-snic-fix-possible-memory-leak-if-device_add-fails.patch
new file mode 100644 (file)
index 0000000..514c88e
--- /dev/null
@@ -0,0 +1,34 @@
+From 41320b18a0e0dfb236dba4edb9be12dba1878156 Mon Sep 17 00:00:00 2001
+From: Zhu Wang <wangzhu9@huawei.com>
+Date: Tue, 1 Aug 2023 19:14:21 +0800
+Subject: scsi: snic: Fix possible memory leak if device_add() fails
+
+From: Zhu Wang <wangzhu9@huawei.com>
+
+commit 41320b18a0e0dfb236dba4edb9be12dba1878156 upstream.
+
+If device_add() returns error, the name allocated by dev_set_name() needs
+be freed. As the comment of device_add() says, put_device() should be used
+to give up the reference in the error path. So fix this by calling
+put_device(), then the name can be freed in kobject_cleanp().
+
+Fixes: c8806b6c9e82 ("snic: driver for Cisco SCSI HBA")
+Signed-off-by: Zhu Wang <wangzhu9@huawei.com>
+Acked-by: Narsimhulu Musini <nmusini@cisco.com>
+Link: https://lore.kernel.org/r/20230801111421.63651-1-wangzhu9@huawei.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/snic/snic_disc.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/scsi/snic/snic_disc.c
++++ b/drivers/scsi/snic/snic_disc.c
+@@ -317,6 +317,7 @@ snic_tgt_create(struct snic *snic, struc
+                             "Snic Tgt: device_add, with err = %d\n",
+                             ret);
++              put_device(&tgt->dev);
+               put_device(&snic->shost->shost_gendev);
+               spin_lock_irqsave(snic->shost->host_lock, flags);
+               list_del(&tgt->list);
diff --git a/queue-5.15/scsi-storvsc-fix-handling-of-virtual-fibre-channel-timeouts.patch b/queue-5.15/scsi-storvsc-fix-handling-of-virtual-fibre-channel-timeouts.patch
new file mode 100644 (file)
index 0000000..592b847
--- /dev/null
@@ -0,0 +1,62 @@
+From 175544ad48cbf56affeef2a679c6a4d4fb1e2881 Mon Sep 17 00:00:00 2001
+From: Michael Kelley <mikelley@microsoft.com>
+Date: Fri, 28 Jul 2023 21:59:24 -0700
+Subject: scsi: storvsc: Fix handling of virtual Fibre Channel timeouts
+
+From: Michael Kelley <mikelley@microsoft.com>
+
+commit 175544ad48cbf56affeef2a679c6a4d4fb1e2881 upstream.
+
+Hyper-V provides the ability to connect Fibre Channel LUNs to the host
+system and present them in a guest VM as a SCSI device. I/O to the vFC
+device is handled by the storvsc driver. The storvsc driver includes a
+partial integration with the FC transport implemented in the generic
+portion of the Linux SCSI subsystem so that FC attributes can be displayed
+in /sys.  However, the partial integration means that some aspects of vFC
+don't work properly. Unfortunately, a full and correct integration isn't
+practical because of limitations in what Hyper-V provides to the guest.
+
+In particular, in the context of Hyper-V storvsc, the FC transport timeout
+function fc_eh_timed_out() causes a kernel panic because it can't find the
+rport and dereferences a NULL pointer. The original patch that added the
+call from storvsc_eh_timed_out() to fc_eh_timed_out() is faulty in this
+regard.
+
+In many cases a timeout is due to a transient condition, so the situation
+can be improved by just continuing to wait like with other I/O requests
+issued by storvsc, and avoiding the guaranteed panic. For a permanent
+failure, continuing to wait may result in a hung thread instead of a panic,
+which again may be better.
+
+So fix the panic by removing the storvsc call to fc_eh_timed_out().  This
+allows storvsc to keep waiting for a response.  The change has been tested
+by users who experienced a panic in fc_eh_timed_out() due to transient
+timeouts, and it solves their problem.
+
+In the future we may want to deprecate the vFC functionality in storvsc
+since it can't be fully fixed. But it has current users for whom it is
+working well enough, so it should probably stay for a while longer.
+
+Fixes: 3930d7309807 ("scsi: storvsc: use default I/O timeout handler for FC devices")
+Cc: stable@vger.kernel.org
+Signed-off-by: Michael Kelley <mikelley@microsoft.com>
+Link: https://lore.kernel.org/r/1690606764-79669-1-git-send-email-mikelley@microsoft.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/storvsc_drv.c |    4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/drivers/scsi/storvsc_drv.c
++++ b/drivers/scsi/storvsc_drv.c
+@@ -1730,10 +1730,6 @@ static int storvsc_host_reset_handler(st
+  */
+ static enum blk_eh_timer_return storvsc_eh_timed_out(struct scsi_cmnd *scmnd)
+ {
+-#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
+-      if (scmnd->device->host->transportt == fc_transport_template)
+-              return fc_eh_timed_out(scmnd);
+-#endif
+       return BLK_EH_RESET_TIMER;
+ }
index f38a56a2333f0e28211f468800054935a185f875..ddd117653254da96c9c17694b52788d29b405c58 100644 (file)
@@ -74,3 +74,16 @@ btrfs-set-cache_block_group_error-if-we-find-an-error.patch
 nvme-tcp-fix-potential-unbalanced-freeze-unfreeze.patch
 nvme-rdma-fix-potential-unbalanced-freeze-unfreeze.patch
 netfilter-nf_tables-report-use-refcount-overflow.patch
+scsi-core-fix-legacy-proc-parsing-buffer-overflow.patch
+scsi-storvsc-fix-handling-of-virtual-fibre-channel-timeouts.patch
+scsi-53c700-check-that-command-slot-is-not-null.patch
+scsi-snic-fix-possible-memory-leak-if-device_add-fails.patch
+scsi-core-fix-possible-memory-leak-if-device_add-fails.patch
+scsi-fnic-replace-return-codes-in-fnic_clean_pending_aborts.patch
+scsi-qedi-fix-firmware-halt-over-suspend-and-resume.patch
+scsi-qedf-fix-firmware-halt-over-suspend-and-resume.patch
+alpha-remove-__init-annotation-from-exported-page_is_ram.patch
+sch_netem-fix-issues-in-netem_change-vs-get_dist_table.patch
+tick-detect-and-fix-jiffies-update-stall.patch
+timers-nohz-switch-to-oneshot_stopped-in-the-low-res-handler-when-the-tick-is-stopped.patch
+timers-nohz-last-resort-update-jiffies-on-nohz_full-irq-entry.patch
diff --git a/queue-5.15/tick-detect-and-fix-jiffies-update-stall.patch b/queue-5.15/tick-detect-and-fix-jiffies-update-stall.patch
new file mode 100644 (file)
index 0000000..c4f9168
--- /dev/null
@@ -0,0 +1,90 @@
+From stable-owner@vger.kernel.org Sun Aug 13 05:16:30 2023
+From: "Joel Fernandes (Google)" <joel@joelfernandes.org>
+Date: Sun, 13 Aug 2023 03:16:18 +0000
+Subject: tick: Detect and fix jiffies update stall
+To: stable@vger.kernel.org
+Cc: Guenter Roeck <linux@roeck-us.net>, Steven Rostedt <rostedt@goodmis.org>, Frederic Weisbecker <frederic@kernel.org>, "Paul E . McKenney" <paulmck@kernel.org>, Thomas Gleixner <tglx@linutronix.de>, Joel Fernandes <joel@joelfernandes.org>
+Message-ID: <20230813031620.2218302-1-joel@joelfernandes.org>
+
+From: Frederic Weisbecker <frederic@kernel.org>
+
+[ Upstream commit a1ff03cd6fb9c501fff63a4a2bface9adcfa81cd ]
+
+tick: Detect and fix jiffies update stall
+
+On some rare cases, the timekeeper CPU may be delaying its jiffies
+update duty for a while. Known causes include:
+
+* The timekeeper is waiting on stop_machine in a MULTI_STOP_DISABLE_IRQ
+  or MULTI_STOP_RUN state. Disabled interrupts prevent from timekeeping
+  updates while waiting for the target CPU to complete its
+  stop_machine() callback.
+
+* The timekeeper vcpu has VMEXIT'ed for a long while due to some overload
+  on the host.
+
+Detect and fix these situations with emergency timekeeping catchups.
+
+Original-patch-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/time/tick-sched.c |   17 +++++++++++++++++
+ kernel/time/tick-sched.h |    4 ++++
+ 2 files changed, 21 insertions(+)
+
+--- a/kernel/time/tick-sched.c
++++ b/kernel/time/tick-sched.c
+@@ -180,6 +180,8 @@ static ktime_t tick_init_jiffy_update(vo
+       return period;
+ }
++#define MAX_STALLED_JIFFIES 5
++
+ static void tick_sched_do_timer(struct tick_sched *ts, ktime_t now)
+ {
+       int cpu = smp_processor_id();
+@@ -207,6 +209,21 @@ static void tick_sched_do_timer(struct t
+       if (tick_do_timer_cpu == cpu)
+               tick_do_update_jiffies64(now);
++      /*
++       * If jiffies update stalled for too long (timekeeper in stop_machine()
++       * or VMEXIT'ed for several msecs), force an update.
++       */
++      if (ts->last_tick_jiffies != jiffies) {
++              ts->stalled_jiffies = 0;
++              ts->last_tick_jiffies = READ_ONCE(jiffies);
++      } else {
++              if (++ts->stalled_jiffies == MAX_STALLED_JIFFIES) {
++                      tick_do_update_jiffies64(now);
++                      ts->stalled_jiffies = 0;
++                      ts->last_tick_jiffies = READ_ONCE(jiffies);
++              }
++      }
++
+       if (ts->inidle)
+               ts->got_idle_tick = 1;
+ }
+--- a/kernel/time/tick-sched.h
++++ b/kernel/time/tick-sched.h
+@@ -49,6 +49,8 @@ enum tick_nohz_mode {
+  * @timer_expires_base:       Base time clock monotonic for @timer_expires
+  * @next_timer:               Expiry time of next expiring timer for debugging purpose only
+  * @tick_dep_mask:    Tick dependency mask - is set, if someone needs the tick
++ * @last_tick_jiffies:        Value of jiffies seen on last tick
++ * @stalled_jiffies:  Number of stalled jiffies detected across ticks
+  */
+ struct tick_sched {
+       struct hrtimer                  sched_timer;
+@@ -77,6 +79,8 @@ struct tick_sched {
+       u64                             next_timer;
+       ktime_t                         idle_expires;
+       atomic_t                        tick_dep_mask;
++      unsigned long                   last_tick_jiffies;
++      unsigned int                    stalled_jiffies;
+ };
+ extern struct tick_sched *tick_get_tick_sched(int cpu);
diff --git a/queue-5.15/timers-nohz-last-resort-update-jiffies-on-nohz_full-irq-entry.patch b/queue-5.15/timers-nohz-last-resort-update-jiffies-on-nohz_full-irq-entry.patch
new file mode 100644 (file)
index 0000000..f5adaf3
--- /dev/null
@@ -0,0 +1,92 @@
+From stable-owner@vger.kernel.org Sun Aug 13 05:16:33 2023
+From: "Joel Fernandes (Google)" <joel@joelfernandes.org>
+Date: Sun, 13 Aug 2023 03:16:20 +0000
+Subject: timers/nohz: Last resort update jiffies on nohz_full IRQ entry
+To: stable@vger.kernel.org
+Cc: Guenter Roeck <linux@roeck-us.net>, Steven Rostedt <rostedt@goodmis.org>, Frederic Weisbecker <frederic@kernel.org>, "Paul E . McKenney" <paulmck@kernel.org>, Thomas Gleixner <tglx@linutronix.de>, Joel Fernandes <joel@joelfernandes.org>
+Message-ID: <20230813031620.2218302-3-joel@joelfernandes.org>
+
+From: Frederic Weisbecker <frederic@kernel.org>
+
+[ Upstream commit 53e87e3cdc155f20c3417b689df8d2ac88d79576 ]
+
+When at least one CPU runs in nohz_full mode, a dedicated timekeeper CPU
+is guaranteed to stay online and to never stop its tick.
+
+Meanwhile on some rare case, the dedicated timekeeper may be running
+with interrupts disabled for a while, such as in stop_machine.
+
+If jiffies stop being updated, a nohz_full CPU may end up endlessly
+programming the next tick in the past, taking the last jiffies update
+monotonic timestamp as a stale base, resulting in an tick storm.
+
+Here is a scenario where it matters:
+
+0) CPU 0 is the timekeeper and CPU 1 a nohz_full CPU.
+
+1) A stop machine callback is queued to execute somewhere.
+
+2) CPU 0 reaches MULTI_STOP_DISABLE_IRQ while CPU 1 is still in
+   MULTI_STOP_PREPARE. Hence CPU 0 can't do its timekeeping duty. CPU 1
+   can still take IRQs.
+
+3) CPU 1 receives an IRQ which queues a timer callback one jiffy forward.
+
+4) On IRQ exit, CPU 1 schedules the tick one jiffy forward, taking
+   last_jiffies_update as a base. But last_jiffies_update hasn't been
+   updated for 2 jiffies since the timekeeper has interrupts disabled.
+
+5) clockevents_program_event(), which relies on ktime_get(), observes
+   that the expiration is in the past and therefore programs the min
+   delta event on the clock.
+
+6) The tick fires immediately, goto 3)
+
+7) Tick storm, the nohz_full CPU is drown and takes ages to reach
+   MULTI_STOP_DISABLE_IRQ, which is the only way out of this situation.
+
+Solve this with unconditionally updating jiffies if the value is stale
+on nohz_full IRQ entry. IRQs and other disturbances are expected to be
+rare enough on nohz_full for the unconditional call to ktime_get() to
+actually matter.
+
+Reported-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Tested-by: Paul E. McKenney <paulmck@kernel.org>
+Link: https://lore.kernel.org/r/20211026141055.57358-2-frederic@kernel.org
+Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/softirq.c         |    3 ++-
+ kernel/time/tick-sched.c |    7 +++++++
+ 2 files changed, 9 insertions(+), 1 deletion(-)
+
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -595,7 +595,8 @@ void irq_enter_rcu(void)
+ {
+       __irq_enter_raw();
+-      if (is_idle_task(current) && (irq_count() == HARDIRQ_OFFSET))
++      if (tick_nohz_full_cpu(smp_processor_id()) ||
++          (is_idle_task(current) && (irq_count() == HARDIRQ_OFFSET)))
+               tick_irq_enter();
+       account_hardirq_enter(current);
+--- a/kernel/time/tick-sched.c
++++ b/kernel/time/tick-sched.c
+@@ -1420,6 +1420,13 @@ static inline void tick_nohz_irq_enter(v
+       now = ktime_get();
+       if (ts->idle_active)
+               tick_nohz_stop_idle(ts, now);
++      /*
++       * If all CPUs are idle. We may need to update a stale jiffies value.
++       * Note nohz_full is a special case: a timekeeper is guaranteed to stay
++       * alive but it might be busy looping with interrupts disabled in some
++       * rare case (typically stop machine). So we must make sure we have a
++       * last resort.
++       */
+       if (ts->tick_stopped)
+               tick_nohz_update_jiffies(now);
+ }
diff --git a/queue-5.15/timers-nohz-switch-to-oneshot_stopped-in-the-low-res-handler-when-the-tick-is-stopped.patch b/queue-5.15/timers-nohz-switch-to-oneshot_stopped-in-the-low-res-handler-when-the-tick-is-stopped.patch
new file mode 100644 (file)
index 0000000..654ec41
--- /dev/null
@@ -0,0 +1,61 @@
+From stable-owner@vger.kernel.org Sun Aug 13 05:16:31 2023
+From: "Joel Fernandes (Google)" <joel@joelfernandes.org>
+Date: Sun, 13 Aug 2023 03:16:19 +0000
+Subject: timers/nohz: Switch to ONESHOT_STOPPED in the low-res handler when the tick is stopped
+To: stable@vger.kernel.org
+Cc: Guenter Roeck <linux@roeck-us.net>, Steven Rostedt <rostedt@goodmis.org>, Nicholas Piggin <npiggin@gmail.com>, Thomas Gleixner <tglx@linutronix.de>, Joel Fernandes <joel@joelfernandes.org>
+Message-ID: <20230813031620.2218302-2-joel@joelfernandes.org>
+
+From: Nicholas Piggin <npiggin@gmail.com>
+
+[ Upstream commit 62c1256d544747b38e77ca9b5bfe3a26f9592576 ]
+
+When tick_nohz_stop_tick() stops the tick and high resolution timers are
+disabled, then the clock event device is not put into ONESHOT_STOPPED
+mode. This can lead to spurious timer interrupts with some clock event
+device drivers that don't shut down entirely after firing.
+
+Eliminate these by putting the device into ONESHOT_STOPPED mode at points
+where it is not being reprogrammed. When there are no timers active, then
+tick_program_event() with KTIME_MAX can be used to stop the device. When
+there is a timer active, the device can be stopped at the next tick (any
+new timer added by timers will reprogram the tick).
+
+Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/20220422141446.915024-1-npiggin@gmail.com
+Signed-off-by: Joel Fernandes (Google) <joel@joelfernandes.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/time/tick-sched.c |   12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+--- a/kernel/time/tick-sched.c
++++ b/kernel/time/tick-sched.c
+@@ -950,6 +950,8 @@ static void tick_nohz_stop_tick(struct t
+       if (unlikely(expires == KTIME_MAX)) {
+               if (ts->nohz_mode == NOHZ_MODE_HIGHRES)
+                       hrtimer_cancel(&ts->sched_timer);
++              else
++                      tick_program_event(KTIME_MAX, 1);
+               return;
+       }
+@@ -1356,9 +1358,15 @@ static void tick_nohz_handler(struct clo
+       tick_sched_do_timer(ts, now);
+       tick_sched_handle(ts, regs);
+-      /* No need to reprogram if we are running tickless  */
+-      if (unlikely(ts->tick_stopped))
++      if (unlikely(ts->tick_stopped)) {
++              /*
++               * The clockevent device is not reprogrammed, so change the
++               * clock event device to ONESHOT_STOPPED to avoid spurious
++               * interrupts on devices which might not be truly one shot.
++               */
++              tick_program_event(KTIME_MAX, 1);
+               return;
++      }
+       hrtimer_forward(&ts->sched_timer, now, TICK_NSEC);
+       tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);