Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+7 −20
Original line number Original line Diff line number Diff line
@@ -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
+1 −1
Original line number Original line Diff line number Diff line
@@ -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 *);


+2 −2
Original line number Original line Diff line number Diff line
@@ -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)
	}
	}
	/* 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);
}
}