[S390] pm: dcssblk power management callbacks.
Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
2b1e3e5558
commit
c369527f18
|
@ -14,10 +14,11 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <asm/extmem.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <asm/extmem.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define DCSSBLK_NAME "dcssblk"
|
||||
#define DCSSBLK_MINORS_PER_DISK 1
|
||||
|
@ -939,12 +940,95 @@ dcssblk_check_params(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Suspend / Resume
|
||||
*/
|
||||
static int dcssblk_freeze(struct device *dev)
|
||||
{
|
||||
struct dcssblk_dev_info *dev_info;
|
||||
int rc = 0;
|
||||
|
||||
list_for_each_entry(dev_info, &dcssblk_devices, lh) {
|
||||
switch (dev_info->segment_type) {
|
||||
case SEG_TYPE_SR:
|
||||
case SEG_TYPE_ER:
|
||||
case SEG_TYPE_SC:
|
||||
if (!dev_info->is_shared)
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
if (rc)
|
||||
break;
|
||||
}
|
||||
if (rc)
|
||||
pr_err("Suspend failed because device %s is writeable.\n",
|
||||
dev_info->segment_name);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dcssblk_restore(struct device *dev)
|
||||
{
|
||||
struct dcssblk_dev_info *dev_info;
|
||||
struct segment_info *entry;
|
||||
unsigned long start, end;
|
||||
int rc = 0;
|
||||
|
||||
list_for_each_entry(dev_info, &dcssblk_devices, lh) {
|
||||
list_for_each_entry(entry, &dev_info->seg_list, lh) {
|
||||
segment_unload(entry->segment_name);
|
||||
rc = segment_load(entry->segment_name, SEGMENT_SHARED,
|
||||
&start, &end);
|
||||
if (rc < 0) {
|
||||
// TODO in_use check ?
|
||||
segment_warning(rc, entry->segment_name);
|
||||
goto out_panic;
|
||||
}
|
||||
if (start != entry->start || end != entry->end) {
|
||||
pr_err("Mismatch of start / end address after "
|
||||
"resuming device %s\n",
|
||||
entry->segment_name);
|
||||
goto out_panic;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
out_panic:
|
||||
panic("fatal dcssblk resume error\n");
|
||||
}
|
||||
|
||||
static int dcssblk_thaw(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dev_pm_ops dcssblk_pm_ops = {
|
||||
.freeze = dcssblk_freeze,
|
||||
.thaw = dcssblk_thaw,
|
||||
.restore = dcssblk_restore,
|
||||
};
|
||||
|
||||
static struct platform_driver dcssblk_pdrv = {
|
||||
.driver = {
|
||||
.name = "dcssblk",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &dcssblk_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *dcssblk_pdev;
|
||||
|
||||
|
||||
/*
|
||||
* The init/exit functions.
|
||||
*/
|
||||
static void __exit
|
||||
dcssblk_exit(void)
|
||||
{
|
||||
platform_device_unregister(dcssblk_pdev);
|
||||
platform_driver_unregister(&dcssblk_pdrv);
|
||||
root_device_unregister(dcssblk_root_dev);
|
||||
unregister_blkdev(dcssblk_major, DCSSBLK_NAME);
|
||||
}
|
||||
|
@ -954,30 +1038,44 @@ dcssblk_init(void)
|
|||
{
|
||||
int rc;
|
||||
|
||||
rc = platform_driver_register(&dcssblk_pdrv);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
dcssblk_pdev = platform_device_register_simple("dcssblk", -1, NULL,
|
||||
0);
|
||||
if (IS_ERR(dcssblk_pdev)) {
|
||||
rc = PTR_ERR(dcssblk_pdev);
|
||||
goto out_pdrv;
|
||||
}
|
||||
|
||||
dcssblk_root_dev = root_device_register("dcssblk");
|
||||
if (IS_ERR(dcssblk_root_dev))
|
||||
return PTR_ERR(dcssblk_root_dev);
|
||||
if (IS_ERR(dcssblk_root_dev)) {
|
||||
rc = PTR_ERR(dcssblk_root_dev);
|
||||
goto out_pdev;
|
||||
}
|
||||
rc = device_create_file(dcssblk_root_dev, &dev_attr_add);
|
||||
if (rc) {
|
||||
root_device_unregister(dcssblk_root_dev);
|
||||
return rc;
|
||||
}
|
||||
if (rc)
|
||||
goto out_root;
|
||||
rc = device_create_file(dcssblk_root_dev, &dev_attr_remove);
|
||||
if (rc) {
|
||||
root_device_unregister(dcssblk_root_dev);
|
||||
return rc;
|
||||
}
|
||||
if (rc)
|
||||
goto out_root;
|
||||
rc = register_blkdev(0, DCSSBLK_NAME);
|
||||
if (rc < 0) {
|
||||
root_device_unregister(dcssblk_root_dev);
|
||||
return rc;
|
||||
}
|
||||
if (rc < 0)
|
||||
goto out_root;
|
||||
dcssblk_major = rc;
|
||||
init_rwsem(&dcssblk_devices_sem);
|
||||
|
||||
dcssblk_check_params();
|
||||
|
||||
return 0;
|
||||
|
||||
out_root:
|
||||
root_device_unregister(dcssblk_root_dev);
|
||||
out_pdev:
|
||||
platform_device_unregister(dcssblk_pdev);
|
||||
out_pdrv:
|
||||
platform_driver_unregister(&dcssblk_pdrv);
|
||||
return rc;
|
||||
}
|
||||
|
||||
module_init(dcssblk_init);
|
||||
|
|
Loading…
Reference in New Issue