diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-01-13 16:55:05 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-01-13 16:55:05 -0500 |
commit | ff483d55ba6fb50a8d6f99e808da35218533b1ef (patch) | |
tree | 4e5f33a15074af298e1c5aff6c5491e374a1717f | |
parent | a30f82b7ebc87cdec3ef48303278f02970086118 (diff) |
Revert "s390: use device_remove_file_self() instead of device_schedule_callback()"
This reverts commit bdbb0a1376635d80e096f6433595a38984cf5408.
Tejun writes:
I'm sorry but can you please revert the whole series?
get_active() waiting while a node is deactivated has potential
to lead to deadlock and that deactivate/reactivate interface is
something fundamentally flawed and that cgroup will have to work
with the remove_self() like everybody else. IOW, I think the
first posting was correct.
Cc: Tejun Heo <tj@kernel.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: linux390@de.ibm.com
Cc: linux-s390@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | arch/s390/include/asm/ccwgroup.h | 1 | ||||
-rw-r--r-- | arch/s390/pci/pci_sysfs.c | 18 | ||||
-rw-r--r-- | drivers/s390/block/dcssblk.c | 14 | ||||
-rw-r--r-- | drivers/s390/cio/ccwgroup.c | 26 |
4 files changed, 27 insertions, 32 deletions
diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h index 6e670f88d125..23723ce5ca7a 100644 --- a/arch/s390/include/asm/ccwgroup.h +++ b/arch/s390/include/asm/ccwgroup.h | |||
@@ -23,7 +23,6 @@ struct ccwgroup_device { | |||
23 | unsigned int count; | 23 | unsigned int count; |
24 | struct device dev; | 24 | struct device dev; |
25 | struct ccw_device *cdev[0]; | 25 | struct ccw_device *cdev[0]; |
26 | struct work_struct ungroup_work; | ||
27 | }; | 26 | }; |
28 | 27 | ||
29 | /** | 28 | /** |
diff --git a/arch/s390/pci/pci_sysfs.c b/arch/s390/pci/pci_sysfs.c index ab4a91393005..cf8a12ff733b 100644 --- a/arch/s390/pci/pci_sysfs.c +++ b/arch/s390/pci/pci_sysfs.c | |||
@@ -48,27 +48,29 @@ static ssize_t show_pfgid(struct device *dev, struct device_attribute *attr, | |||
48 | } | 48 | } |
49 | static DEVICE_ATTR(pfgid, S_IRUGO, show_pfgid, NULL); | 49 | static DEVICE_ATTR(pfgid, S_IRUGO, show_pfgid, NULL); |
50 | 50 | ||
51 | static ssize_t store_recover(struct device *dev, struct device_attribute *attr, | 51 | static void recover_callback(struct device *dev) |
52 | const char *buf, size_t count) | ||
53 | { | 52 | { |
54 | struct pci_dev *pdev = to_pci_dev(dev); | 53 | struct pci_dev *pdev = to_pci_dev(dev); |
55 | struct zpci_dev *zdev = get_zdev(pdev); | 54 | struct zpci_dev *zdev = get_zdev(pdev); |
56 | int ret; | 55 | int ret; |
57 | 56 | ||
58 | if (!device_remove_file_self(dev, attr)) | ||
59 | return count; | ||
60 | |||
61 | pci_stop_and_remove_bus_device(pdev); | 57 | pci_stop_and_remove_bus_device(pdev); |
62 | ret = zpci_disable_device(zdev); | 58 | ret = zpci_disable_device(zdev); |
63 | if (ret) | 59 | if (ret) |
64 | return ret; | 60 | return; |
65 | 61 | ||
66 | ret = zpci_enable_device(zdev); | 62 | ret = zpci_enable_device(zdev); |
67 | if (ret) | 63 | if (ret) |
68 | return ret; | 64 | return; |
69 | 65 | ||
70 | pci_rescan_bus(zdev->bus); | 66 | pci_rescan_bus(zdev->bus); |
71 | return count; | 67 | } |
68 | |||
69 | static ssize_t store_recover(struct device *dev, struct device_attribute *attr, | ||
70 | const char *buf, size_t count) | ||
71 | { | ||
72 | int rc = device_schedule_callback(dev, recover_callback); | ||
73 | return rc ? rc : count; | ||
72 | } | 74 | } |
73 | static DEVICE_ATTR(recover, S_IWUSR, NULL, store_recover); | 75 | static DEVICE_ATTR(recover, S_IWUSR, NULL, store_recover); |
74 | 76 | ||
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 2e2f454a05a1..6eca019bcf30 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
@@ -304,6 +304,12 @@ dcssblk_load_segment(char *name, struct segment_info **seg_info) | |||
304 | return rc; | 304 | return rc; |
305 | } | 305 | } |
306 | 306 | ||
307 | static void dcssblk_unregister_callback(struct device *dev) | ||
308 | { | ||
309 | device_unregister(dev); | ||
310 | put_device(dev); | ||
311 | } | ||
312 | |||
307 | /* | 313 | /* |
308 | * device attribute for switching shared/nonshared (exclusive) | 314 | * device attribute for switching shared/nonshared (exclusive) |
309 | * operation (show + store) | 315 | * operation (show + store) |
@@ -391,13 +397,7 @@ removeseg: | |||
391 | blk_cleanup_queue(dev_info->dcssblk_queue); | 397 | blk_cleanup_queue(dev_info->dcssblk_queue); |
392 | dev_info->gd->queue = NULL; | 398 | dev_info->gd->queue = NULL; |
393 | put_disk(dev_info->gd); | 399 | put_disk(dev_info->gd); |
394 | up_write(&dcssblk_devices_sem); | 400 | rc = device_schedule_callback(dev, dcssblk_unregister_callback); |
395 | |||
396 | if (device_remove_file_self(dev, attr)) { | ||
397 | device_unregister(dev); | ||
398 | put_device(dev); | ||
399 | } | ||
400 | return rc; | ||
401 | out: | 401 | out: |
402 | up_write(&dcssblk_devices_sem); | 402 | up_write(&dcssblk_devices_sem); |
403 | return rc; | 403 | return rc; |
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 67b9dc9044c2..959135a01847 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -168,12 +168,14 @@ static ssize_t ccwgroup_online_show(struct device *dev, | |||
168 | * Provide an 'ungroup' attribute so the user can remove group devices no | 168 | * Provide an 'ungroup' attribute so the user can remove group devices no |
169 | * longer needed or accidentially created. Saves memory :) | 169 | * longer needed or accidentially created. Saves memory :) |
170 | */ | 170 | */ |
171 | static void ccwgroup_ungroup(struct ccwgroup_device *gdev) | 171 | static void ccwgroup_ungroup_callback(struct device *dev) |
172 | { | 172 | { |
173 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); | ||
174 | |||
173 | mutex_lock(&gdev->reg_mutex); | 175 | mutex_lock(&gdev->reg_mutex); |
174 | if (device_is_registered(&gdev->dev)) { | 176 | if (device_is_registered(&gdev->dev)) { |
175 | __ccwgroup_remove_symlinks(gdev); | 177 | __ccwgroup_remove_symlinks(gdev); |
176 | device_unregister(&gdev->dev); | 178 | device_unregister(dev); |
177 | __ccwgroup_remove_cdev_refs(gdev); | 179 | __ccwgroup_remove_cdev_refs(gdev); |
178 | } | 180 | } |
179 | mutex_unlock(&gdev->reg_mutex); | 181 | mutex_unlock(&gdev->reg_mutex); |
@@ -193,9 +195,10 @@ static ssize_t ccwgroup_ungroup_store(struct device *dev, | |||
193 | rc = -EINVAL; | 195 | rc = -EINVAL; |
194 | goto out; | 196 | goto out; |
195 | } | 197 | } |
196 | 198 | /* Note that we cannot unregister the device from one of its | |
197 | if (device_remove_file_self(dev, attr)) | 199 | * attribute methods, so we have to use this roundabout approach. |
198 | ccwgroup_ungroup(gdev); | 200 | */ |
201 | rc = device_schedule_callback(dev, ccwgroup_ungroup_callback); | ||
199 | out: | 202 | out: |
200 | if (rc) { | 203 | if (rc) { |
201 | if (rc != -EAGAIN) | 204 | if (rc != -EAGAIN) |
@@ -221,14 +224,6 @@ static const struct attribute_group *ccwgroup_attr_groups[] = { | |||
221 | NULL, | 224 | NULL, |
222 | }; | 225 | }; |
223 | 226 | ||
224 | static void ccwgroup_ungroup_workfn(struct work_struct *work) | ||
225 | { | ||
226 | struct ccwgroup_device *gdev = | ||
227 | container_of(work, struct ccwgroup_device, ungroup_work); | ||
228 | |||
229 | ccwgroup_ungroup(gdev); | ||
230 | } | ||
231 | |||
232 | static void ccwgroup_release(struct device *dev) | 227 | static void ccwgroup_release(struct device *dev) |
233 | { | 228 | { |
234 | kfree(to_ccwgroupdev(dev)); | 229 | kfree(to_ccwgroupdev(dev)); |
@@ -328,7 +323,6 @@ int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv, | |||
328 | atomic_set(&gdev->onoff, 0); | 323 | atomic_set(&gdev->onoff, 0); |
329 | mutex_init(&gdev->reg_mutex); | 324 | mutex_init(&gdev->reg_mutex); |
330 | mutex_lock(&gdev->reg_mutex); | 325 | mutex_lock(&gdev->reg_mutex); |
331 | INIT_WORK(&gdev->ungroup_work, ccwgroup_ungroup_workfn); | ||
332 | gdev->count = num_devices; | 326 | gdev->count = num_devices; |
333 | gdev->dev.bus = &ccwgroup_bus_type; | 327 | gdev->dev.bus = &ccwgroup_bus_type; |
334 | gdev->dev.parent = parent; | 328 | gdev->dev.parent = parent; |
@@ -410,10 +404,10 @@ EXPORT_SYMBOL(ccwgroup_create_dev); | |||
410 | static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, | 404 | static int ccwgroup_notifier(struct notifier_block *nb, unsigned long action, |
411 | void *data) | 405 | void *data) |
412 | { | 406 | { |
413 | struct ccwgroup_device *gdev = to_ccwgroupdev(data); | 407 | struct device *dev = data; |
414 | 408 | ||
415 | if (action == BUS_NOTIFY_UNBIND_DRIVER) | 409 | if (action == BUS_NOTIFY_UNBIND_DRIVER) |
416 | schedule_work(&gdev->ungroup_work); | 410 | device_schedule_callback(dev, ccwgroup_ungroup_callback); |
417 | 411 | ||
418 | return NOTIFY_OK; | 412 | return NOTIFY_OK; |
419 | } | 413 | } |