From: Eric Farman <farman@linux.ibm.com>
To: linux-s390@vger.kernel.org, kvm@vger.kernel.org,
linux-kernel@vger.kernel.org
Cc: Matthew Rosato <mjrosato@linux.ibm.com>,
Halil Pasic <pasic@linux.ibm.com>,
Christian Borntraeger <borntraeger@linux.ibm.com>,
Eric Farman <farman@linux.ibm.com>,
stable@vger.kernel.org, Farhan Ali <alifm@linux.ibm.com>
Subject: [PATCH v5 10/10] s390/vfio_ccw: implement a crw lock
Date: Sun, 26 Jul 2026 06:01:29 +0200 [thread overview]
Message-ID: <20260726040129.2946151-11-farman@linux.ibm.com> (raw)
In-Reply-To: <20260726040129.2946151-1-farman@linux.ibm.com>
Unlike the channel_program struct, which covers synchronous I/O
submissions and asynchronous interrupts, the CRW region relies
exclusively on asynchronous events coming from hardware.
Implement a lock to manage the list of those payloads, to ensure
they are read cohesively.
Fixes: 3f02cb2fd9d2 ("vfio-ccw: Wire up the CRW irq and CRW region")
Cc: stable@vger.kernel.org
Cc: Farhan Ali <alifm@linux.ibm.com>
Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: Eric Farman <farman@linux.ibm.com>
---
drivers/s390/cio/vfio_ccw_chp.c | 26 ++++++++++++++++----------
drivers/s390/cio/vfio_ccw_drv.c | 6 ++++++
drivers/s390/cio/vfio_ccw_ops.c | 4 ++++
drivers/s390/cio/vfio_ccw_private.h | 4 ++++
4 files changed, 30 insertions(+), 10 deletions(-)
diff --git a/drivers/s390/cio/vfio_ccw_chp.c b/drivers/s390/cio/vfio_ccw_chp.c
index f3015132d4b5..7708eb4d6de0 100644
--- a/drivers/s390/cio/vfio_ccw_chp.c
+++ b/drivers/s390/cio/vfio_ccw_chp.c
@@ -93,17 +93,12 @@ static ssize_t vfio_ccw_crw_region_read(struct vfio_ccw_private *private,
loff_t pos = *ppos & VFIO_CCW_OFFSET_MASK;
struct ccw_crw_region *region;
struct vfio_ccw_crw *crw;
+ unsigned long flags;
int ret;
if (pos + count > sizeof(*region))
return -EINVAL;
- crw = list_first_entry_or_null(&private->crw,
- struct vfio_ccw_crw, next);
-
- if (crw)
- list_del(&crw->next);
-
mutex_lock(&private->io_mutex);
if (i >= private->num_regions) {
ret = -EINVAL;
@@ -113,6 +108,16 @@ static ssize_t vfio_ccw_crw_region_read(struct vfio_ccw_private *private,
i = array_index_nospec(i, private->num_regions);
region = private->region[i].data;
+ spin_lock_irqsave(&private->crw_lock, flags);
+ crw = list_first_entry_or_null(&private->crw,
+ struct vfio_ccw_crw, next);
+
+ if (crw)
+ list_del(&crw->next);
+
+ /* Drop CRW lock while copying to userspace */
+ spin_unlock_irqrestore(&private->crw_lock, flags);
+
if (crw)
memcpy(®ion->crw, &crw->crw, sizeof(region->crw));
@@ -122,15 +127,16 @@ static ssize_t vfio_ccw_crw_region_read(struct vfio_ccw_private *private,
ret = count;
region->crw = 0;
-
-out:
- mutex_unlock(&private->io_mutex);
-
kfree(crw);
/* Notify the guest if more CRWs are on our queue */
+ spin_lock_irqsave(&private->crw_lock, flags);
if (!list_empty(&private->crw) && private->crw_trigger)
eventfd_signal(private->crw_trigger);
+ spin_unlock_irqrestore(&private->crw_lock, flags);
+
+out:
+ mutex_unlock(&private->io_mutex);
return ret;
}
diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index 4830f0dd9c3a..437d7709b4a5 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -122,11 +122,14 @@ void vfio_ccw_sch_io_todo(struct work_struct *work)
void vfio_ccw_crw_todo(struct work_struct *work)
{
struct vfio_ccw_private *private;
+ unsigned long flags;
private = container_of(work, struct vfio_ccw_private, crw_work);
+ spin_lock_irqsave(&private->crw_lock, flags);
if (!list_empty(&private->crw) && private->crw_trigger)
eventfd_signal(private->crw_trigger);
+ spin_unlock_irqrestore(&private->crw_lock, flags);
}
void vfio_ccw_notoper_todo(struct work_struct *work)
@@ -290,6 +293,7 @@ static void vfio_ccw_queue_crw(struct vfio_ccw_private *private,
unsigned int rsid)
{
struct vfio_ccw_crw *crw;
+ unsigned long flags;
/*
* If unable to allocate a CRW, just drop the event and
@@ -307,7 +311,9 @@ static void vfio_ccw_queue_crw(struct vfio_ccw_private *private,
crw->crw.erc = erc;
crw->crw.rsid = rsid;
+ spin_lock_irqsave(&private->crw_lock, flags);
list_add_tail(&crw->next, &private->crw);
+ spin_unlock_irqrestore(&private->crw_lock, flags);
queue_work(vfio_ccw_work_q, &private->crw_work);
}
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index b8e702f36106..2e2b05b78073 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -61,6 +61,7 @@ static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
INIT_WORK(&private->crw_work, vfio_ccw_crw_todo);
INIT_WORK(&private->notoper_work, vfio_ccw_notoper_todo);
+ spin_lock_init(&private->crw_lock);
private->cp.guest_cp = kzalloc_objs(struct ccw1, CCWCHAIN_LEN_MAX);
if (!private->cp.guest_cp)
@@ -138,11 +139,14 @@ static void vfio_ccw_mdev_release_dev(struct vfio_device *vdev)
struct vfio_ccw_private *private =
container_of(vdev, struct vfio_ccw_private, vdev);
struct vfio_ccw_crw *crw, *temp;
+ unsigned long flags;
+ spin_lock_irqsave(&private->crw_lock, flags);
list_for_each_entry_safe(crw, temp, &private->crw, next) {
list_del(&crw->next);
kfree(crw);
}
+ spin_unlock_irqrestore(&private->crw_lock, flags);
cancel_work_sync(&private->io_work);
cancel_work_sync(&private->crw_work);
diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h
index b595fd81f370..dd8efa9ee64e 100644
--- a/drivers/s390/cio/vfio_ccw_private.h
+++ b/drivers/s390/cio/vfio_ccw_private.h
@@ -98,6 +98,8 @@ struct vfio_ccw_parent {
* @cp: channel program for the current I/O operation
* @irb: irb info received from interrupt
* @scsw: scsw info
+ * @crw_lock: serialization of CRW list information
+ * @crw: list of Channel Report Word elements
* @io_trigger: eventfd ctx for signaling userspace I/O results
* @crw_trigger: eventfd ctx for signaling userspace CRW information
* @req_trigger: eventfd ctx for signaling userspace to return device
@@ -122,6 +124,8 @@ struct vfio_ccw_private {
struct irb irb;
union scsw scsw;
+
+ spinlock_t crw_lock;
struct list_head crw;
struct eventfd_ctx *io_trigger;
--
2.53.0
next prev parent reply other threads:[~2026-07-26 4:01 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-26 4:01 [PATCH v5 00/10] s390/vfio_ccw fixes Eric Farman
2026-07-26 4:01 ` [PATCH v5 01/10] s390/vfio_ccw: free all memory if cp_init() fails Eric Farman
2026-07-26 4:15 ` sashiko-bot
2026-07-26 4:01 ` [PATCH v5 02/10] s390/vfio_ccw: limit the number of channel program segments Eric Farman
2026-07-26 4:08 ` sashiko-bot
2026-07-26 4:01 ` [PATCH v5 03/10] s390/vfio_ccw: fix out of bounds check on CCW array Eric Farman
2026-07-26 4:33 ` sashiko-bot
2026-07-26 4:01 ` [PATCH v5 04/10] s390/vfio_ccw: ensure first IDAW remains constant Eric Farman
2026-07-26 4:18 ` sashiko-bot
2026-07-26 4:01 ` [PATCH v5 05/10] s390/vfio_ccw: calculate idal length based on idaw type Eric Farman
2026-07-26 4:14 ` sashiko-bot
2026-07-26 4:01 ` [PATCH v5 06/10] s390/vfio_ccw: ensure index for read/write regions are within range Eric Farman
2026-07-26 4:16 ` sashiko-bot
2026-07-26 4:01 ` [PATCH v5 07/10] s390/vfio_ccw: cancel existing workqueues Eric Farman
2026-07-26 4:16 ` sashiko-bot
2026-07-26 4:01 ` [PATCH v5 08/10] s390/vfio_ccw: move cp cleanup out of not operational Eric Farman
2026-07-26 4:14 ` sashiko-bot
2026-07-26 4:01 ` [PATCH v5 09/10] s390/vfio_ccw: implement a channel program mutex Eric Farman
2026-07-26 4:18 ` sashiko-bot
2026-07-26 4:01 ` Eric Farman [this message]
2026-07-26 4:27 ` [PATCH v5 10/10] s390/vfio_ccw: implement a crw lock 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=20260726040129.2946151-11-farman@linux.ibm.com \
--to=farman@linux.ibm.com \
--cc=alifm@linux.ibm.com \
--cc=borntraeger@linux.ibm.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=mjrosato@linux.ibm.com \
--cc=pasic@linux.ibm.com \
--cc=stable@vger.kernel.org \
/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.