aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device_fsm.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/s390/cio/device_fsm.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/s390/cio/device_fsm.c')
-rw-r--r--drivers/s390/cio/device_fsm.c53
1 files changed, 44 insertions, 9 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index c9b852647f01..52c233fa2b12 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -174,7 +174,10 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev)
174 ret = cio_clear (sch); 174 ret = cio_clear (sch);
175 return (ret == 0) ? -EBUSY : ret; 175 return (ret == 0) ? -EBUSY : ret;
176 } 176 }
177 panic("Can't stop i/o on subchannel.\n"); 177 /* Function was unsuccessful */
178 CIO_MSG_EVENT(0, "0.%x.%04x: could not stop I/O\n",
179 cdev->private->dev_id.ssid, cdev->private->dev_id.devno);
180 return -EIO;
178} 181}
179 182
180void ccw_device_update_sense_data(struct ccw_device *cdev) 183void ccw_device_update_sense_data(struct ccw_device *cdev)
@@ -315,7 +318,7 @@ ccw_device_sense_id_done(struct ccw_device *cdev, int err)
315 318
316/** 319/**
317 * ccw_device_notify() - inform the device's driver about an event 320 * ccw_device_notify() - inform the device's driver about an event
318 * @cdev: device for which an event occured 321 * @cdev: device for which an event occurred
319 * @event: event that occurred 322 * @event: event that occurred
320 * 323 *
321 * Returns: 324 * Returns:
@@ -349,9 +352,13 @@ out:
349 352
350static void ccw_device_oper_notify(struct ccw_device *cdev) 353static void ccw_device_oper_notify(struct ccw_device *cdev)
351{ 354{
355 struct subchannel *sch = to_subchannel(cdev->dev.parent);
356
352 if (ccw_device_notify(cdev, CIO_OPER) == NOTIFY_OK) { 357 if (ccw_device_notify(cdev, CIO_OPER) == NOTIFY_OK) {
353 /* Reenable channel measurements, if needed. */ 358 /* Reenable channel measurements, if needed. */
354 ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF); 359 ccw_device_sched_todo(cdev, CDEV_TODO_ENABLE_CMF);
360 /* Save indication for new paths. */
361 cdev->private->path_new_mask = sch->vpm;
355 return; 362 return;
356 } 363 }
357 /* Driver doesn't want device back. */ 364 /* Driver doesn't want device back. */
@@ -401,9 +408,10 @@ ccw_device_done(struct ccw_device *cdev, int state)
401 CIO_MSG_EVENT(0, "Disconnected device %04x on subchannel " 408 CIO_MSG_EVENT(0, "Disconnected device %04x on subchannel "
402 "%04x\n", cdev->private->dev_id.devno, 409 "%04x\n", cdev->private->dev_id.devno,
403 sch->schid.sch_no); 410 sch->schid.sch_no);
404 if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK) 411 if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK) {
412 cdev->private->state = DEV_STATE_NOT_OPER;
405 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); 413 ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
406 else 414 } else
407 ccw_device_set_disconnected(cdev); 415 ccw_device_set_disconnected(cdev);
408 cdev->private->flags.donotify = 0; 416 cdev->private->flags.donotify = 0;
409 break; 417 break;
@@ -462,6 +470,32 @@ static void ccw_device_request_event(struct ccw_device *cdev, enum dev_event e)
462 } 470 }
463} 471}
464 472
473static void ccw_device_report_path_events(struct ccw_device *cdev)
474{
475 struct subchannel *sch = to_subchannel(cdev->dev.parent);
476 int path_event[8];
477 int chp, mask;
478
479 for (chp = 0, mask = 0x80; chp < 8; chp++, mask >>= 1) {
480 path_event[chp] = PE_NONE;
481 if (mask & cdev->private->path_gone_mask & ~(sch->vpm))
482 path_event[chp] |= PE_PATH_GONE;
483 if (mask & cdev->private->path_new_mask & sch->vpm)
484 path_event[chp] |= PE_PATH_AVAILABLE;
485 if (mask & cdev->private->pgid_reset_mask & sch->vpm)
486 path_event[chp] |= PE_PATHGROUP_ESTABLISHED;
487 }
488 if (cdev->online && cdev->drv->path_event)
489 cdev->drv->path_event(cdev, path_event);
490}
491
492static void ccw_device_reset_path_events(struct ccw_device *cdev)
493{
494 cdev->private->path_gone_mask = 0;
495 cdev->private->path_new_mask = 0;
496 cdev->private->pgid_reset_mask = 0;
497}
498
465void 499void
466ccw_device_verify_done(struct ccw_device *cdev, int err) 500ccw_device_verify_done(struct ccw_device *cdev, int err)
467{ 501{
@@ -498,6 +532,7 @@ callback:
498 &cdev->private->irb); 532 &cdev->private->irb);
499 memset(&cdev->private->irb, 0, sizeof(struct irb)); 533 memset(&cdev->private->irb, 0, sizeof(struct irb));
500 } 534 }
535 ccw_device_report_path_events(cdev);
501 break; 536 break;
502 case -ETIME: 537 case -ETIME:
503 case -EUSERS: 538 case -EUSERS:
@@ -516,6 +551,7 @@ callback:
516 ccw_device_done(cdev, DEV_STATE_NOT_OPER); 551 ccw_device_done(cdev, DEV_STATE_NOT_OPER);
517 break; 552 break;
518 } 553 }
554 ccw_device_reset_path_events(cdev);
519} 555}
520 556
521/* 557/*
@@ -653,7 +689,7 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event)
653 (scsw_stctl(&cdev->private->irb.scsw) & SCSW_STCTL_STATUS_PEND)) { 689 (scsw_stctl(&cdev->private->irb.scsw) & SCSW_STCTL_STATUS_PEND)) {
654 /* 690 /*
655 * No final status yet or final status not yet delivered 691 * No final status yet or final status not yet delivered
656 * to the device driver. Can't do path verfication now, 692 * to the device driver. Can't do path verification now,
657 * delay until final status was delivered. 693 * delay until final status was delivered.
658 */ 694 */
659 cdev->private->flags.doverify = 1; 695 cdev->private->flags.doverify = 1;
@@ -734,13 +770,14 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event)
734 int ret; 770 int ret;
735 771
736 ccw_device_set_timeout(cdev, 0); 772 ccw_device_set_timeout(cdev, 0);
773 cdev->private->iretry = 255;
737 ret = ccw_device_cancel_halt_clear(cdev); 774 ret = ccw_device_cancel_halt_clear(cdev);
738 if (ret == -EBUSY) { 775 if (ret == -EBUSY) {
739 ccw_device_set_timeout(cdev, 3*HZ); 776 ccw_device_set_timeout(cdev, 3*HZ);
740 cdev->private->state = DEV_STATE_TIMEOUT_KILL; 777 cdev->private->state = DEV_STATE_TIMEOUT_KILL;
741 return; 778 return;
742 } 779 }
743 if (ret == -ENODEV) 780 if (ret)
744 dev_fsm_event(cdev, DEV_EVENT_NOTOPER); 781 dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
745 else if (cdev->handler) 782 else if (cdev->handler)
746 cdev->handler(cdev, cdev->private->intparm, 783 cdev->handler(cdev, cdev->private->intparm,
@@ -804,9 +841,6 @@ call_handler:
804static void 841static void
805ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event) 842ccw_device_killing_irq(struct ccw_device *cdev, enum dev_event dev_event)
806{ 843{
807 struct subchannel *sch;
808
809 sch = to_subchannel(cdev->dev.parent);
810 ccw_device_set_timeout(cdev, 0); 844 ccw_device_set_timeout(cdev, 0);
811 /* Start delayed path verification. */ 845 /* Start delayed path verification. */
812 ccw_device_online_verify(cdev, 0); 846 ccw_device_online_verify(cdev, 0);
@@ -837,6 +871,7 @@ void ccw_device_kill_io(struct ccw_device *cdev)
837{ 871{
838 int ret; 872 int ret;
839 873
874 cdev->private->iretry = 255;
840 ret = ccw_device_cancel_halt_clear(cdev); 875 ret = ccw_device_cancel_halt_clear(cdev);
841 if (ret == -EBUSY) { 876 if (ret == -EBUSY) {
842 ccw_device_set_timeout(cdev, 3*HZ); 877 ccw_device_set_timeout(cdev, 3*HZ);