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

Commit 1bc6664b authored by Sebastian Ott's avatar Sebastian Ott Committed by Martin Schwidefsky
Browse files

s390/cio: use device_lock during cmb activation



Hold the device_lock during [de]activation of the channel measurement
block to synchronize concurrent usage of these functions.

Signed-off-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Reviewed-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 279b8f9a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
struct ccw_device;
extern int enable_cmf(struct ccw_device *cdev);
extern int disable_cmf(struct ccw_device *cdev);
extern int __disable_cmf(struct ccw_device *cdev);
extern u64 cmf_read(struct ccw_device *cdev, int index);
extern int cmf_readall(struct ccw_device *cdev, struct cmbdata *data);

+37 −12
Original line number Diff line number Diff line
@@ -1226,20 +1226,46 @@ int enable_cmf(struct ccw_device *cdev)
{
	int ret;

	device_lock(&cdev->dev);
	ret = cmbops->alloc(cdev);
	cmbops->reset(cdev);
	if (ret)
		return ret;
		goto out;
	cmbops->reset(cdev);
	ret = sysfs_create_group(&cdev->dev.kobj, cmbops->attr_group);
	if (ret) {
		cmbops->free(cdev);
		goto out;
	}
	ret = cmbops->set(cdev, 2);
	if (ret) {
		sysfs_remove_group(&cdev->dev.kobj, cmbops->attr_group);
		cmbops->free(cdev);
	}
out:
	device_unlock(&cdev->dev);
	return ret;
}
	ret = sysfs_create_group(&cdev->dev.kobj, cmbops->attr_group);
	if (!ret)
		return 0;
	cmbops->set(cdev, 0);  //FIXME: this can fail

/**
 * __disable_cmf() - switch off the channel measurement for a specific device
 *  @cdev:	The ccw device to be disabled
 *
 *  Returns %0 for success or a negative error value.
 *
 *  Context:
 *    non-atomic, device_lock() held.
 */
int __disable_cmf(struct ccw_device *cdev)
{
	int ret;

	ret = cmbops->set(cdev, 0);
	if (ret)
		return ret;

	sysfs_remove_group(&cdev->dev.kobj, cmbops->attr_group);
	cmbops->free(cdev);

	return ret;
}

@@ -1256,11 +1282,10 @@ int disable_cmf(struct ccw_device *cdev)
{
	int ret;

	ret = cmbops->set(cdev, 0);
	if (ret)
		return ret;
	cmbops->free(cdev);
	sysfs_remove_group(&cdev->dev.kobj, cmbops->attr_group);
	device_lock(&cdev->dev);
	ret = __disable_cmf(cdev);
	device_unlock(&cdev->dev);

	return ret;
}

+1 −1
Original line number Diff line number Diff line
@@ -1797,7 +1797,7 @@ static void ccw_device_shutdown(struct device *dev)
	cdev = to_ccwdev(dev);
	if (cdev->drv && cdev->drv->shutdown)
		cdev->drv->shutdown(cdev);
	disable_cmf(cdev);
	__disable_cmf(cdev);
}

static int ccw_device_pm_prepare(struct device *dev)