/** * ccwgroup_remove_ccwdev() - remove function for slave devices * @cdev: ccw device to be removed * * This is a remove function for ccw devices that are slave devices in a ccw * group device. It sets the ccw device offline and also deregisters the * embedding ccw group device. */ void ccwgroup_remove_ccwdev(struct ccw_device *cdev) { struct ccwgroup_device *gdev; /* Ignore offlining errors, device is gone anyway. */ ccw_device_set_offline(cdev); /* If one of its devices is gone, the whole group is done for. */ spin_lock_irq(cdev->ccwlock); gdev = dev_get_drvdata(&cdev->dev); if (!gdev) { spin_unlock_irq(cdev->ccwlock); return; } /* Get ccwgroup device reference for local processing. */ get_device(&gdev->dev); spin_unlock_irq(cdev->ccwlock); /* Unregister group device. */ mutex_lock(&gdev->reg_mutex); if (device_is_registered(&gdev->dev)) { __ccwgroup_remove_symlinks(gdev); device_unregister(&gdev->dev); __ccwgroup_remove_cdev_refs(gdev); } mutex_unlock(&gdev->reg_mutex); /* Release ccwgroup device reference for local processing. */ put_device(&gdev->dev); }
/* * Provide an 'ungroup' attribute so the user can remove group devices no * longer needed or accidentially created. Saves memory :) */ static void ccwgroup_ungroup(struct ccwgroup_device *gdev) { mutex_lock(&gdev->reg_mutex); if (device_is_registered(&gdev->dev)) { __ccwgroup_remove_symlinks(gdev); device_unregister(&gdev->dev); __ccwgroup_remove_cdev_refs(gdev); } mutex_unlock(&gdev->reg_mutex); }
/** * ccwgroup_driver_unregister() - deregister a ccw group driver * @cdriver: driver to be deregistered * * This function is mainly a wrapper around driver_unregister(). */ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) { struct device *dev; /* We don't want ccwgroup devices to live longer than their driver. */ while ((dev = driver_find_device(&cdriver->driver, NULL, NULL, __ccwgroup_match_all))) { struct ccwgroup_device *gdev = to_ccwgroupdev(dev); mutex_lock(&gdev->reg_mutex); __ccwgroup_remove_symlinks(gdev); device_unregister(dev); __ccwgroup_remove_cdev_refs(gdev); mutex_unlock(&gdev->reg_mutex); put_device(dev); } driver_unregister(&cdriver->driver); }