[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>

authored by Stefan Haberland and committed by Martin Schwidefsky 6c5f57c7 a3afe70b

+52 -27
+6 -11
drivers/s390/block/dasd.c
··· 1057 if (device->features & DASD_FEATURE_ERPLOG) { 1058 dasd_log_sense(cqr, irb); 1059 } 1060 - /* If we have no sense data, or we just don't want complex ERP 1061 - * for this request, but if we have retries left, then just 1062 - * reset this request and retry it in the fastpath 1063 */ 1064 - if (!(cqr->irb.esw.esw0.erw.cons && 1065 - test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags)) && 1066 cqr->retries > 0) { 1067 DEV_MESSAGE(KERN_DEBUG, device, 1068 "default ERP in fastpath (%i retries left)", ··· 1741 1742 /* Process requests that may be recovered */ 1743 if (cqr->status == DASD_CQR_NEED_ERP) { 1744 - if (cqr->irb.esw.esw0.erw.cons && 1745 - test_bit(DASD_CQR_FLAGS_USE_ERP, 1746 - &cqr->flags)) { 1747 - erp_fn = base->discipline->erp_action(cqr); 1748 - erp_fn(cqr); 1749 - } 1750 goto restart; 1751 } 1752
··· 1057 if (device->features & DASD_FEATURE_ERPLOG) { 1058 dasd_log_sense(cqr, irb); 1059 } 1060 + /* 1061 + * If we don't want complex ERP for this request, then just 1062 + * reset this and retry it in the fastpath 1063 */ 1064 + if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags) && 1065 cqr->retries > 0) { 1066 DEV_MESSAGE(KERN_DEBUG, device, 1067 "default ERP in fastpath (%i retries left)", ··· 1742 1743 /* Process requests that may be recovered */ 1744 if (cqr->status == DASD_CQR_NEED_ERP) { 1745 + erp_fn = base->discipline->erp_action(cqr); 1746 + erp_fn(cqr); 1747 goto restart; 1748 } 1749
+46 -16
drivers/s390/block/dasd_3990_erp.c
··· 164 165 /* reset status to submit the request again... */ 166 erp->status = DASD_CQR_FILLED; 167 - erp->retries = 1; 168 } else { 169 DEV_MESSAGE(KERN_ERR, device, 170 "No alternate channel path left (lpum=%x / " ··· 301 erp->function = dasd_3990_erp_action_4; 302 303 } else { 304 - 305 - if (sense[25] == 0x1D) { /* state change pending */ 306 307 DEV_MESSAGE(KERN_INFO, device, 308 "waiting for state change pending " ··· 310 311 dasd_3990_erp_block_queue(erp, 30*HZ); 312 313 - } else if (sense[25] == 0x1E) { /* busy */ 314 DEV_MESSAGE(KERN_INFO, device, 315 "busy - redriving request later, " 316 "%d retries left", ··· 2119 */ 2120 2121 /* 2122 * DASD_3990_ERP_INSPECT 2123 * 2124 * DESCRIPTION ··· 2172 if (erp_new) 2173 return erp_new; 2174 2175 /* distinguish between 24 and 32 byte sense data */ 2176 - if (sense[27] & DASD_SENSE_BIT_0) { 2177 2178 /* inspect the 24 byte sense data */ 2179 erp_new = dasd_3990_erp_inspect_24(erp, sense); ··· 2315 // return 0; /* CCW doesn't match */ 2316 } 2317 2318 /* check sense data; byte 0-2,25,27 */ 2319 if (!((memcmp (cqr1->irb.ecw, cqr2->irb.ecw, 3) == 0) && 2320 (cqr1->irb.ecw[27] == cqr2->irb.ecw[27]) && ··· 2600 cqr->status = DASD_CQR_DONE; 2601 2602 return cqr; 2603 - } 2604 - /* check if sense data are available */ 2605 - if (!cqr->irb.ecw) { 2606 - DEV_MESSAGE(KERN_DEBUG, device, 2607 - "ERP called witout sense data avail ..." 2608 - "request %p - NO ERP possible", cqr); 2609 - 2610 - cqr->status = DASD_CQR_FAILED; 2611 - 2612 - return cqr; 2613 - 2614 } 2615 2616 /* check if error happened before */
··· 164 165 /* reset status to submit the request again... */ 166 erp->status = DASD_CQR_FILLED; 167 + erp->retries = 10; 168 } else { 169 DEV_MESSAGE(KERN_ERR, device, 170 "No alternate channel path left (lpum=%x / " ··· 301 erp->function = dasd_3990_erp_action_4; 302 303 } else { 304 + if (sense && (sense[25] == 0x1D)) { /* state change pending */ 305 306 DEV_MESSAGE(KERN_INFO, device, 307 "waiting for state change pending " ··· 311 312 dasd_3990_erp_block_queue(erp, 30*HZ); 313 314 + } else if (sense && (sense[25] == 0x1E)) { /* busy */ 315 DEV_MESSAGE(KERN_INFO, device, 316 "busy - redriving request later, " 317 "%d retries left", ··· 2120 */ 2121 2122 /* 2123 + * DASD_3990_ERP_CONTROL_CHECK 2124 + * 2125 + * DESCRIPTION 2126 + * Does a generic inspection if a control check occured and sets up 2127 + * the related error recovery procedure 2128 + * 2129 + * PARAMETER 2130 + * erp pointer to the currently created default ERP 2131 + * 2132 + * RETURN VALUES 2133 + * erp_filled pointer to the erp 2134 + */ 2135 + 2136 + static struct dasd_ccw_req * 2137 + dasd_3990_erp_control_check(struct dasd_ccw_req *erp) 2138 + { 2139 + struct dasd_device *device = erp->startdev; 2140 + 2141 + if (erp->refers->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK 2142 + | SCHN_STAT_CHN_CTRL_CHK)) { 2143 + DEV_MESSAGE(KERN_DEBUG, device, "%s", 2144 + "channel or interface control check"); 2145 + erp = dasd_3990_erp_action_4(erp, NULL); 2146 + } 2147 + return erp; 2148 + } 2149 + 2150 + /* 2151 * DASD_3990_ERP_INSPECT 2152 * 2153 * DESCRIPTION ··· 2145 if (erp_new) 2146 return erp_new; 2147 2148 + /* check if no concurrent sens is available */ 2149 + if (!erp->refers->irb.esw.esw0.erw.cons) 2150 + erp_new = dasd_3990_erp_control_check(erp); 2151 /* distinguish between 24 and 32 byte sense data */ 2152 + else if (sense[27] & DASD_SENSE_BIT_0) { 2153 2154 /* inspect the 24 byte sense data */ 2155 erp_new = dasd_3990_erp_inspect_24(erp, sense); ··· 2285 // return 0; /* CCW doesn't match */ 2286 } 2287 2288 + if (cqr1->irb.esw.esw0.erw.cons != cqr2->irb.esw.esw0.erw.cons) 2289 + return 0; 2290 + 2291 + if ((cqr1->irb.esw.esw0.erw.cons == 0) && 2292 + (cqr2->irb.esw.esw0.erw.cons == 0)) { 2293 + if ((cqr1->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK | 2294 + SCHN_STAT_CHN_CTRL_CHK)) == 2295 + (cqr2->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK | 2296 + SCHN_STAT_CHN_CTRL_CHK))) 2297 + return 1; /* match with ifcc*/ 2298 + } 2299 /* check sense data; byte 0-2,25,27 */ 2300 if (!((memcmp (cqr1->irb.ecw, cqr2->irb.ecw, 3) == 0) && 2301 (cqr1->irb.ecw[27] == cqr2->irb.ecw[27]) && ··· 2559 cqr->status = DASD_CQR_DONE; 2560 2561 return cqr; 2562 } 2563 2564 /* check if error happened before */