diff options
author | Stefan Haberland <stefan.haberland@de.ibm.com> | 2008-02-05 10:50:46 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-02-05 10:50:59 -0500 |
commit | 6c5f57c7884a7e0806ae9af86de243321cab4953 (patch) | |
tree | 40794edbe388da6e9da03ce42ec13e520914a022 /drivers/s390 | |
parent | a3afe70b83fdbbd4d757d2911900d168bc798a31 (diff) |
[S390] dasd: add ifcc handling
Adding interface control check (ifcc) handling in error recovery.
First retry up to 255 times and if all retries fail try an alternate
path if possible.
Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/dasd.c | 17 | ||||
-rw-r--r-- | drivers/s390/block/dasd_3990_erp.c | 62 |
2 files changed, 52 insertions, 27 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index d640427c74c8..ab4f64c49829 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -1057,12 +1057,11 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1057 | if (device->features & DASD_FEATURE_ERPLOG) { | 1057 | if (device->features & DASD_FEATURE_ERPLOG) { |
1058 | dasd_log_sense(cqr, irb); | 1058 | dasd_log_sense(cqr, irb); |
1059 | } | 1059 | } |
1060 | /* If we have no sense data, or we just don't want complex ERP | 1060 | /* |
1061 | * for this request, but if we have retries left, then just | 1061 | * If we don't want complex ERP for this request, then just |
1062 | * reset this request and retry it in the fastpath | 1062 | * reset this and retry it in the fastpath |
1063 | */ | 1063 | */ |
1064 | if (!(cqr->irb.esw.esw0.erw.cons && | 1064 | if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags) && |
1065 | test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags)) && | ||
1066 | cqr->retries > 0) { | 1065 | cqr->retries > 0) { |
1067 | DEV_MESSAGE(KERN_DEBUG, device, | 1066 | DEV_MESSAGE(KERN_DEBUG, device, |
1068 | "default ERP in fastpath (%i retries left)", | 1067 | "default ERP in fastpath (%i retries left)", |
@@ -1742,12 +1741,8 @@ restart: | |||
1742 | 1741 | ||
1743 | /* Process requests that may be recovered */ | 1742 | /* Process requests that may be recovered */ |
1744 | if (cqr->status == DASD_CQR_NEED_ERP) { | 1743 | if (cqr->status == DASD_CQR_NEED_ERP) { |
1745 | if (cqr->irb.esw.esw0.erw.cons && | 1744 | erp_fn = base->discipline->erp_action(cqr); |
1746 | test_bit(DASD_CQR_FLAGS_USE_ERP, | 1745 | erp_fn(cqr); |
1747 | &cqr->flags)) { | ||
1748 | erp_fn = base->discipline->erp_action(cqr); | ||
1749 | erp_fn(cqr); | ||
1750 | } | ||
1751 | goto restart; | 1746 | goto restart; |
1752 | } | 1747 | } |
1753 | 1748 | ||
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index c361ab69ec00..f69714a0e9e7 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c | |||
@@ -164,7 +164,7 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) | |||
164 | 164 | ||
165 | /* reset status to submit the request again... */ | 165 | /* reset status to submit the request again... */ |
166 | erp->status = DASD_CQR_FILLED; | 166 | erp->status = DASD_CQR_FILLED; |
167 | erp->retries = 1; | 167 | erp->retries = 10; |
168 | } else { | 168 | } else { |
169 | DEV_MESSAGE(KERN_ERR, device, | 169 | DEV_MESSAGE(KERN_ERR, device, |
170 | "No alternate channel path left (lpum=%x / " | 170 | "No alternate channel path left (lpum=%x / " |
@@ -301,8 +301,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) | |||
301 | erp->function = dasd_3990_erp_action_4; | 301 | erp->function = dasd_3990_erp_action_4; |
302 | 302 | ||
303 | } else { | 303 | } else { |
304 | 304 | if (sense && (sense[25] == 0x1D)) { /* state change pending */ | |
305 | if (sense[25] == 0x1D) { /* state change pending */ | ||
306 | 305 | ||
307 | DEV_MESSAGE(KERN_INFO, device, | 306 | DEV_MESSAGE(KERN_INFO, device, |
308 | "waiting for state change pending " | 307 | "waiting for state change pending " |
@@ -311,7 +310,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) | |||
311 | 310 | ||
312 | dasd_3990_erp_block_queue(erp, 30*HZ); | 311 | dasd_3990_erp_block_queue(erp, 30*HZ); |
313 | 312 | ||
314 | } else if (sense[25] == 0x1E) { /* busy */ | 313 | } else if (sense && (sense[25] == 0x1E)) { /* busy */ |
315 | DEV_MESSAGE(KERN_INFO, device, | 314 | DEV_MESSAGE(KERN_INFO, device, |
316 | "busy - redriving request later, " | 315 | "busy - redriving request later, " |
317 | "%d retries left", | 316 | "%d retries left", |
@@ -2120,6 +2119,34 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) | |||
2120 | */ | 2119 | */ |
2121 | 2120 | ||
2122 | /* | 2121 | /* |
2122 | * DASD_3990_ERP_CONTROL_CHECK | ||
2123 | * | ||
2124 | * DESCRIPTION | ||
2125 | * Does a generic inspection if a control check occured and sets up | ||
2126 | * the related error recovery procedure | ||
2127 | * | ||
2128 | * PARAMETER | ||
2129 | * erp pointer to the currently created default ERP | ||
2130 | * | ||
2131 | * RETURN VALUES | ||
2132 | * erp_filled pointer to the erp | ||
2133 | */ | ||
2134 | |||
2135 | static struct dasd_ccw_req * | ||
2136 | dasd_3990_erp_control_check(struct dasd_ccw_req *erp) | ||
2137 | { | ||
2138 | struct dasd_device *device = erp->startdev; | ||
2139 | |||
2140 | if (erp->refers->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK | ||
2141 | | SCHN_STAT_CHN_CTRL_CHK)) { | ||
2142 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | ||
2143 | "channel or interface control check"); | ||
2144 | erp = dasd_3990_erp_action_4(erp, NULL); | ||
2145 | } | ||
2146 | return erp; | ||
2147 | } | ||
2148 | |||
2149 | /* | ||
2123 | * DASD_3990_ERP_INSPECT | 2150 | * DASD_3990_ERP_INSPECT |
2124 | * | 2151 | * |
2125 | * DESCRIPTION | 2152 | * DESCRIPTION |
@@ -2145,8 +2172,11 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp) | |||
2145 | if (erp_new) | 2172 | if (erp_new) |
2146 | return erp_new; | 2173 | return erp_new; |
2147 | 2174 | ||
2175 | /* check if no concurrent sens is available */ | ||
2176 | if (!erp->refers->irb.esw.esw0.erw.cons) | ||
2177 | erp_new = dasd_3990_erp_control_check(erp); | ||
2148 | /* distinguish between 24 and 32 byte sense data */ | 2178 | /* distinguish between 24 and 32 byte sense data */ |
2149 | if (sense[27] & DASD_SENSE_BIT_0) { | 2179 | else if (sense[27] & DASD_SENSE_BIT_0) { |
2150 | 2180 | ||
2151 | /* inspect the 24 byte sense data */ | 2181 | /* inspect the 24 byte sense data */ |
2152 | erp_new = dasd_3990_erp_inspect_24(erp, sense); | 2182 | erp_new = dasd_3990_erp_inspect_24(erp, sense); |
@@ -2285,6 +2315,17 @@ dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2) | |||
2285 | // return 0; /* CCW doesn't match */ | 2315 | // return 0; /* CCW doesn't match */ |
2286 | } | 2316 | } |
2287 | 2317 | ||
2318 | if (cqr1->irb.esw.esw0.erw.cons != cqr2->irb.esw.esw0.erw.cons) | ||
2319 | return 0; | ||
2320 | |||
2321 | if ((cqr1->irb.esw.esw0.erw.cons == 0) && | ||
2322 | (cqr2->irb.esw.esw0.erw.cons == 0)) { | ||
2323 | if ((cqr1->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK | | ||
2324 | SCHN_STAT_CHN_CTRL_CHK)) == | ||
2325 | (cqr2->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK | | ||
2326 | SCHN_STAT_CHN_CTRL_CHK))) | ||
2327 | return 1; /* match with ifcc*/ | ||
2328 | } | ||
2288 | /* check sense data; byte 0-2,25,27 */ | 2329 | /* check sense data; byte 0-2,25,27 */ |
2289 | if (!((memcmp (cqr1->irb.ecw, cqr2->irb.ecw, 3) == 0) && | 2330 | if (!((memcmp (cqr1->irb.ecw, cqr2->irb.ecw, 3) == 0) && |
2290 | (cqr1->irb.ecw[27] == cqr2->irb.ecw[27]) && | 2331 | (cqr1->irb.ecw[27] == cqr2->irb.ecw[27]) && |
@@ -2560,17 +2601,6 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) | |||
2560 | 2601 | ||
2561 | return cqr; | 2602 | return cqr; |
2562 | } | 2603 | } |
2563 | /* check if sense data are available */ | ||
2564 | if (!cqr->irb.ecw) { | ||
2565 | DEV_MESSAGE(KERN_DEBUG, device, | ||
2566 | "ERP called witout sense data avail ..." | ||
2567 | "request %p - NO ERP possible", cqr); | ||
2568 | |||
2569 | cqr->status = DASD_CQR_FAILED; | ||
2570 | |||
2571 | return cqr; | ||
2572 | |||
2573 | } | ||
2574 | 2604 | ||
2575 | /* check if error happened before */ | 2605 | /* check if error happened before */ |
2576 | erp = dasd_3990_erp_in_erp(cqr); | 2606 | erp = dasd_3990_erp_in_erp(cqr); |