forked from luck/tmp_suning_uos_patched
[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>
This commit is contained in:
parent
1485c5c884
commit
eb32ae8d0e
|
@ -681,35 +681,22 @@ get_orphaned_ccwdev_by_dev_id(struct channel_subsystem *css,
|
|||
return dev ? to_ccwdev(dev) : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
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)
|
||||
void ccw_device_do_unbind_bind(struct work_struct *work)
|
||||
{
|
||||
struct ccw_device_private *priv;
|
||||
struct ccw_device *cdev;
|
||||
struct subchannel *sch;
|
||||
int ret;
|
||||
|
||||
priv = container_of(work, struct ccw_device_private, kick_work);
|
||||
cdev = priv->cdev;
|
||||
sch = to_subchannel(cdev->dev.parent);
|
||||
|
||||
ccw_device_unregister(cdev);
|
||||
PREPARE_WORK(&cdev->private->kick_work,
|
||||
ccw_device_add_changed);
|
||||
queue_work(ccw_device_work, &cdev->private->kick_work);
|
||||
if (test_bit(1, &cdev->private->registered)) {
|
||||
device_release_driver(&cdev->dev);
|
||||
ret = device_attach(&cdev->dev);
|
||||
WARN_ON(ret == -ENODEV);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -80,7 +80,7 @@ void io_subchannel_init_config(struct subchannel *sch);
|
|||
|
||||
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 *);
|
||||
int ccw_device_is_orphan(struct ccw_device *);
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ ccw_device_handle_oper(struct ccw_device *cdev)
|
|||
cdev->id.dev_type != cdev->private->senseid.dev_type ||
|
||||
cdev->id.dev_model != cdev->private->senseid.dev_model) {
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
@ -366,7 +366,7 @@ static void ccw_device_oper_notify(struct ccw_device *cdev)
|
|||
}
|
||||
/* Driver doesn't want device back. */
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user