aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device.c
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2007-04-27 10:01:39 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2007-04-27 10:01:42 -0400
commitef99516c9646802c3d38c3eb83de302e05b3c1b5 (patch)
tree48f9126ee7df357d45c253e1b879e3c0ead4dce4 /drivers/s390/cio/device.c
parent8c4941c53b14e5a08ed2f270e9f087b410a9abcc (diff)
[S390] cio: Unregister ccw devices directly.
We used to unregister ccw devices not directly from the I/O subchannel remove function in order to avoid lifelocks on the css bus semaphore. This semaphore is gone, and there is no reason to not unregister the ccw device directly (it is even better since it is more in keeping with the goal of immediate disconnect). Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/device.c')
-rw-r--r--drivers/s390/cio/device.c56
1 files changed, 12 insertions, 44 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 3b56f373da3a..03355902c582 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -290,16 +290,10 @@ int ccw_device_is_orphan(struct ccw_device *cdev)
290 return sch_is_pseudo_sch(to_subchannel(cdev->dev.parent)); 290 return sch_is_pseudo_sch(to_subchannel(cdev->dev.parent));
291} 291}
292 292
293static void ccw_device_unregister(struct work_struct *work) 293static void ccw_device_unregister(struct ccw_device *cdev)
294{ 294{
295 struct ccw_device_private *priv;
296 struct ccw_device *cdev;
297
298 priv = container_of(work, struct ccw_device_private, kick_work);
299 cdev = priv->cdev;
300 if (test_and_clear_bit(1, &cdev->private->registered)) 295 if (test_and_clear_bit(1, &cdev->private->registered))
301 device_unregister(&cdev->dev); 296 device_del(&cdev->dev);
302 put_device(&cdev->dev);
303} 297}
304 298
305static void 299static void
@@ -316,11 +310,8 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
316 spin_lock_irqsave(cdev->ccwlock, flags); 310 spin_lock_irqsave(cdev->ccwlock, flags);
317 cdev->private->state = DEV_STATE_NOT_OPER; 311 cdev->private->state = DEV_STATE_NOT_OPER;
318 spin_unlock_irqrestore(cdev->ccwlock, flags); 312 spin_unlock_irqrestore(cdev->ccwlock, flags);
319 if (get_device(&cdev->dev)) { 313 ccw_device_unregister(cdev);
320 PREPARE_WORK(&cdev->private->kick_work, 314 put_device(&cdev->dev);
321 ccw_device_unregister);
322 queue_work(ccw_device_work, &cdev->private->kick_work);
323 }
324 return ; 315 return ;
325 } 316 }
326 sch = to_subchannel(cdev->dev.parent); 317 sch = to_subchannel(cdev->dev.parent);
@@ -555,17 +546,10 @@ static struct attribute_group ccwdev_attr_group = {
555 .attrs = ccwdev_attrs, 546 .attrs = ccwdev_attrs,
556}; 547};
557 548
558static int 549struct attribute_group *ccwdev_attr_groups[] = {
559device_add_files (struct device *dev) 550 &ccwdev_attr_group,
560{ 551 NULL,
561 return sysfs_create_group(&dev->kobj, &ccwdev_attr_group); 552};
562}
563
564static void
565device_remove_files(struct device *dev)
566{
567 sysfs_remove_group(&dev->kobj, &ccwdev_attr_group);
568}
569 553
570/* this is a simple abstraction for device_register that sets the 554/* this is a simple abstraction for device_register that sets the
571 * correct bus type and adds the bus specific files */ 555 * correct bus type and adds the bus specific files */
@@ -580,10 +564,6 @@ static int ccw_device_register(struct ccw_device *cdev)
580 return ret; 564 return ret;
581 565
582 set_bit(1, &cdev->private->registered); 566 set_bit(1, &cdev->private->registered);
583 if ((ret = device_add_files(dev))) {
584 if (test_and_clear_bit(1, &cdev->private->registered))
585 device_del(dev);
586 }
587 return ret; 567 return ret;
588} 568}
589 569
@@ -655,10 +635,6 @@ ccw_device_add_changed(struct work_struct *work)
655 return; 635 return;
656 } 636 }
657 set_bit(1, &cdev->private->registered); 637 set_bit(1, &cdev->private->registered);
658 if (device_add_files(&cdev->dev)) {
659 if (test_and_clear_bit(1, &cdev->private->registered))
660 device_unregister(&cdev->dev);
661 }
662} 638}
663 639
664void ccw_device_do_unreg_rereg(struct work_struct *work) 640void ccw_device_do_unreg_rereg(struct work_struct *work)
@@ -671,9 +647,7 @@ void ccw_device_do_unreg_rereg(struct work_struct *work)
671 cdev = priv->cdev; 647 cdev = priv->cdev;
672 sch = to_subchannel(cdev->dev.parent); 648 sch = to_subchannel(cdev->dev.parent);
673 649
674 device_remove_files(&cdev->dev); 650 ccw_device_unregister(cdev);
675 if (test_and_clear_bit(1, &cdev->private->registered))
676 device_del(&cdev->dev);
677 PREPARE_WORK(&cdev->private->kick_work, 651 PREPARE_WORK(&cdev->private->kick_work,
678 ccw_device_add_changed); 652 ccw_device_add_changed);
679 queue_work(ccw_device_work, &cdev->private->kick_work); 653 queue_work(ccw_device_work, &cdev->private->kick_work);
@@ -712,6 +686,7 @@ static int io_subchannel_initialize_dev(struct subchannel *sch,
712 cdev->dev.parent = &sch->dev; 686 cdev->dev.parent = &sch->dev;
713 cdev->dev.release = ccw_device_release; 687 cdev->dev.release = ccw_device_release;
714 INIT_LIST_HEAD(&cdev->private->kick_work.entry); 688 INIT_LIST_HEAD(&cdev->private->kick_work.entry);
689 cdev->dev.groups = ccwdev_attr_groups;
715 /* Do first half of device_register. */ 690 /* Do first half of device_register. */
716 device_initialize(&cdev->dev); 691 device_initialize(&cdev->dev);
717 if (!get_device(&sch->dev)) { 692 if (!get_device(&sch->dev)) {
@@ -1141,15 +1116,8 @@ io_subchannel_remove (struct subchannel *sch)
1141 sch->dev.driver_data = NULL; 1116 sch->dev.driver_data = NULL;
1142 cdev->private->state = DEV_STATE_NOT_OPER; 1117 cdev->private->state = DEV_STATE_NOT_OPER;
1143 spin_unlock_irqrestore(cdev->ccwlock, flags); 1118 spin_unlock_irqrestore(cdev->ccwlock, flags);
1144 /* 1119 ccw_device_unregister(cdev);
1145 * Put unregistration on workqueue to avoid livelocks on the css bus 1120 put_device(&cdev->dev);
1146 * semaphore.
1147 */
1148 if (get_device(&cdev->dev)) {
1149 PREPARE_WORK(&cdev->private->kick_work,
1150 ccw_device_unregister);
1151 queue_work(ccw_device_work, &cdev->private->kick_work);
1152 }
1153 return 0; 1121 return 0;
1154} 1122}
1155 1123