mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-17 01:04:19 +08:00
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:
parent
279b8f9a0f
commit
1bc6664bdf
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user