231 lines
7.5 KiB
Diff
231 lines
7.5 KiB
Diff
From 9c94d906621e775f005fa34583671f08000f1723 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Dan=20Hor=C3=A1k?= <dan@danny.cz>
|
|
Date: Thu, 4 Feb 2010 13:07:30 +0100
|
|
Subject: [PATCH] zipl: handle SSCH status
|
|
|
|
Description: zipl: handle status during IPL SSCH
|
|
Symptom: System enters disabled wait during IPL of DASD disk when an
|
|
unexpected status (e.g. triggered by a flashcopy operation)
|
|
is recognized on the IPL device.
|
|
Problem: Unexpected status is not handled correctly during the SSCH
|
|
portion of the IPL code.
|
|
Solution: Introduce a more robust SSCH result handling which performs
|
|
retries and clears status when encountering errors.
|
|
---
|
|
zipl/boot/common.S | 163 +++++++++++++++++++++++++++++++++++-----------------
|
|
zipl/boot/eckd2.S | 1 -
|
|
zipl/boot/fba2.S | 1 -
|
|
3 files changed, 110 insertions(+), 55 deletions(-)
|
|
|
|
diff --git a/zipl/boot/common.S b/zipl/boot/common.S
|
|
index fa45e5a..108dbbf 100644
|
|
--- a/zipl/boot/common.S
|
|
+++ b/zipl/boot/common.S
|
|
@@ -249,69 +249,126 @@ _disable_device:
|
|
.endm
|
|
|
|
.macro io_subroutines
|
|
+
|
|
+
|
|
+__LC_IO_NEW_PSW = 0x78
|
|
+__LC_SUBCHANNEL_ID = 0xb8
|
|
+
|
|
+#
|
|
+# Wait for I/O interrupt.
|
|
+#
|
|
+# Wait until status for the specified subchannel is available.
|
|
+#
|
|
+# %r2 : subchannel id
|
|
+# %r3 : address of irb
|
|
+#
|
|
+
|
|
+_wait_for_int:
|
|
+ lr %r1,%r2
|
|
+ basr %r4,0 # get base register
|
|
+0:
|
|
+ mvc __LC_IO_NEW_PSW(8),4f-0b(%r4) # set i/o new psw
|
|
+1: # wait
|
|
+ lpsw 3f-0b(%r4)
|
|
+2: # continue
|
|
+ tsch 0(%r3) # get status
|
|
+ brc 4,1b # if cc=1 goto wait
|
|
+ br %r14 # return
|
|
+ .align 8
|
|
+3:
|
|
+ .long 0x020a0000,0x80000000+1b # enabled wait psw
|
|
+4:
|
|
+ .long 0x00080000,0x80000000+2b # io new psw
|
|
+
|
|
#
|
|
# Start I/O
|
|
-# %r2 : device subchannel id
|
|
+#
|
|
+# Attempt to start I/O defined by ORB on specified subchannel. Retry I/O
|
|
+# 256 times per path (recommended error recovery procedure for IFCCs) unless
|
|
+# a permanent path error condition is indicated. Try all paths twice to try to
|
|
+# work around "link flapping" (paths going down once each in the same order as
|
|
+# they are tried). Perform CLEAR SUBCHANNEL when switching paths to clear any
|
|
+# improper subchannel status.
|
|
+#
|
|
+# %r2 : subchannel id
|
|
# %r3 : address of orb
|
|
# %r4 : address of irb
|
|
-# %r5 : retry count
|
|
#
|
|
_ssch:
|
|
- stm %r6,%r15,24(%r15)
|
|
- basr %r13,0 # base register
|
|
-0: s %r15,6f-0b(%r13) # create stack frame
|
|
- lr %r12,%r2 # save subchannel id
|
|
- lr %r11,%r3 # save orb
|
|
- lr %r10,%r4 # save irb
|
|
- lr %r9,%r5 # save retry count
|
|
- ic %r0,.Llpm-0b(%r13) # copy lpm to orb lpm
|
|
- stc %r0,6(%r3)
|
|
-1: lr %r1,%r12
|
|
- ssch 0(%r11) # go
|
|
- bnz 4f-0b(%r13) # houston, we have a problem
|
|
-2: lr %r2,%r12 # call _wait4de with subchannel id
|
|
- lr %r3,%r10 # and irb address as parameters
|
|
- bas %r14,_wait4de-0b(%r13) # wait until DE or error
|
|
- tm 9(%r10),0xff # test channel status
|
|
- bnz 4f-0b(%r13)
|
|
- tm 8(%r10),0xf3 # test device status
|
|
- bz 5f-0b(%r13)
|
|
- bct %r9,1b-0b(%r13) # something went wrong, retry.
|
|
-4: l %r2,7f-0b(%r13)
|
|
- bas %r4,_panik-0b(%r13) # won't return
|
|
-5: lm %r6,%r15,120(%r15)
|
|
- br %r14
|
|
-6: .long 96
|
|
-7: .long ESSCH
|
|
+ stm %r6,%r15,24(%r15)
|
|
+ basr %r13,0 # get base register
|
|
+0:
|
|
+ ahi %r15,-96 # create stack frame
|
|
+ lr %r6,%r2 # r6: sid
|
|
+ lr %r7,%r3 # r7: orb
|
|
+ lr %r8,%r4 # r8: irb
|
|
+ sr %r9,%r9 # r9: initial lpm
|
|
+ ic %r9,.Llpm-0b(%r13)
|
|
+ l %r10,.Lmask-0b(%r13) # r10: path mask
|
|
+1: # restart_all
|
|
+ lhi %r11,256 # r11: retry counter
|
|
+2: # restart
|
|
+ stc %r9,6(%r7) # store initial lpm in orb
|
|
+ ltr %r9,%r9 # if non-zero initial lpm
|
|
+ jne 3f # then use initial lpm
|
|
+ stc %r10,6(%r7) # else use current path mask
|
|
+3: # gotlpm
|
|
+ lr %r1,%r6 # get sid
|
|
+ ssch 0(%r7) # start subchannel
|
|
+ brc 1,7f # if cc==3 goto next_path
|
|
+ brc 7,6f # if cc!=0 goto retry
|
|
+4: # wait_for_int_loop
|
|
+ lr %r2,%r6 # get sid
|
|
+ lr %r3,%r8 # get irb
|
|
+ bras %r14,_wait_for_int # wait for interrupt
|
|
+ jnz 9f # if cc!=0 goto panic
|
|
+ tm 0(%r8),0x3 # test irb deferred cc
|
|
+ brc 1,7f # if cc==3 goto next_path
|
|
+ jz 5f # if cc==0 goto no_stctl_check
|
|
+ tm 3(%r8),0x10 # test irb status control
|
|
+ jnz 6f # if alert goto retry
|
|
+5: # no_stctl_check
|
|
+ tm 9(%r8),0xff # test irb subchannel status
|
|
+ jnz 6f # if status!=0 goto retry
|
|
+ tm 8(%r8),0xf3 # test irb unusual device status
|
|
+ jnz 6f # if status!=0 goto retry
|
|
+ tm 8(%r8),0x4 # test irb device end
|
|
+ jz 4b # if !device_end goto wait_for_int_loop
|
|
+ lm %r6,%r15,120(%r15)
|
|
+ br %r14 # return
|
|
+
|
|
+6: # retry
|
|
+ lr %r1,%r6 # get sid
|
|
+ tsch 0(%r8) # clear status if necessary
|
|
+ brct %r11,2b # if --retries>0 goto restart
|
|
+7: # next_path
|
|
+ ltr %r9,%r9 # if initial lpm != 0
|
|
+ jnz 8f # then goto noshift
|
|
+ srl %r10,1 # path_mask >>= 1
|
|
+ ltr %r10,%r10 # if path_mask==0
|
|
+ jz 9f # then goto panic
|
|
+8: # noshift
|
|
+ sr %r9,%r9 # clear initial lpm
|
|
+ lr %r1,%r6 # get sid
|
|
+ csch # clear subchannel
|
|
+ brc 7,9f # if cc!=0 goto panic
|
|
+ lr %r2,%r6 # get sid
|
|
+ lr %r3,%r8 # get irb
|
|
+ bras %r14,_wait_for_int # wait for interrupt
|
|
+ j 1b # goto restart_all
|
|
+9: # panic
|
|
+ l %r2,.Lerrno-0b(%r13) # get error code
|
|
+ bras %r14,_panik # panic
|
|
+
|
|
+.Lerrno:
|
|
+ .long ESSCH
|
|
+.Lmask:
|
|
+ .long 0x8080
|
|
.Llpm:
|
|
- .byte 0xff
|
|
+ .byte 0x00
|
|
.align 2
|
|
|
|
#
|
|
-# Wait for interrupt subroutine
|
|
-# %r2 : device subchannel id
|
|
-# %r3 : address of irb
|
|
-#
|
|
-_wait4de:
|
|
- lr %r1,%r2
|
|
- basr %r4,0
|
|
-0: mvc 0x78(8),5f-0b(%r4) # set i/o new psw
|
|
-1: lpsw 4f-0b(%r4)
|
|
-2: c %r1,0xb8 # compare subchannel id
|
|
- bne 1b-0b(%r4) # unequal -> continue waiting
|
|
- tsch 0(%r3)
|
|
- tm 9(%r3),0xff # test channel status
|
|
- bnz 3f-0b(%r4)
|
|
- tm 8(%r3),0xf3 # got something unusual ?
|
|
- bnz 3f-0b(%r4)
|
|
- tm 8(%r3),0x04 # got device end ?
|
|
- bz 1b-0b(%r4) # still busy -> continue waiting
|
|
-3: br %r14
|
|
- .align 8
|
|
-4: .long 0x020a0000,0x80000000+1b
|
|
-5: .long 0x00080000,0x80000000+2b # io new psw
|
|
-
|
|
-#
|
|
# Panik routine. Loads a disabled wait psw
|
|
# %r2 : panik code
|
|
#
|
|
diff --git a/zipl/boot/eckd2.S b/zipl/boot/eckd2.S
|
|
index ba71db9..b59ab0e 100644
|
|
--- a/zipl/boot/eckd2.S
|
|
+++ b/zipl/boot/eckd2.S
|
|
@@ -85,7 +85,6 @@ _load_direct:
|
|
la %r3,.Lorb-.Lbase(%r13) # pass address of orb
|
|
la %r4,.Lirb-.Lbase(%r13) # and pass address of irb
|
|
lr %r2,%r11 # pass subchannel id
|
|
- la %r5,5 # 5 retries
|
|
bas %r14,_ssch-.Lbase(%r13) # read records
|
|
.Lexit:
|
|
lr %r2,%r12 # return updated load address
|
|
diff --git a/zipl/boot/fba2.S b/zipl/boot/fba2.S
|
|
index 82b1447..90bb2cd 100644
|
|
--- a/zipl/boot/fba2.S
|
|
+++ b/zipl/boot/fba2.S
|
|
@@ -98,7 +98,6 @@ _load_direct:
|
|
lr %r2,%r11 # pass subchannel id
|
|
la %r3,.Lorb-.Lbase(%r13) # pass address of orb
|
|
la %r4,.Lirb-.Lbase(%r13) # and pass address of irb
|
|
- la %r5,5 # 5 retries
|
|
bas %r14,_ssch-.Lbase(%r13) # read up to 128 blocks
|
|
b .Lmain-.Lbase(%r13)
|
|
.Lexit: lr %r2,%r12 # return updated load address
|
|
--
|
|
1.6.6
|
|
|