aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/device_fsm.c
diff options
context:
space:
mode:
authorPeter Oberparleiter <peter.oberparleiter@de.ibm.com>2009-12-07 06:51:32 -0500
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2009-12-07 06:51:32 -0500
commitd7d12ef2befac4fed0dccaddff11338b654804df (patch)
tree1563b299e609024844affbc3ebba99c0718db238 /drivers/s390/cio/device_fsm.c
parent52ef0608e3ee4a511725e443c4b572fece22b353 (diff)
[S390] cio: make steal lock procedure more robust
An Unconditional Reserve + Release operation (steal lock) for a boxed device may fail when encountering special error cases (e.g. unit checks or path errors). Fix this by using the more robust ccw_request infrastructure for performing the steal lock CCW program. Signed-off-by: Peter Oberparleiter <peter.oberparleiter@de.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.c55
1 files changed, 26 insertions, 29 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 8d565ff85e43..7d42417bc2c7 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -641,6 +641,23 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event)
641} 641}
642 642
643/* 643/*
644 * Handle path verification event in boxed state.
645 */
646static void ccw_device_boxed_verify(struct ccw_device *cdev,
647 enum dev_event dev_event)
648{
649 struct subchannel *sch = to_subchannel(cdev->dev.parent);
650
651 if (cdev->online) {
652 if (cio_enable_subchannel(sch, (u32) (addr_t) sch))
653 ccw_device_done(cdev, DEV_STATE_NOT_OPER);
654 else
655 ccw_device_online_verify(cdev, dev_event);
656 } else
657 css_schedule_eval(sch->schid);
658}
659
660/*
644 * Got an interrupt for a normal io (state online). 661 * Got an interrupt for a normal io (state online).
645 */ 662 */
646static void 663static void
@@ -817,32 +834,6 @@ ccw_device_delay_verify(struct ccw_device *cdev, enum dev_event dev_event)
817} 834}
818 835
819static void 836static void
820ccw_device_stlck_done(struct ccw_device *cdev, enum dev_event dev_event)
821{
822 struct irb *irb;
823
824 switch (dev_event) {
825 case DEV_EVENT_INTERRUPT:
826 irb = (struct irb *) __LC_IRB;
827 /* Check for unsolicited interrupt. */
828 if ((scsw_stctl(&irb->scsw) ==
829 (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) &&
830 (!scsw_cc(&irb->scsw)))
831 /* FIXME: we should restart stlck here, but this
832 * is extremely unlikely ... */
833 goto out_wakeup;
834
835 ccw_device_accumulate_irb(cdev, irb);
836 /* We don't care about basic sense etc. */
837 break;
838 default: /* timeout */
839 break;
840 }
841out_wakeup:
842 wake_up(&cdev->private->wait_q);
843}
844
845static void
846ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event) 837ccw_device_start_id(struct ccw_device *cdev, enum dev_event dev_event)
847{ 838{
848 struct subchannel *sch; 839 struct subchannel *sch;
@@ -1010,9 +1001,9 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
1010 }, 1001 },
1011 [DEV_STATE_BOXED] = { 1002 [DEV_STATE_BOXED] = {
1012 [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, 1003 [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper,
1013 [DEV_EVENT_INTERRUPT] = ccw_device_stlck_done, 1004 [DEV_EVENT_INTERRUPT] = ccw_device_nop,
1014 [DEV_EVENT_TIMEOUT] = ccw_device_stlck_done, 1005 [DEV_EVENT_TIMEOUT] = ccw_device_nop,
1015 [DEV_EVENT_VERIFY] = ccw_device_nop, 1006 [DEV_EVENT_VERIFY] = ccw_device_boxed_verify,
1016 }, 1007 },
1017 /* states to wait for i/o completion before doing something */ 1008 /* states to wait for i/o completion before doing something */
1018 [DEV_STATE_TIMEOUT_KILL] = { 1009 [DEV_STATE_TIMEOUT_KILL] = {
@@ -1052,6 +1043,12 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = {
1052 [DEV_EVENT_TIMEOUT] = ccw_device_update_cmfblock, 1043 [DEV_EVENT_TIMEOUT] = ccw_device_update_cmfblock,
1053 [DEV_EVENT_VERIFY] = ccw_device_update_cmfblock, 1044 [DEV_EVENT_VERIFY] = ccw_device_update_cmfblock,
1054 }, 1045 },
1046 [DEV_STATE_STEAL_LOCK] = {
1047 [DEV_EVENT_NOTOPER] = ccw_device_request_event,
1048 [DEV_EVENT_INTERRUPT] = ccw_device_request_event,
1049 [DEV_EVENT_TIMEOUT] = ccw_device_request_event,
1050 [DEV_EVENT_VERIFY] = ccw_device_nop,
1051 },
1055}; 1052};
1056 1053
1057EXPORT_SYMBOL_GPL(ccw_device_set_timeout); 1054EXPORT_SYMBOL_GPL(ccw_device_set_timeout);