Commit eb32ae8d authored by Cornelia Huck's avatar Cornelia Huck Committed by Martin Schwidefsky

[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: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 1485c5c8
...@@ -681,35 +681,22 @@ get_orphaned_ccwdev_by_dev_id(struct channel_subsystem *css, ...@@ -681,35 +681,22 @@ get_orphaned_ccwdev_by_dev_id(struct channel_subsystem *css,
return dev ? to_ccwdev(dev) : NULL; return dev ? to_ccwdev(dev) : NULL;
} }
static void void ccw_device_do_unbind_bind(struct work_struct *work)
ccw_device_add_changed(struct work_struct *work)
{
struct ccw_device_private *priv;
struct ccw_device *cdev;
priv = container_of(work, struct ccw_device_private, kick_work);
cdev = priv->cdev;
if (device_add(&cdev->dev)) {
put_device(&cdev->dev);
return;
}
set_bit(1, &cdev->private->registered);
}
void ccw_device_do_unreg_rereg(struct work_struct *work)
{ {
struct ccw_device_private *priv; struct ccw_device_private *priv;
struct ccw_device *cdev; struct ccw_device *cdev;
struct subchannel *sch; struct subchannel *sch;
int ret;
priv = container_of(work, struct ccw_device_private, kick_work); priv = container_of(work, struct ccw_device_private, kick_work);
cdev = priv->cdev; cdev = priv->cdev;
sch = to_subchannel(cdev->dev.parent); sch = to_subchannel(cdev->dev.parent);
ccw_device_unregister(cdev); if (test_bit(1, &cdev->private->registered)) {
PREPARE_WORK(&cdev->private->kick_work, device_release_driver(&cdev->dev);
ccw_device_add_changed); ret = device_attach(&cdev->dev);
queue_work(ccw_device_work, &cdev->private->kick_work); WARN_ON(ret == -ENODEV);
}
} }
static void static void
......
...@@ -80,7 +80,7 @@ void io_subchannel_init_config(struct subchannel *sch); ...@@ -80,7 +80,7 @@ void io_subchannel_init_config(struct subchannel *sch);
int ccw_device_cancel_halt_clear(struct ccw_device *); int ccw_device_cancel_halt_clear(struct ccw_device *);
void ccw_device_do_unreg_rereg(struct work_struct *); void ccw_device_do_unbind_bind(struct work_struct *);
void ccw_device_move_to_orphanage(struct work_struct *); void ccw_device_move_to_orphanage(struct work_struct *);
int ccw_device_is_orphan(struct ccw_device *); int ccw_device_is_orphan(struct ccw_device *);
......
...@@ -194,7 +194,7 @@ ccw_device_handle_oper(struct ccw_device *cdev) ...@@ -194,7 +194,7 @@ ccw_device_handle_oper(struct ccw_device *cdev)
cdev->id.dev_type != cdev->private->senseid.dev_type || cdev->id.dev_type != cdev->private->senseid.dev_type ||
cdev->id.dev_model != cdev->private->senseid.dev_model) { cdev->id.dev_model != cdev->private->senseid.dev_model) {
PREPARE_WORK(&cdev->private->kick_work, PREPARE_WORK(&cdev->private->kick_work,
ccw_device_do_unreg_rereg); ccw_device_do_unbind_bind);
queue_work(ccw_device_work, &cdev->private->kick_work); queue_work(ccw_device_work, &cdev->private->kick_work);
return 0; return 0;
} }
...@@ -366,7 +366,7 @@ static void ccw_device_oper_notify(struct ccw_device *cdev) ...@@ -366,7 +366,7 @@ static void ccw_device_oper_notify(struct ccw_device *cdev)
} }
/* Driver doesn't want device back. */ /* Driver doesn't want device back. */
ccw_device_set_notoper(cdev); ccw_device_set_notoper(cdev);
PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unreg_rereg); PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unbind_bind);
queue_work(ccw_device_work, &cdev->private->kick_work); queue_work(ccw_device_work, &cdev->private->kick_work);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment