Skip to content

Commit 204b394

Browse files
efarmanawilliam
authored andcommitted
vfio/ccw: Move FSM open/close to MDEV open/close
Part of the confusion that has existed is the FSM lifecycle of subchannels between the common CSS driver and the vfio-ccw driver. During configuration, the FSM state goes from NOT_OPER to STANDBY to IDLE, but then back to NOT_OPER. For example: vfio_ccw_sch_probe: VFIO_CCW_STATE_NOT_OPER vfio_ccw_sch_probe: VFIO_CCW_STATE_STANDBY vfio_ccw_mdev_probe: VFIO_CCW_STATE_IDLE vfio_ccw_mdev_remove: VFIO_CCW_STATE_NOT_OPER vfio_ccw_sch_remove: VFIO_CCW_STATE_NOT_OPER vfio_ccw_sch_shutdown: VFIO_CCW_STATE_NOT_OPER Rearrange the open/close events to align with the mdev open/close, to better manage the memory and state of the devices as time progresses. Specifically, make mdev_open() perform the FSM open, and mdev_close() perform the FSM close instead of reset (which is both close and open). This makes the NOT_OPER state a dead-end path, indicating the device is probably not recoverable without fully probing and re-configuring the device. This has the nice side-effect of removing a number of special-cases where the FSM state is managed outside of the FSM itself (such as the aforementioned mdev_close() routine). Suggested-by: Jason Gunthorpe <[email protected]> Signed-off-by: Eric Farman <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Reviewed-by: Matthew Rosato <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alex Williamson <[email protected]>
1 parent bfec266 commit 204b394

File tree

3 files changed

+39
-32
lines changed

3 files changed

+39
-32
lines changed

drivers/s390/cio/vfio_ccw_drv.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch)
138138

139139
private->sch = sch;
140140
mutex_init(&private->io_mutex);
141-
private->state = VFIO_CCW_STATE_NOT_OPER;
141+
private->state = VFIO_CCW_STATE_STANDBY;
142142
INIT_LIST_HEAD(&private->crw);
143143
INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
144144
INIT_WORK(&private->crw_work, vfio_ccw_crw_todo);
@@ -222,21 +222,15 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
222222

223223
dev_set_drvdata(&sch->dev, private);
224224

225-
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_OPEN);
226-
if (private->state == VFIO_CCW_STATE_NOT_OPER)
227-
goto out_free;
228-
229225
ret = mdev_register_device(&sch->dev, &vfio_ccw_mdev_driver);
230226
if (ret)
231-
goto out_disable;
227+
goto out_free;
232228

233229
VFIO_CCW_MSG_EVENT(4, "bound to subchannel %x.%x.%04x\n",
234230
sch->schid.cssid, sch->schid.ssid,
235231
sch->schid.sch_no);
236232
return 0;
237233

238-
out_disable:
239-
cio_disable_subchannel(sch);
240234
out_free:
241235
dev_set_drvdata(&sch->dev, NULL);
242236
vfio_ccw_free_private(private);
@@ -264,6 +258,7 @@ static void vfio_ccw_sch_shutdown(struct subchannel *sch)
264258
struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
265259

266260
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_CLOSE);
261+
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
267262
}
268263

269264
/**

drivers/s390/cio/vfio_ccw_fsm.c

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ static void fsm_notoper(struct vfio_ccw_private *private,
175175
*/
176176
css_sched_sch_todo(sch, SCH_TODO_UNREG);
177177
private->state = VFIO_CCW_STATE_NOT_OPER;
178+
179+
/* This is usually handled during CLOSE event */
180+
cp_free(&private->cp);
178181
}
179182

180183
/*
@@ -379,9 +382,16 @@ static void fsm_open(struct vfio_ccw_private *private,
379382
spin_lock_irq(sch->lock);
380383
sch->isc = VFIO_CCW_ISC;
381384
ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
382-
if (!ret)
383-
private->state = VFIO_CCW_STATE_STANDBY;
385+
if (ret)
386+
goto err_unlock;
387+
388+
private->state = VFIO_CCW_STATE_IDLE;
384389
spin_unlock_irq(sch->lock);
390+
return;
391+
392+
err_unlock:
393+
spin_unlock_irq(sch->lock);
394+
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
385395
}
386396

387397
static void fsm_close(struct vfio_ccw_private *private,
@@ -393,16 +403,22 @@ static void fsm_close(struct vfio_ccw_private *private,
393403
spin_lock_irq(sch->lock);
394404

395405
if (!sch->schib.pmcw.ena)
396-
goto out_unlock;
406+
goto err_unlock;
397407

398408
ret = cio_disable_subchannel(sch);
399409
if (ret == -EBUSY)
400410
vfio_ccw_sch_quiesce(sch);
411+
if (ret)
412+
goto err_unlock;
401413

402-
out_unlock:
403-
private->state = VFIO_CCW_STATE_NOT_OPER;
414+
private->state = VFIO_CCW_STATE_STANDBY;
404415
spin_unlock_irq(sch->lock);
405416
cp_free(&private->cp);
417+
return;
418+
419+
err_unlock:
420+
spin_unlock_irq(sch->lock);
421+
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
406422
}
407423

408424
/*
@@ -414,16 +430,16 @@ fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS] = {
414430
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_error,
415431
[VFIO_CCW_EVENT_ASYNC_REQ] = fsm_async_error,
416432
[VFIO_CCW_EVENT_INTERRUPT] = fsm_disabled_irq,
417-
[VFIO_CCW_EVENT_OPEN] = fsm_open,
433+
[VFIO_CCW_EVENT_OPEN] = fsm_nop,
418434
[VFIO_CCW_EVENT_CLOSE] = fsm_nop,
419435
},
420436
[VFIO_CCW_STATE_STANDBY] = {
421437
[VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper,
422438
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_error,
423439
[VFIO_CCW_EVENT_ASYNC_REQ] = fsm_async_error,
424-
[VFIO_CCW_EVENT_INTERRUPT] = fsm_irq,
425-
[VFIO_CCW_EVENT_OPEN] = fsm_notoper,
426-
[VFIO_CCW_EVENT_CLOSE] = fsm_close,
440+
[VFIO_CCW_EVENT_INTERRUPT] = fsm_disabled_irq,
441+
[VFIO_CCW_EVENT_OPEN] = fsm_open,
442+
[VFIO_CCW_EVENT_CLOSE] = fsm_notoper,
427443
},
428444
[VFIO_CCW_STATE_IDLE] = {
429445
[VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper,

drivers/s390/cio/vfio_ccw_ops.c

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,12 @@ static int vfio_ccw_mdev_reset(struct vfio_ccw_private *private)
2424
/*
2525
* If the FSM state is seen as Not Operational after closing
2626
* and re-opening the mdev, return an error.
27-
*
28-
* Otherwise, change the FSM from STANDBY to IDLE which is
29-
* normally done by vfio_ccw_mdev_probe() in current lifecycle.
3027
*/
3128
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_CLOSE);
3229
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_OPEN);
3330
if (private->state == VFIO_CCW_STATE_NOT_OPER)
3431
return -EINVAL;
3532

36-
private->state = VFIO_CCW_STATE_IDLE;
37-
3833
return 0;
3934
}
4035

@@ -121,8 +116,6 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev)
121116
vfio_init_group_dev(&private->vdev, &mdev->dev,
122117
&vfio_ccw_dev_ops);
123118

124-
private->state = VFIO_CCW_STATE_IDLE;
125-
126119
VFIO_CCW_MSG_EVENT(2, "sch %x.%x.%04x: create\n",
127120
private->sch->schid.cssid,
128121
private->sch->schid.ssid,
@@ -137,7 +130,6 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev)
137130
err_atomic:
138131
vfio_uninit_group_dev(&private->vdev);
139132
atomic_inc(&private->avail);
140-
private->state = VFIO_CCW_STATE_STANDBY;
141133
return ret;
142134
}
143135

@@ -165,6 +157,10 @@ static int vfio_ccw_mdev_open_device(struct vfio_device *vdev)
165157
unsigned long events = VFIO_IOMMU_NOTIFY_DMA_UNMAP;
166158
int ret;
167159

160+
/* Device cannot simply be opened again from this state */
161+
if (private->state == VFIO_CCW_STATE_NOT_OPER)
162+
return -EINVAL;
163+
168164
private->nb.notifier_call = vfio_ccw_mdev_notifier;
169165

170166
ret = vfio_register_notifier(vdev, VFIO_IOMMU_NOTIFY,
@@ -184,6 +180,12 @@ static int vfio_ccw_mdev_open_device(struct vfio_device *vdev)
184180
if (ret)
185181
goto out_unregister;
186182

183+
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_OPEN);
184+
if (private->state == VFIO_CCW_STATE_NOT_OPER) {
185+
ret = -EINVAL;
186+
goto out_unregister;
187+
}
188+
187189
return ret;
188190

189191
out_unregister:
@@ -197,13 +199,7 @@ static void vfio_ccw_mdev_close_device(struct vfio_device *vdev)
197199
struct vfio_ccw_private *private =
198200
container_of(vdev, struct vfio_ccw_private, vdev);
199201

200-
if ((private->state != VFIO_CCW_STATE_NOT_OPER) &&
201-
(private->state != VFIO_CCW_STATE_STANDBY)) {
202-
if (!vfio_ccw_mdev_reset(private))
203-
private->state = VFIO_CCW_STATE_STANDBY;
204-
/* The state will be NOT_OPER on error. */
205-
}
206-
202+
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_CLOSE);
207203
vfio_ccw_unregister_dev_regions(private);
208204
vfio_unregister_notifier(vdev, VFIO_IOMMU_NOTIFY, &private->nb);
209205
}

0 commit comments

Comments
 (0)