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: Sebastian Ott <sebott@linux.vnet.ibm.com>
Reviewed-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Sebastian Ott 2015-09-15 13:11:42 +02:00 committed by Martin Schwidefsky
parent 279b8f9a0f
commit 1bc6664bdf
3 changed files with 40 additions and 14 deletions

View File

@ -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);

View File

@ -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;
ret = cmbops->set(cdev, 2);
goto out;
cmbops->reset(cdev);
ret = sysfs_create_group(&cdev->dev.kobj, cmbops->attr_group);
if (ret) {
cmbops->free(cdev);
return ret;
goto out;
}
ret = sysfs_create_group(&cdev->dev.kobj, cmbops->attr_group);
if (!ret)
return 0;
cmbops->set(cdev, 0); //FIXME: this can fail
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;
}
/**
* __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;
}

View File

@ -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)