diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2009-03-26 10:24:05 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-03-26 10:24:12 -0400 |
commit | eb32ae8d0e052d1a287f99f93130ea2ad9af317e (patch) | |
tree | a2841ecbe3768fe248b798a311fa2ebdd6aa0907 /drivers | |
parent | 1485c5c88483d200c9c4c71ed7e8eef1a1e317a1 (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.c | 27 | ||||
-rw-r--r-- | drivers/s390/cio/device.h | 2 | ||||
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 4 |
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 | ||
684 | static void | 684 | void ccw_device_do_unbind_bind(struct work_struct *work) |
685 | ccw_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 | |||
699 | void 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 | ||
715 | static void | 702 | static 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 | ||
81 | int ccw_device_cancel_halt_clear(struct ccw_device *); | 81 | int ccw_device_cancel_halt_clear(struct ccw_device *); |
82 | 82 | ||
83 | void ccw_device_do_unreg_rereg(struct work_struct *); | 83 | void ccw_device_do_unbind_bind(struct work_struct *); |
84 | void ccw_device_move_to_orphanage(struct work_struct *); | 84 | void ccw_device_move_to_orphanage(struct work_struct *); |
85 | int ccw_device_is_orphan(struct ccw_device *); | 85 | int 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 | ||