From: Alexander Egorenkov <egorenar@linux.ibm.com>
To: oberpar@linux.ibm.com
Cc: gor@linux.ibm.com, hca@linux.ibm.com, agordeev@linux.ibm.com,
borntraeger@linux.ibm.com,
linux390-list@tuxmaker.boeblingen.de.ibm.com,
linux-s390@vger.kernel.org
Subject: [PATCH v5 4/4] s390/sclp: Ensure no callback gets called after sclp_unregister() returns
Date: Thu, 17 Sep 2026 08:58:24 +0200 [thread overview]
Message-ID: <20260917065824.2858737-5-egorenar@linux.ibm.com> (raw)
In-Reply-To: <20260917065824.2858737-1-egorenar@linux.ibm.com>
There is a potential race condition between sclp_unregister()
and sclp_dispatch_evbufs()/sclp_dispatch_state_change(). As a result,
it is not guaranteed that the callbacks registered with sclp_register()
will not get called one more time (and no more than one) after
sclp_unregister() returns.
The basic idea is to use a single global wait queue which is woken up
when no SCLP WRITE_EVENT_MASK and no SCLP READ_EVENT_DATA request is
outstanding. If both are true then it is guaranteed that no sclp_register
callback could be in-flight. Once the struct sclp_register given to
sclp_unregister() is removed from the list sclp_reg_list, no further
callbacks can be scheduled for the given struct sclp_register and it only
remains to wait until the SCLP driver becomes idle.
With this change sclp_unregister() may no longer be invoked from atomic
context or registered callbacks. But this represents no problem because
this is no regular use case and no driver using sclp_unregister() requires
this at the moment and likely should not require it in the future.
Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Suggested-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
---
drivers/s390/char/sclp.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 98e334724a62..c064234314bf 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -20,6 +20,7 @@
#include <linux/jiffies.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/wait.h>
#include <asm/types.h>
#include <asm/irq.h>
#include <asm/debug.h>
@@ -67,6 +68,8 @@ static struct sclp_req sclp_init_req;
static void *sclp_read_sccb;
static struct init_sccb *sclp_init_sccb;
+static DECLARE_WAIT_QUEUE_HEAD(sclp_state_wq);
+
/* Number of console pages to allocate, used by sclp_con.c and sclp_vt220.c */
int sclp_console_pages = SCLP_CONSOLE_PAGES;
/* Flag to indicate if buffer pages are dropped on buffer full condition */
@@ -588,6 +591,7 @@ sclp_read_cb(struct sclp_req *req, void *data)
sclp_dispatch_evbufs(sccb);
spin_lock_irqsave(&sclp_lock, flags);
sclp_reading_state = sclp_reading_state_idle;
+ wake_up_all(&sclp_state_wq);
spin_unlock_irqrestore(&sclp_lock, flags);
}
@@ -898,19 +902,26 @@ sclp_register(struct sclp_register *reg)
EXPORT_SYMBOL(sclp_register);
-/* Unregister event listener. */
-void
-sclp_unregister(struct sclp_register *reg)
+/* Unregister event listener.
+ * This function may sleep. Do not call it from atomic context or
+ * sclp_register.receive_fn(). */
+void sclp_unregister(struct sclp_register *reg)
{
- unsigned long flags;
+ might_sleep();
/* UREG: Event listener unregistered (b=caller) */
sclp_trace_register(2, "UREG", 0, _RET_IP_, reg);
- spin_lock_irqsave(&sclp_lock, flags);
+ spin_lock_irq(&sclp_lock);
list_del(®->list);
- spin_unlock_irqrestore(&sclp_lock, flags);
+ spin_unlock_irq(&sclp_lock);
sclp_init_mask(1);
+ spin_lock_irq(&sclp_lock);
+ wait_event_lock_irq(sclp_state_wq,
+ (sclp_mask_state == sclp_mask_state_idle) &&
+ (sclp_reading_state == sclp_reading_state_idle),
+ sclp_lock);
+ spin_unlock_irq(&sclp_lock);
}
EXPORT_SYMBOL(sclp_unregister);
@@ -1036,6 +1047,7 @@ sclp_init_mask(int calculate)
}
}
sclp_mask_state = sclp_mask_state_idle;
+ wake_up_all(&sclp_state_wq);
spin_unlock_irqrestore(&sclp_lock, flags);
return rc;
}
--
2.53.0
next prev parent reply other threads:[~2026-09-17 6:58 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-17 6:58 [PATCH v5 0/4] s390/sclp: Misc fixes Alexander Egorenkov
2026-09-17 6:58 ` [PATCH v5 1/4] s390/sclp: Introduce macro sclp_gds_for_each() Alexander Egorenkov
2026-09-17 7:08 ` sashiko-bot
2026-09-17 9:49 ` Alexander Egorenkov
2026-09-17 12:32 ` Peter Oberparleiter
2026-09-17 13:21 ` Alexander Egorenkov
2026-09-17 6:58 ` [PATCH v5 2/4] s390/sclp_tty: Make use of sclp_gds_for_each() Alexander Egorenkov
2026-09-17 7:12 ` sashiko-bot
2026-09-17 6:58 ` [PATCH v5 3/4] s390/sclp_ocf: Fix computation of length of GDS values Alexander Egorenkov
2026-09-17 7:09 ` sashiko-bot
2026-09-17 12:50 ` Peter Oberparleiter
2026-09-17 6:58 ` Alexander Egorenkov [this message]
2026-09-17 7:07 ` [PATCH v5 4/4] s390/sclp: Ensure no callback gets called after sclp_unregister() returns sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260917065824.2858737-5-egorenar@linux.ibm.com \
--to=egorenar@linux.ibm.com \
--cc=agordeev@linux.ibm.com \
--cc=borntraeger@linux.ibm.com \
--cc=gor@linux.ibm.com \
--cc=hca@linux.ibm.com \
--cc=linux-s390@vger.kernel.org \
--cc=linux390-list@tuxmaker.boeblingen.de.ibm.com \
--cc=oberpar@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.