Take a reference to the vfio device when looking at the corresponding vfio_ccw_private struct, and put it back once we are finished. Suggested-by: Jason Gunthorpe <jgg@xxxxxxxxxx> Signed-off-by: Eric Farman <farman@xxxxxxxxxxxxx> --- drivers/s390/cio/vfio_ccw_drv.c | 9 ++++++++- drivers/s390/cio/vfio_ccw_private.h | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index c8cbbad6e1c5..2e55fa45f76c 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -71,6 +71,7 @@ int vfio_ccw_sch_quiesce(struct subchannel *sch) ret = cio_disable_subchannel(sch); } while (ret == -EBUSY); + vfio_device_put(&private->vdev); return ret; } @@ -131,6 +132,7 @@ static void vfio_ccw_sch_irq(struct subchannel *sch) inc_irq_stat(IRQIO_CIO); vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT); + vfio_device_put(&private->vdev); } struct vfio_ccw_private *vfio_ccw_alloc_private(struct mdev_device *mdev, @@ -252,6 +254,7 @@ static void vfio_ccw_sch_shutdown(struct subchannel *sch) vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_CLOSE); vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER); + vfio_device_put(&private->vdev); } /** @@ -287,6 +290,7 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process) out_unlock: spin_unlock_irqrestore(sch->lock, flags); + vfio_device_put(&private->vdev); return rc; } @@ -334,8 +338,10 @@ static int vfio_ccw_chp_event(struct subchannel *sch, sch->schid.ssid, sch->schid.sch_no, mask, event); - if (cio_update_schib(sch)) + if (cio_update_schib(sch)) { + vfio_device_put(&private->vdev); return -ENODEV; + } switch (event) { case CHP_VARY_OFF: @@ -365,6 +371,7 @@ static int vfio_ccw_chp_event(struct subchannel *sch, break; } + vfio_device_put(&private->vdev); return 0; } diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h index 3833204bd388..be238cf277ff 100644 --- a/drivers/s390/cio/vfio_ccw_private.h +++ b/drivers/s390/cio/vfio_ccw_private.h @@ -135,6 +135,8 @@ static inline struct vfio_ccw_private *vfio_ccw_get_private(struct subchannel *s return NULL; private = dev_get_drvdata(&sch->dev); + if (private && !vfio_device_try_get(&private->vdev)) + private = NULL; return private; } -- 2.32.0