diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2014-06-13 11:02:24 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2014-06-16 04:32:24 -0400 |
commit | 9280ddb19489fa24e2d4f6f492d185ae1172bec2 (patch) | |
tree | 7146a4e9891ae8d38f3741664e387bdd03e35ea3 /drivers | |
parent | 613c4e0459603cc04384723b08fd62103b5eaaaf (diff) |
s390/ccwgroup: obtain extra reference for asynchronous processing
Commit 0b60f9ead5d4816e7e3d6e28f4a0d22d4a1b2513
"s390: use device_remove_file_self() instead of device_schedule_callback()"
changed ccwgroup to use an extra work queue instead of
device_schedule_callback. This function obtained an extra device
reference for its async work which is missing in the new implementation
and results in a "freeing memory with a lock still held" BUG. Fix
this by obtaining an extra reference for the async work.
Reported-by: Stefan Raspl <raspl@linux.vnet.ibm.com>
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/s390/cio/ccwgroup.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index dfd7bc681c25..040e643746aa 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -227,6 +227,7 @@ static void ccwgroup_ungroup_workfn(struct work_struct *work) | |||
227 | container_of(work, struct ccwgroup_device, ungroup_work); | 227 | container_of(work, struct ccwgroup_device, ungroup_work); |
228 | 228 | ||
229 | ccwgroup_ungroup(gdev); | 229 | ccwgroup_ungroup(gdev); |
230 | put_device(&gdev->dev); | ||
230 | } | 231 | } |
231 | 232 | ||
232 | static void ccwgroup_release(struct device *dev) | 233 | static void ccwgroup_release(struct device *dev) |
@@ -412,8 +413,10 @@ static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, | |||
412 | { | 413 | { |
413 | struct ccwgroup_device *gdev = to_ccwgroupdev(data); | 414 | struct ccwgroup_device *gdev = to_ccwgroupdev(data); |
414 | 415 | ||
415 | if (action == BUS_NOTIFY_UNBIND_DRIVER) | 416 | if (action == BUS_NOTIFY_UNBIND_DRIVER) { |
417 | get_device(&gdev->dev); | ||
416 | schedule_work(&gdev->ungroup_work); | 418 | schedule_work(&gdev->ungroup_work); |
419 | } | ||
417 | 420 | ||
418 | return NOTIFY_OK; | 421 | return NOTIFY_OK; |
419 | } | 422 | } |