diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2009-06-16 04:30:20 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-06-16 04:31:08 -0400 |
commit | 823d494ac11111064cf39abd4178ce299414c771 (patch) | |
tree | ede15540ad89c3412f16c24770408a4c34cc032c /drivers/s390/cio/device_fsm.c | |
parent | 03347e2592078a90df818670fddf97a33eec70fb (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.c | 96 |
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 | ||
180 | static int | 180 | void ccw_device_update_sense_data(struct ccw_device *cdev) |
181 | ccw_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); | 189 | int 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 | |||
233 | ccw_device_recog_done(struct ccw_device *cdev, int state) | 225 | ccw_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) |