Skip to content

Commit c9b85aa

Browse files
efarmangregkh
authored andcommitted
s390/vfio_ccw: Move cp cleanup out of not operational
[ Upstream commit 0c11f61 ] The fsm_notoper() routine is called when the device has been lost, and is (by definition) no longer operational. Since this can happen asynchronously from the normal behavior of the driver, the cleanup may happen when holding other locks in the calling sequence (notably, the cio subchannel lock). Push the cleanup of the private->cp resources to a workqueue, where it can be done out from under that lock sequence and a future patch can safely manage the locking requirements. Fixes: 204b394 ("vfio/ccw: Move FSM open/close to MDEV open/close") Cc: stable@vger.kernel.org Signed-off-by: Eric Farman <farman@linux.ibm.com> Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com> Stable-dep-of: 16b0798 ("s390/vfio_ccw: Implement a crw lock") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 7e9954e commit c9b85aa

4 files changed

Lines changed: 25 additions & 2 deletions

File tree

drivers/s390/cio/vfio_ccw_drv.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@ static void vfio_ccw_crw_todo(struct work_struct *work)
116116
eventfd_signal(private->crw_trigger, 1);
117117
}
118118

119+
static void vfio_ccw_notoper_todo(struct work_struct *work)
120+
{
121+
struct vfio_ccw_private *private;
122+
123+
private = container_of(work, struct vfio_ccw_private, notoper_work);
124+
125+
cp_free(&private->cp);
126+
}
127+
119128
/*
120129
* Css driver callbacks
121130
*/
@@ -141,6 +150,7 @@ static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch)
141150
INIT_LIST_HEAD(&private->crw);
142151
INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
143152
INIT_WORK(&private->crw_work, vfio_ccw_crw_todo);
153+
INIT_WORK(&private->notoper_work, vfio_ccw_notoper_todo);
144154

145155
private->cp.guest_cp = kcalloc(CCWCHAIN_LEN_MAX, sizeof(struct ccw1),
146156
GFP_KERNEL);

drivers/s390/cio/vfio_ccw_fsm.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,7 @@ static void fsm_notoper(struct vfio_ccw_private *private,
176176
css_sched_sch_todo(sch, SCH_TODO_UNREG);
177177
private->state = VFIO_CCW_STATE_NOT_OPER;
178178

179-
/* This is usually handled during CLOSE event */
180-
cp_free(&private->cp);
179+
queue_work(vfio_ccw_work_q, &private->notoper_work);
181180
}
182181

183182
/*

drivers/s390/cio/vfio_ccw_ops.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,16 @@ static void vfio_ccw_mdev_release_dev(struct vfio_device *vdev)
8989
/*
9090
* Ensure these work items are fully drained, so none can
9191
* fire after being released.
92+
*
93+
* notoper_work should have nothing to do here, because only
94+
* open devices could have channel_program resources in use
95+
* and those would be released during close. Nevertheless,
96+
* call flush here as well to be certain anything that was
97+
* allocated is freed.
9298
*/
9399
cancel_work_sync(&private->io_work);
94100
cancel_work_sync(&private->crw_work);
101+
flush_work(&private->notoper_work);
95102

96103
/*
97104
* We cannot free vfio_ccw_private here because it includes
@@ -173,9 +180,14 @@ static void vfio_ccw_mdev_close_device(struct vfio_device *vdev)
173180
/*
174181
* Ensure these work items are drained, in the event the
175182
* device is re-opened instead of released.
183+
*
184+
* notoper_work needs to be given a chance to run if it
185+
* is queued, so any memory associated with the channel
186+
* program can be returned.
176187
*/
177188
cancel_work_sync(&private->io_work);
178189
cancel_work_sync(&private->crw_work);
190+
flush_work(&private->notoper_work);
179191

180192
vfio_ccw_unregister_dev_regions(private);
181193
}

drivers/s390/cio/vfio_ccw_private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ struct vfio_ccw_crw {
8888
* @req_trigger: eventfd ctx for signaling userspace to return device
8989
* @io_work: work for deferral process of I/O handling
9090
* @crw_work: work for deferral process of CRW handling
91+
* @notoper_work: work for deferred processing in not-operational state
9192
* @release_comp: synchronization helper for vfio device release
9293
* @parent: parent data structures for mdevs created
9394
*/
@@ -114,6 +115,7 @@ struct vfio_ccw_private {
114115
struct eventfd_ctx *req_trigger;
115116
struct work_struct io_work;
116117
struct work_struct crw_work;
118+
struct work_struct notoper_work;
117119

118120
struct completion release_comp;
119121

0 commit comments

Comments
 (0)