Skip to content

Commit

Permalink
s390/ccwgroup: release the cdevs from within dev->release()
Browse files Browse the repository at this point in the history
Wiring up the cdevs is an essential part of the gdev creation. So
release them during the gdev destruction, ie. on the last put_device().
This could cause us to hold on to the cdevs a tiny bit longer, but
that's not a real concern.

As we have much less certainty of what context this put_device() is
executed from, switch to irqsave locking.

Signed-off-by: Julian Wiedmann <[email protected]>
Signed-off-by: Vasily Gorbik <[email protected]>
  • Loading branch information
julianwiedmann authored and Vasily Gorbik committed Jun 7, 2021
1 parent 95c09f0 commit 197cec2
Showing 1 changed file with 17 additions and 32 deletions.
49 changes: 17 additions & 32 deletions drivers/s390/cio/ccwgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,6 @@ static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
}
}

/*
* Remove references from ccw devices to ccw group device and from
* ccw group device to ccw devices.
*/
static void __ccwgroup_remove_cdev_refs(struct ccwgroup_device *gdev)
{
struct ccw_device *cdev;
int i;

for (i = 0; i < gdev->count; i++) {
cdev = gdev->cdev[i];
if (!cdev)
continue;
spin_lock_irq(cdev->ccwlock);
dev_set_drvdata(&cdev->dev, NULL);
spin_unlock_irq(cdev->ccwlock);
gdev->cdev[i] = NULL;
put_device(&cdev->dev);
}
}

/**
* ccwgroup_set_online() - enable a ccwgroup device
* @gdev: target ccwgroup device
Expand Down Expand Up @@ -175,7 +154,6 @@ static void ccwgroup_ungroup(struct ccwgroup_device *gdev)
if (device_is_registered(&gdev->dev)) {
__ccwgroup_remove_symlinks(gdev);
device_unregister(&gdev->dev);
__ccwgroup_remove_cdev_refs(gdev);
}
mutex_unlock(&gdev->reg_mutex);
}
Expand Down Expand Up @@ -228,7 +206,23 @@ static void ccwgroup_ungroup_workfn(struct work_struct *work)

static void ccwgroup_release(struct device *dev)
{
kfree(to_ccwgroupdev(dev));
struct ccwgroup_device *gdev = to_ccwgroupdev(dev);
unsigned int i;

for (i = 0; i < gdev->count; i++) {
struct ccw_device *cdev = gdev->cdev[i];
unsigned long flags;

if (cdev) {
spin_lock_irqsave(cdev->ccwlock, flags);
if (dev_get_drvdata(&cdev->dev) == gdev)
dev_set_drvdata(&cdev->dev, NULL);
spin_unlock_irqrestore(cdev->ccwlock, flags);
put_device(&cdev->dev);
}
}

kfree(gdev);
}

static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
Expand Down Expand Up @@ -396,15 +390,6 @@ int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv,
mutex_unlock(&gdev->reg_mutex);
return 0;
error:
for (i = 0; i < num_devices; i++)
if (gdev->cdev[i]) {
spin_lock_irq(gdev->cdev[i]->ccwlock);
if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev)
dev_set_drvdata(&gdev->cdev[i]->dev, NULL);
spin_unlock_irq(gdev->cdev[i]->ccwlock);
put_device(&gdev->cdev[i]->dev);
gdev->cdev[i] = NULL;
}
mutex_unlock(&gdev->reg_mutex);
put_device(&gdev->dev);
return rc;
Expand Down

0 comments on commit 197cec2

Please sign in to comment.