diff options
Diffstat (limited to 'drivers/s390/cio/ccwgroup.c')
-rw-r--r-- | drivers/s390/cio/ccwgroup.c | 28 |
1 files changed, 11 insertions, 17 deletions
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index dfd7bc681c25..e443b0d0b236 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -184,7 +184,7 @@ static ssize_t ccwgroup_ungroup_store(struct device *dev, | |||
184 | const char *buf, size_t count) | 184 | const char *buf, size_t count) |
185 | { | 185 | { |
186 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); | 186 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); |
187 | int rc; | 187 | int rc = 0; |
188 | 188 | ||
189 | /* Prevent concurrent online/offline processing and ungrouping. */ | 189 | /* Prevent concurrent online/offline processing and ungrouping. */ |
190 | if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0) | 190 | if (atomic_cmpxchg(&gdev->onoff, 0, 1) != 0) |
@@ -196,11 +196,12 @@ static ssize_t ccwgroup_ungroup_store(struct device *dev, | |||
196 | 196 | ||
197 | if (device_remove_file_self(dev, attr)) | 197 | if (device_remove_file_self(dev, attr)) |
198 | ccwgroup_ungroup(gdev); | 198 | ccwgroup_ungroup(gdev); |
199 | else | ||
200 | rc = -ENODEV; | ||
199 | out: | 201 | out: |
200 | if (rc) { | 202 | if (rc) { |
201 | if (rc != -EAGAIN) | 203 | /* Release onoff "lock" when ungrouping failed. */ |
202 | /* Release onoff "lock" when ungrouping failed. */ | 204 | atomic_set(&gdev->onoff, 0); |
203 | atomic_set(&gdev->onoff, 0); | ||
204 | return rc; | 205 | return rc; |
205 | } | 206 | } |
206 | return count; | 207 | return count; |
@@ -227,6 +228,7 @@ static void ccwgroup_ungroup_workfn(struct work_struct *work) | |||
227 | container_of(work, struct ccwgroup_device, ungroup_work); | 228 | container_of(work, struct ccwgroup_device, ungroup_work); |
228 | 229 | ||
229 | ccwgroup_ungroup(gdev); | 230 | ccwgroup_ungroup(gdev); |
231 | put_device(&gdev->dev); | ||
230 | } | 232 | } |
231 | 233 | ||
232 | static void ccwgroup_release(struct device *dev) | 234 | static void ccwgroup_release(struct device *dev) |
@@ -412,8 +414,10 @@ static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, | |||
412 | { | 414 | { |
413 | struct ccwgroup_device *gdev = to_ccwgroupdev(data); | 415 | struct ccwgroup_device *gdev = to_ccwgroupdev(data); |
414 | 416 | ||
415 | if (action == BUS_NOTIFY_UNBIND_DRIVER) | 417 | if (action == BUS_NOTIFY_UNBIND_DRIVER) { |
418 | get_device(&gdev->dev); | ||
416 | schedule_work(&gdev->ungroup_work); | 419 | schedule_work(&gdev->ungroup_work); |
420 | } | ||
417 | 421 | ||
418 | return NOTIFY_OK; | 422 | return NOTIFY_OK; |
419 | } | 423 | } |
@@ -582,11 +586,7 @@ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) | |||
582 | __ccwgroup_match_all))) { | 586 | __ccwgroup_match_all))) { |
583 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); | 587 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); |
584 | 588 | ||
585 | mutex_lock(&gdev->reg_mutex); | 589 | ccwgroup_ungroup(gdev); |
586 | __ccwgroup_remove_symlinks(gdev); | ||
587 | device_unregister(dev); | ||
588 | __ccwgroup_remove_cdev_refs(gdev); | ||
589 | mutex_unlock(&gdev->reg_mutex); | ||
590 | put_device(dev); | 590 | put_device(dev); |
591 | } | 591 | } |
592 | driver_unregister(&cdriver->driver); | 592 | driver_unregister(&cdriver->driver); |
@@ -633,13 +633,7 @@ void ccwgroup_remove_ccwdev(struct ccw_device *cdev) | |||
633 | get_device(&gdev->dev); | 633 | get_device(&gdev->dev); |
634 | spin_unlock_irq(cdev->ccwlock); | 634 | spin_unlock_irq(cdev->ccwlock); |
635 | /* Unregister group device. */ | 635 | /* Unregister group device. */ |
636 | mutex_lock(&gdev->reg_mutex); | 636 | ccwgroup_ungroup(gdev); |
637 | if (device_is_registered(&gdev->dev)) { | ||
638 | __ccwgroup_remove_symlinks(gdev); | ||
639 | device_unregister(&gdev->dev); | ||
640 | __ccwgroup_remove_cdev_refs(gdev); | ||
641 | } | ||
642 | mutex_unlock(&gdev->reg_mutex); | ||
643 | /* Release ccwgroup device reference for local processing. */ | 637 | /* Release ccwgroup device reference for local processing. */ |
644 | put_device(&gdev->dev); | 638 | put_device(&gdev->dev); |
645 | } | 639 | } |