aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device_fsm.c
diff options
context:
space:
mode:
authorSebastian Ott <sebott@linux.vnet.ibm.com>2009-06-16 04:30:20 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-16 04:31:08 -0400
commit823d494ac11111064cf39abd4178ce299414c771 (patch)
treeede15540ad89c3412f16c24770408a4c34cc032c /drivers/s390/cio/device_fsm.c
parent03347e2592078a90df818670fddf97a33eec70fb (diff)
[S390] pm: ccw bus power management callbacks
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/device_fsm.c')
-rw-r--r--drivers/s390/cio/device_fsm.c96
1 files changed, 43 insertions, 53 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index e46049261561..3db88c52d287 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -177,29 +177,21 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
177 panic("Can't stop i/o on subchannel.\n"); 177 panic("Can't stop i/o on subchannel.\n");
178} 178}
179 179
180static int 180void ccw_device_update_sense_data(struct ccw_device *cdev)
181ccw_device_handle_oper(struct ccw_device *cdev)
182{ 181{
183 struct subchannel *sch; 182 memset(&cdev->id, 0, sizeof(cdev->id));
183 cdev->id.cu_type = cdev->private->senseid.cu_type;
184 cdev->id.cu_model = cdev->private->senseid.cu_model;
185 cdev->id.dev_type = cdev->private->senseid.dev_type;
186 cdev->id.dev_model = cdev->private->senseid.dev_model;
187}
184 188
185 sch = to_subchannel(cdev->dev.parent); 189int ccw_device_test_sense_data(struct ccw_device *cdev)
186 cdev->private->flags.recog_done = 1; 190{
187 /* 191 return cdev->id.cu_type == cdev->private->senseid.cu_type &&
188 * Check if cu type and device type still match. If 192 cdev->id.cu_model == cdev->private->senseid.cu_model &&
189 * not, it is certainly another device and we have to 193 cdev->id.dev_type == cdev->private->senseid.dev_type &&
190 * de- and re-register. 194 cdev->id.dev_model == cdev->private->senseid.dev_model;
191 */
192 if (cdev->id.cu_type != cdev->private->senseid.cu_type ||
193 cdev->id.cu_model != cdev->private->senseid.cu_model ||
194 cdev->id.dev_type != cdev->private->senseid.dev_type ||
195 cdev->id.dev_model != cdev->private->senseid.dev_model) {
196 PREPARE_WORK(&cdev->private->kick_work,
197 ccw_device_do_unbind_bind);
198 queue_work(ccw_device_work, &cdev->private->kick_work);
199 return 0;
200 }
201 cdev->private->flags.donotify = 1;
202 return 1;
203} 195}
204 196
205/* 197/*
@@ -233,7 +225,7 @@ static void
233ccw_device_recog_done(struct ccw_device *cdev, int state) 225ccw_device_recog_done(struct ccw_device *cdev, int state)
234{ 226{
235 struct subchannel *sch; 227 struct subchannel *sch;
236 int notify, old_lpm, same_dev; 228 int old_lpm;
237 229
238 sch = to_subchannel(cdev->dev.parent); 230 sch = to_subchannel(cdev->dev.parent);
239 231
@@ -263,8 +255,12 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
263 wake_up(&cdev->private->wait_q); 255 wake_up(&cdev->private->wait_q);
264 return; 256 return;
265 } 257 }
266 notify = 0; 258 if (cdev->private->flags.resuming) {
267 same_dev = 0; /* Keep the compiler quiet... */ 259 cdev->private->state = state;
260 cdev->private->flags.recog_done = 1;
261 wake_up(&cdev->private->wait_q);
262 return;
263 }
268 switch (state) { 264 switch (state) {
269 case DEV_STATE_NOT_OPER: 265 case DEV_STATE_NOT_OPER:
270 CIO_MSG_EVENT(2, "SenseID : unknown device %04x on " 266 CIO_MSG_EVENT(2, "SenseID : unknown device %04x on "
@@ -273,34 +269,31 @@ ccw_device_recog_done(struct ccw_device *cdev, int state)
273 sch->schid.ssid, sch->schid.sch_no); 269 sch->schid.ssid, sch->schid.sch_no);
274 break; 270 break;
275 case DEV_STATE_OFFLINE: 271 case DEV_STATE_OFFLINE:
276 if (cdev->online) { 272 if (!cdev->online) {
277 same_dev = ccw_device_handle_oper(cdev); 273 ccw_device_update_sense_data(cdev);
278 notify = 1; 274 /* Issue device info message. */
275 CIO_MSG_EVENT(4, "SenseID : device 0.%x.%04x reports: "
276 "CU Type/Mod = %04X/%02X, Dev Type/Mod "
277 "= %04X/%02X\n",
278 cdev->private->dev_id.ssid,
279 cdev->private->dev_id.devno,
280 cdev->id.cu_type, cdev->id.cu_model,
281 cdev->id.dev_type, cdev->id.dev_model);
282 break;
279 } 283 }
280 /* fill out sense information */ 284 cdev->private->state = DEV_STATE_OFFLINE;
281 memset(&cdev->id, 0, sizeof(cdev->id)); 285 cdev->private->flags.recog_done = 1;
282 cdev->id.cu_type = cdev->private->senseid.cu_type; 286 if (ccw_device_test_sense_data(cdev)) {
283 cdev->id.cu_model = cdev->private->senseid.cu_model; 287 cdev->private->flags.donotify = 1;
284 cdev->id.dev_type = cdev->private->senseid.dev_type; 288 ccw_device_online(cdev);
285 cdev->id.dev_model = cdev->private->senseid.dev_model; 289 wake_up(&cdev->private->wait_q);
286 if (notify) { 290 } else {
287 cdev->private->state = DEV_STATE_OFFLINE; 291 ccw_device_update_sense_data(cdev);
288 if (same_dev) { 292 PREPARE_WORK(&cdev->private->kick_work,
289 /* Get device online again. */ 293 ccw_device_do_unbind_bind);
290 ccw_device_online(cdev); 294 queue_work(ccw_device_work, &cdev->private->kick_work);
291 wake_up(&cdev->private->wait_q);
292 }
293 return;
294 } 295 }
295 /* Issue device info message. */ 296 return;
296 CIO_MSG_EVENT(4, "SenseID : device 0.%x.%04x reports: "
297 "CU Type/Mod = %04X/%02X, Dev Type/Mod = "
298 "%04X/%02X\n",
299 cdev->private->dev_id.ssid,
300 cdev->private->dev_id.devno,
301 cdev->id.cu_type, cdev->id.cu_model,
302 cdev->id.dev_type, cdev->id.dev_model);
303 break;
304 case DEV_STATE_BOXED: 297 case DEV_STATE_BOXED:
305 CIO_MSG_EVENT(0, "SenseID : boxed device %04x on " 298 CIO_MSG_EVENT(0, "SenseID : boxed device %04x on "
306 " subchannel 0.%x.%04x\n", 299 " subchannel 0.%x.%04x\n",
@@ -502,9 +495,6 @@ ccw_device_recognition(struct ccw_device *cdev)
502 struct subchannel *sch; 495 struct subchannel *sch;
503 int ret; 496 int ret;
504 497
505 if ((cdev->private->state != DEV_STATE_NOT_OPER) &&
506 (cdev->private->state != DEV_STATE_BOXED))
507 return -EINVAL;
508 sch = to_subchannel(cdev->dev.parent); 498 sch = to_subchannel(cdev->dev.parent);
509 ret = cio_enable_subchannel(sch, (u32)(addr_t)sch); 499 ret = cio_enable_subchannel(sch, (u32)(addr_t)sch);
510 if (ret != 0) 500 if (ret != 0)