Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Gerald Schaefer and committed by
Martin Schwidefsky
c369527f 2b1e3e55

+115 -17
+115 -17
drivers/s390/block/dcssblk.c
··· 14 14 #include <linux/init.h> 15 15 #include <linux/slab.h> 16 16 #include <linux/blkdev.h> 17 - #include <asm/extmem.h> 18 - #include <asm/io.h> 19 17 #include <linux/completion.h> 20 18 #include <linux/interrupt.h> 19 + #include <linux/platform_device.h> 20 + #include <asm/extmem.h> 21 + #include <asm/io.h> 21 22 22 23 #define DCSSBLK_NAME "dcssblk" 23 24 #define DCSSBLK_MINORS_PER_DISK 1 ··· 941 940 } 942 941 943 942 /* 943 + * Suspend / Resume 944 + */ 945 + static int dcssblk_freeze(struct device *dev) 946 + { 947 + struct dcssblk_dev_info *dev_info; 948 + int rc = 0; 949 + 950 + list_for_each_entry(dev_info, &dcssblk_devices, lh) { 951 + switch (dev_info->segment_type) { 952 + case SEG_TYPE_SR: 953 + case SEG_TYPE_ER: 954 + case SEG_TYPE_SC: 955 + if (!dev_info->is_shared) 956 + rc = -EINVAL; 957 + break; 958 + default: 959 + rc = -EINVAL; 960 + break; 961 + } 962 + if (rc) 963 + break; 964 + } 965 + if (rc) 966 + pr_err("Suspend failed because device %s is writeable.\n", 967 + dev_info->segment_name); 968 + return rc; 969 + } 970 + 971 + static int dcssblk_restore(struct device *dev) 972 + { 973 + struct dcssblk_dev_info *dev_info; 974 + struct segment_info *entry; 975 + unsigned long start, end; 976 + int rc = 0; 977 + 978 + list_for_each_entry(dev_info, &dcssblk_devices, lh) { 979 + list_for_each_entry(entry, &dev_info->seg_list, lh) { 980 + segment_unload(entry->segment_name); 981 + rc = segment_load(entry->segment_name, SEGMENT_SHARED, 982 + &start, &end); 983 + if (rc < 0) { 984 + // TODO in_use check ? 985 + segment_warning(rc, entry->segment_name); 986 + goto out_panic; 987 + } 988 + if (start != entry->start || end != entry->end) { 989 + pr_err("Mismatch of start / end address after " 990 + "resuming device %s\n", 991 + entry->segment_name); 992 + goto out_panic; 993 + } 994 + } 995 + } 996 + return 0; 997 + out_panic: 998 + panic("fatal dcssblk resume error\n"); 999 + } 1000 + 1001 + static int dcssblk_thaw(struct device *dev) 1002 + { 1003 + return 0; 1004 + } 1005 + 1006 + static struct dev_pm_ops dcssblk_pm_ops = { 1007 + .freeze = dcssblk_freeze, 1008 + .thaw = dcssblk_thaw, 1009 + .restore = dcssblk_restore, 1010 + }; 1011 + 1012 + static struct platform_driver dcssblk_pdrv = { 1013 + .driver = { 1014 + .name = "dcssblk", 1015 + .owner = THIS_MODULE, 1016 + .pm = &dcssblk_pm_ops, 1017 + }, 1018 + }; 1019 + 1020 + static struct platform_device *dcssblk_pdev; 1021 + 1022 + 1023 + /* 944 1024 * The init/exit functions. 945 1025 */ 946 1026 static void __exit 947 1027 dcssblk_exit(void) 948 1028 { 1029 + platform_device_unregister(dcssblk_pdev); 1030 + platform_driver_unregister(&dcssblk_pdrv); 949 1031 root_device_unregister(dcssblk_root_dev); 950 1032 unregister_blkdev(dcssblk_major, DCSSBLK_NAME); 951 1033 } ··· 1038 954 { 1039 955 int rc; 1040 956 957 + rc = platform_driver_register(&dcssblk_pdrv); 958 + if (rc) 959 + return rc; 960 + 961 + dcssblk_pdev = platform_device_register_simple("dcssblk", -1, NULL, 962 + 0); 963 + if (IS_ERR(dcssblk_pdev)) { 964 + rc = PTR_ERR(dcssblk_pdev); 965 + goto out_pdrv; 966 + } 967 + 1041 968 dcssblk_root_dev = root_device_register("dcssblk"); 1042 - if (IS_ERR(dcssblk_root_dev)) 1043 - return PTR_ERR(dcssblk_root_dev); 969 + if (IS_ERR(dcssblk_root_dev)) { 970 + rc = PTR_ERR(dcssblk_root_dev); 971 + goto out_pdev; 972 + } 1044 973 rc = device_create_file(dcssblk_root_dev, &dev_attr_add); 1045 - if (rc) { 1046 - root_device_unregister(dcssblk_root_dev); 1047 - return rc; 1048 - } 974 + if (rc) 975 + goto out_root; 1049 976 rc = device_create_file(dcssblk_root_dev, &dev_attr_remove); 1050 - if (rc) { 1051 - root_device_unregister(dcssblk_root_dev); 1052 - return rc; 1053 - } 977 + if (rc) 978 + goto out_root; 1054 979 rc = register_blkdev(0, DCSSBLK_NAME); 1055 - if (rc < 0) { 1056 - root_device_unregister(dcssblk_root_dev); 1057 - return rc; 1058 - } 980 + if (rc < 0) 981 + goto out_root; 1059 982 dcssblk_major = rc; 1060 983 init_rwsem(&dcssblk_devices_sem); 1061 984 1062 985 dcssblk_check_params(); 1063 - 1064 986 return 0; 987 + 988 + out_root: 989 + root_device_unregister(dcssblk_root_dev); 990 + out_pdev: 991 + platform_device_unregister(dcssblk_pdev); 992 + out_pdrv: 993 + platform_driver_unregister(&dcssblk_pdrv); 994 + return rc; 1065 995 } 1066 996 1067 997 module_init(dcssblk_init);