aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/smsgiucv.c
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-16 04:30:46 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-16 04:31:20 -0400
commit6a1d96dced593bc17d7a17fdb93c99b275e71eba (patch)
tree69ac1bb8a52d8b537281118b24617076ff08ac3f /drivers/s390/net/smsgiucv.c
parent0259162ecd083f1ce0f6022e669f393330b06f4d (diff)
[S390] pm: smsgiucv power management callbacks.
Create dummy iucv-device to get control when the system is suspended and resumed. Server the smsg iucv path on suspend, reestablish the path on resume. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/net/smsgiucv.c')
-rw-r--r--drivers/s390/net/smsgiucv.c63
1 files changed, 60 insertions, 3 deletions
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index 164e090c2625..e76a320d373b 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -1,7 +1,8 @@
1/* 1/*
2 * IUCV special message driver 2 * IUCV special message driver
3 * 3 *
4 * Copyright 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation 4 * Copyright IBM Corp. 2003, 2009
5 *
5 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) 6 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
@@ -40,6 +41,8 @@ MODULE_AUTHOR
40MODULE_DESCRIPTION ("Linux for S/390 IUCV special message driver"); 41MODULE_DESCRIPTION ("Linux for S/390 IUCV special message driver");
41 42
42static struct iucv_path *smsg_path; 43static struct iucv_path *smsg_path;
44/* dummy device used as trigger for PM functions */
45static struct device *smsg_dev;
43 46
44static DEFINE_SPINLOCK(smsg_list_lock); 47static DEFINE_SPINLOCK(smsg_list_lock);
45static LIST_HEAD(smsg_list); 48static LIST_HEAD(smsg_list);
@@ -132,14 +135,51 @@ void smsg_unregister_callback(char *prefix,
132 kfree(cb); 135 kfree(cb);
133} 136}
134 137
138static int smsg_pm_freeze(struct device *dev)
139{
140#ifdef CONFIG_PM_DEBUG
141 printk(KERN_WARNING "smsg_pm_freeze\n");
142#endif
143 if (smsg_path)
144 iucv_path_sever(smsg_path, NULL);
145 return 0;
146}
147
148static int smsg_pm_restore_thaw(struct device *dev)
149{
150 int rc;
151
152#ifdef CONFIG_PM_DEBUG
153 printk(KERN_WARNING "smsg_pm_restore_thaw\n");
154#endif
155 if (smsg_path) {
156 memset(smsg_path, 0, sizeof(*smsg_path));
157 smsg_path->msglim = 255;
158 smsg_path->flags = 0;
159 rc = iucv_path_connect(smsg_path, &smsg_handler, "*MSG ",
160 NULL, NULL, NULL);
161 printk(KERN_ERR "iucv_path_connect returned with rc %i\n", rc);
162 }
163 return 0;
164}
165
166static struct dev_pm_ops smsg_pm_ops = {
167 .freeze = smsg_pm_freeze,
168 .thaw = smsg_pm_restore_thaw,
169 .restore = smsg_pm_restore_thaw,
170};
171
135static struct device_driver smsg_driver = { 172static struct device_driver smsg_driver = {
173 .owner = THIS_MODULE,
136 .name = "SMSGIUCV", 174 .name = "SMSGIUCV",
137 .bus = &iucv_bus, 175 .bus = &iucv_bus,
176 .pm = &smsg_pm_ops,
138}; 177};
139 178
140static void __exit smsg_exit(void) 179static void __exit smsg_exit(void)
141{ 180{
142 cpcmd("SET SMSG IUCV", NULL, 0, NULL); 181 cpcmd("SET SMSG IUCV", NULL, 0, NULL);
182 device_unregister(smsg_dev);
143 iucv_unregister(&smsg_handler, 1); 183 iucv_unregister(&smsg_handler, 1);
144 driver_unregister(&smsg_driver); 184 driver_unregister(&smsg_driver);
145} 185}
@@ -166,12 +206,29 @@ static int __init smsg_init(void)
166 rc = iucv_path_connect(smsg_path, &smsg_handler, "*MSG ", 206 rc = iucv_path_connect(smsg_path, &smsg_handler, "*MSG ",
167 NULL, NULL, NULL); 207 NULL, NULL, NULL);
168 if (rc) 208 if (rc)
169 goto out_free; 209 goto out_free_path;
210 smsg_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
211 if (!smsg_dev) {
212 rc = -ENOMEM;
213 goto out_free_path;
214 }
215 dev_set_name(smsg_dev, "smsg_iucv");
216 smsg_dev->bus = &iucv_bus;
217 smsg_dev->parent = iucv_root;
218 smsg_dev->release = (void (*)(struct device *))kfree;
219 smsg_dev->driver = &smsg_driver;
220 rc = device_register(smsg_dev);
221 if (rc)
222 goto out_free_dev;
223
170 cpcmd("SET SMSG IUCV", NULL, 0, NULL); 224 cpcmd("SET SMSG IUCV", NULL, 0, NULL);
171 return 0; 225 return 0;
172 226
173out_free: 227out_free_dev:
228 kfree(smsg_dev);
229out_free_path:
174 iucv_path_free(smsg_path); 230 iucv_path_free(smsg_path);
231 smsg_path = NULL;
175out_register: 232out_register:
176 iucv_unregister(&smsg_handler, 1); 233 iucv_unregister(&smsg_handler, 1);
177out_driver: 234out_driver: