aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2009-03-26 10:24:05 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-03-26 10:24:12 -0400
commiteb32ae8d0e052d1a287f99f93130ea2ad9af317e (patch)
treea2841ecbe3768fe248b798a311fa2ebdd6aa0907 /drivers
parent1485c5c88483d200c9c4c71ed7e8eef1a1e317a1 (diff)
[S390] cio: Use unbind/bind instead of unregister/register.
The common I/O layer may encounter a situation where the device number of a ccw device has changed or a device driver doesn't want to keep a formerly disconnected device becoming operational again. Instead of using device_del()/ device_add() as now, we can just unbind the driver from the device and rebind it to get the desired effect (rebinding) with less overhead. Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/cio/device.c27
-rw-r--r--drivers/s390/cio/device.h2
-rw-r--r--drivers/s390/cio/device_fsm.c4
3 files changed, 10 insertions, 23 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 23d5752349b5..71b3b73e8ebe 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -681,35 +681,22 @@ get_orphaned_ccwdev_by_dev_id(struct channel_subsystem *css,
681 return dev ? to_ccwdev(dev) : NULL; 681 return dev ? to_ccwdev(dev) : NULL;
682} 682}
683 683
684static void 684void ccw_device_do_unbind_bind(struct work_struct *work)
685ccw_device_add_changed(struct work_struct *work)
686{
687 struct ccw_device_private *priv;
688 struct ccw_device *cdev;
689
690 priv = container_of(work, struct ccw_device_private, kick_work);
691 cdev = priv->cdev;
692 if (device_add(&cdev->dev)) {
693 put_device(&cdev->dev);
694 return;
695 }
696 set_bit(1, &cdev->private->registered);
697}
698
699void ccw_device_do_unreg_rereg(struct work_struct *work)
700{ 685{
701 struct ccw_device_private *priv; 686 struct ccw_device_private *priv;
702 struct ccw_device *cdev; 687 struct ccw_device *cdev;
703 struct subchannel *sch; 688 struct subchannel *sch;
689 int ret;
704 690
705 priv = container_of(work, struct ccw_device_private, kick_work); 691 priv = container_of(work, struct ccw_device_private, kick_work);
706 cdev = priv->cdev; 692 cdev = priv->cdev;
707 sch = to_subchannel(cdev->dev.parent); 693 sch = to_subchannel(cdev->dev.parent);
708 694
709 ccw_device_unregister(cdev); 695 if (test_bit(1, &cdev->private->registered)) {
710 PREPARE_WORK(&cdev->private->kick_work, 696 device_release_driver(&cdev->dev);
711 ccw_device_add_changed); 697 ret = device_attach(&cdev->dev);
712 queue_work(ccw_device_work, &cdev->private->kick_work); 698 WARN_ON(ret == -ENODEV);
699 }
713} 700}
714 701
715static void 702static void
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 0f2e63ea48de..85e01846ca65 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -80,7 +80,7 @@ void io_subchannel_init_config(struct subchannel *sch);
80 80
81int ccw_device_cancel_halt_clear(struct ccw_device *); 81int ccw_device_cancel_halt_clear(struct ccw_device *);
82 82
83void ccw_device_do_unreg_rereg(struct work_struct *); 83void ccw_device_do_unbind_bind(struct work_struct *);
84void ccw_device_move_to_orphanage(struct work_struct *); 84void ccw_device_move_to_orphanage(struct work_struct *);
85int ccw_device_is_orphan(struct ccw_device *); 85int ccw_device_is_orphan(struct ccw_device *);
86 86
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 8df5eaafc5ab..95f2f352cb9d 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -194,7 +194,7 @@ ccw_device_handle_oper(struct ccw_device *cdev)
194 cdev->id.dev_type != cdev->private->senseid.dev_type || 194 cdev->id.dev_type != cdev->private->senseid.dev_type ||
195 cdev->id.dev_model != cdev->private->senseid.dev_model) { 195 cdev->id.dev_model != cdev->private->senseid.dev_model) {
196 PREPARE_WORK(&cdev->private->kick_work, 196 PREPARE_WORK(&cdev->private->kick_work,
197 ccw_device_do_unreg_rereg); 197 ccw_device_do_unbind_bind);
198 queue_work(ccw_device_work, &cdev->private->kick_work); 198 queue_work(ccw_device_work, &cdev->private->kick_work);
199 return 0; 199 return 0;
200 } 200 }
@@ -366,7 +366,7 @@ static void ccw_device_oper_notify(struct ccw_device *cdev)
366 } 366 }
367 /* Driver doesn't want device back. */ 367 /* Driver doesn't want device back. */
368 ccw_device_set_notoper(cdev); 368 ccw_device_set_notoper(cdev);
369 PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unreg_rereg); 369 PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unbind_bind);
370 queue_work(ccw_device_work, &cdev->private->kick_work); 370 queue_work(ccw_device_work, &cdev->private->kick_work);
371} 371}
372 372