Commit 3d62fe18 authored by Eric Farman's avatar Eric Farman Committed by Alex Williamson

vfio/ccw: move private to mdev lifecycle

Now that the mdev parent data is split out into its own struct,
it is safe to move the remaining private data to follow the
mdev probe/remove lifecycle. The mdev parent data will remain
where it is, and follow the subchannel and the css driver
interfaces.
Signed-off-by: default avatarEric Farman <farman@linux.ibm.com>
Reviewed-by: default avatarMatthew Rosato <mjrosato@linux.ibm.com>
Link: https://lore.kernel.org/r/20221104142007.1314999-5-farman@linux.ibm.comSigned-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent 06caaa27
...@@ -152,7 +152,7 @@ static void vfio_ccw_sch_irq(struct subchannel *sch) ...@@ -152,7 +152,7 @@ static void vfio_ccw_sch_irq(struct subchannel *sch)
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT); vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT);
} }
static void vfio_ccw_free_private(struct vfio_ccw_private *private) void vfio_ccw_free_private(struct vfio_ccw_private *private)
{ {
struct vfio_ccw_crw *crw, *temp; struct vfio_ccw_crw *crw, *temp;
...@@ -180,7 +180,6 @@ static void vfio_ccw_free_parent(struct device *dev) ...@@ -180,7 +180,6 @@ static void vfio_ccw_free_parent(struct device *dev)
static int vfio_ccw_sch_probe(struct subchannel *sch) static int vfio_ccw_sch_probe(struct subchannel *sch)
{ {
struct pmcw *pmcw = &sch->schib.pmcw; struct pmcw *pmcw = &sch->schib.pmcw;
struct vfio_ccw_private *private;
struct vfio_ccw_parent *parent; struct vfio_ccw_parent *parent;
int ret = -ENOMEM; int ret = -ENOMEM;
...@@ -201,14 +200,7 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) ...@@ -201,14 +200,7 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
if (ret) if (ret)
goto out_free; goto out_free;
private = kzalloc(sizeof(*private), GFP_KERNEL);
if (!private) {
device_unregister(&parent->dev);
return -ENOMEM;
}
dev_set_drvdata(&sch->dev, parent); dev_set_drvdata(&sch->dev, parent);
dev_set_drvdata(&parent->dev, private);
parent->mdev_type.sysfs_name = "io"; parent->mdev_type.sysfs_name = "io";
parent->mdev_type.pretty_name = "I/O subchannel (Non-QDIO)"; parent->mdev_type.pretty_name = "I/O subchannel (Non-QDIO)";
...@@ -227,25 +219,19 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) ...@@ -227,25 +219,19 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
out_unreg: out_unreg:
device_unregister(&parent->dev); device_unregister(&parent->dev);
out_free: out_free:
dev_set_drvdata(&parent->dev, NULL);
dev_set_drvdata(&sch->dev, NULL); dev_set_drvdata(&sch->dev, NULL);
if (private)
vfio_ccw_free_private(private);
return ret; return ret;
} }
static void vfio_ccw_sch_remove(struct subchannel *sch) static void vfio_ccw_sch_remove(struct subchannel *sch)
{ {
struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev); struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev);
struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev);
mdev_unregister_parent(&parent->parent); mdev_unregister_parent(&parent->parent);
device_unregister(&parent->dev); device_unregister(&parent->dev);
dev_set_drvdata(&sch->dev, NULL); dev_set_drvdata(&sch->dev, NULL);
vfio_ccw_free_private(private);
VFIO_CCW_MSG_EVENT(4, "unbound from subchannel %x.%x.%04x\n", VFIO_CCW_MSG_EVENT(4, "unbound from subchannel %x.%x.%04x\n",
sch->schid.cssid, sch->schid.ssid, sch->schid.cssid, sch->schid.ssid,
sch->schid.sch_no); sch->schid.sch_no);
......
...@@ -100,15 +100,20 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev) ...@@ -100,15 +100,20 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev)
{ {
struct subchannel *sch = to_subchannel(mdev->dev.parent); struct subchannel *sch = to_subchannel(mdev->dev.parent);
struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev); struct vfio_ccw_parent *parent = dev_get_drvdata(&sch->dev);
struct vfio_ccw_private *private = dev_get_drvdata(&parent->dev); struct vfio_ccw_private *private;
int ret; int ret;
if (private->state == VFIO_CCW_STATE_NOT_OPER) private = kzalloc(sizeof(*private), GFP_KERNEL);
return -ENODEV; if (!private)
return -ENOMEM;
ret = vfio_init_device(&private->vdev, &mdev->dev, &vfio_ccw_dev_ops); ret = vfio_init_device(&private->vdev, &mdev->dev, &vfio_ccw_dev_ops);
if (ret) if (ret) {
kfree(private);
return ret; return ret;
}
dev_set_drvdata(&parent->dev, private);
VFIO_CCW_MSG_EVENT(2, "sch %x.%x.%04x: create\n", VFIO_CCW_MSG_EVENT(2, "sch %x.%x.%04x: create\n",
sch->schid.cssid, sch->schid.cssid,
...@@ -122,6 +127,7 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev) ...@@ -122,6 +127,7 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev)
return 0; return 0;
err_put_vdev: err_put_vdev:
dev_set_drvdata(&parent->dev, NULL);
vfio_put_device(&private->vdev); vfio_put_device(&private->vdev);
return ret; return ret;
} }
...@@ -131,15 +137,6 @@ static void vfio_ccw_mdev_release_dev(struct vfio_device *vdev) ...@@ -131,15 +137,6 @@ static void vfio_ccw_mdev_release_dev(struct vfio_device *vdev)
struct vfio_ccw_private *private = struct vfio_ccw_private *private =
container_of(vdev, struct vfio_ccw_private, vdev); container_of(vdev, struct vfio_ccw_private, vdev);
/*
* We cannot free vfio_ccw_private here because it includes
* parent info which must be free'ed by css driver.
*
* Use a workaround by memset'ing the core device part and
* then notifying the remove path that all active references
* to this device have been released.
*/
memset(vdev, 0, sizeof(*vdev));
complete(&private->release_comp); complete(&private->release_comp);
} }
...@@ -156,6 +153,7 @@ static void vfio_ccw_mdev_remove(struct mdev_device *mdev) ...@@ -156,6 +153,7 @@ static void vfio_ccw_mdev_remove(struct mdev_device *mdev)
vfio_unregister_group_dev(&private->vdev); vfio_unregister_group_dev(&private->vdev);
dev_set_drvdata(&parent->dev, NULL);
vfio_put_device(&private->vdev); vfio_put_device(&private->vdev);
/* /*
* Wait for all active references on mdev are released so it * Wait for all active references on mdev are released so it
...@@ -166,6 +164,8 @@ static void vfio_ccw_mdev_remove(struct mdev_device *mdev) ...@@ -166,6 +164,8 @@ static void vfio_ccw_mdev_remove(struct mdev_device *mdev)
* cycle. * cycle.
*/ */
wait_for_completion(&private->release_comp); wait_for_completion(&private->release_comp);
vfio_ccw_free_private(private);
} }
static int vfio_ccw_mdev_open_device(struct vfio_device *vdev) static int vfio_ccw_mdev_open_device(struct vfio_device *vdev)
......
...@@ -134,6 +134,8 @@ int vfio_ccw_sch_quiesce(struct subchannel *sch); ...@@ -134,6 +134,8 @@ int vfio_ccw_sch_quiesce(struct subchannel *sch);
void vfio_ccw_sch_io_todo(struct work_struct *work); void vfio_ccw_sch_io_todo(struct work_struct *work);
void vfio_ccw_crw_todo(struct work_struct *work); void vfio_ccw_crw_todo(struct work_struct *work);
void vfio_ccw_free_private(struct vfio_ccw_private *private);
extern struct mdev_driver vfio_ccw_mdev_driver; extern struct mdev_driver vfio_ccw_mdev_driver;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment