diff options
Diffstat (limited to 'drivers/s390/block/dasd_3990_erp.c')
-rw-r--r-- | drivers/s390/block/dasd_3990_erp.c | 141 |
1 files changed, 94 insertions, 47 deletions
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index d82aad5224f0..4cee45916144 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c | |||
@@ -1561,6 +1561,13 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) | |||
1561 | cqr = cqr->refers; | 1561 | cqr = cqr->refers; |
1562 | } | 1562 | } |
1563 | 1563 | ||
1564 | if (scsw_is_tm(&cqr->irb.scsw)) { | ||
1565 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | ||
1566 | "32 bit sense, action 1B is not defined" | ||
1567 | " in transport mode - just retry"); | ||
1568 | return default_erp; | ||
1569 | } | ||
1570 | |||
1564 | /* for imprecise ending just do default erp */ | 1571 | /* for imprecise ending just do default erp */ |
1565 | if (sense[1] & 0x01) { | 1572 | if (sense[1] & 0x01) { |
1566 | 1573 | ||
@@ -1599,7 +1606,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) | |||
1599 | oldccw = cqr->cpaddr; | 1606 | oldccw = cqr->cpaddr; |
1600 | if (oldccw->cmd_code == DASD_ECKD_CCW_PFX) { | 1607 | if (oldccw->cmd_code == DASD_ECKD_CCW_PFX) { |
1601 | PFX_data = cqr->data; | 1608 | PFX_data = cqr->data; |
1602 | memcpy(DE_data, &PFX_data->define_extend, | 1609 | memcpy(DE_data, &PFX_data->define_extent, |
1603 | sizeof(struct DE_eckd_data)); | 1610 | sizeof(struct DE_eckd_data)); |
1604 | } else | 1611 | } else |
1605 | memcpy(DE_data, cqr->data, sizeof(struct DE_eckd_data)); | 1612 | memcpy(DE_data, cqr->data, sizeof(struct DE_eckd_data)); |
@@ -1712,6 +1719,13 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) | |||
1712 | cqr = cqr->refers; | 1719 | cqr = cqr->refers; |
1713 | } | 1720 | } |
1714 | 1721 | ||
1722 | if (scsw_is_tm(&cqr->irb.scsw)) { | ||
1723 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | ||
1724 | "32 bit sense, action 1B, update," | ||
1725 | " in transport mode - just retry"); | ||
1726 | return previous_erp; | ||
1727 | } | ||
1728 | |||
1715 | /* for imprecise ending just do default erp */ | 1729 | /* for imprecise ending just do default erp */ |
1716 | if (sense[1] & 0x01) { | 1730 | if (sense[1] & 0x01) { |
1717 | 1731 | ||
@@ -2171,7 +2185,7 @@ dasd_3990_erp_control_check(struct dasd_ccw_req *erp) | |||
2171 | { | 2185 | { |
2172 | struct dasd_device *device = erp->startdev; | 2186 | struct dasd_device *device = erp->startdev; |
2173 | 2187 | ||
2174 | if (erp->refers->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK | 2188 | if (scsw_cstat(&erp->refers->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK |
2175 | | SCHN_STAT_CHN_CTRL_CHK)) { | 2189 | | SCHN_STAT_CHN_CTRL_CHK)) { |
2176 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 2190 | DEV_MESSAGE(KERN_DEBUG, device, "%s", |
2177 | "channel or interface control check"); | 2191 | "channel or interface control check"); |
@@ -2193,21 +2207,23 @@ dasd_3990_erp_control_check(struct dasd_ccw_req *erp) | |||
2193 | * erp_new contens was possibly modified | 2207 | * erp_new contens was possibly modified |
2194 | */ | 2208 | */ |
2195 | static struct dasd_ccw_req * | 2209 | static struct dasd_ccw_req * |
2196 | dasd_3990_erp_inspect(struct dasd_ccw_req * erp) | 2210 | dasd_3990_erp_inspect(struct dasd_ccw_req *erp) |
2197 | { | 2211 | { |
2198 | 2212 | ||
2199 | struct dasd_ccw_req *erp_new = NULL; | 2213 | struct dasd_ccw_req *erp_new = NULL; |
2200 | /* sense data are located in the refers record of the */ | 2214 | char *sense; |
2201 | /* already set up new ERP ! */ | ||
2202 | char *sense = erp->refers->irb.ecw; | ||
2203 | 2215 | ||
2204 | /* if this problem occured on an alias retry on base */ | 2216 | /* if this problem occured on an alias retry on base */ |
2205 | erp_new = dasd_3990_erp_inspect_alias(erp); | 2217 | erp_new = dasd_3990_erp_inspect_alias(erp); |
2206 | if (erp_new) | 2218 | if (erp_new) |
2207 | return erp_new; | 2219 | return erp_new; |
2208 | 2220 | ||
2209 | /* check if no concurrent sens is available */ | 2221 | /* sense data are located in the refers record of the |
2210 | if (!erp->refers->irb.esw.esw0.erw.cons) | 2222 | * already set up new ERP ! |
2223 | * check if concurrent sens is available | ||
2224 | */ | ||
2225 | sense = dasd_get_sense(&erp->refers->irb); | ||
2226 | if (!sense) | ||
2211 | erp_new = dasd_3990_erp_control_check(erp); | 2227 | erp_new = dasd_3990_erp_control_check(erp); |
2212 | /* distinguish between 24 and 32 byte sense data */ | 2228 | /* distinguish between 24 and 32 byte sense data */ |
2213 | else if (sense[27] & DASD_SENSE_BIT_0) { | 2229 | else if (sense[27] & DASD_SENSE_BIT_0) { |
@@ -2231,7 +2247,11 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp) | |||
2231 | * DESCRIPTION | 2247 | * DESCRIPTION |
2232 | * This funtion adds an additional request block (ERP) to the head of | 2248 | * This funtion adds an additional request block (ERP) to the head of |
2233 | * the given cqr (or erp). | 2249 | * the given cqr (or erp). |
2234 | * This erp is initialized as an default erp (retry TIC) | 2250 | * For a command mode cqr the erp is initialized as an default erp |
2251 | * (retry TIC). | ||
2252 | * For transport mode we make a copy of the original TCW (points to | ||
2253 | * the original TCCB, TIDALs, etc.) but give it a fresh | ||
2254 | * TSB so the original sense data will not be changed. | ||
2235 | * | 2255 | * |
2236 | * PARAMETER | 2256 | * PARAMETER |
2237 | * cqr head of the current ERP-chain (or single cqr if | 2257 | * cqr head of the current ERP-chain (or single cqr if |
@@ -2239,17 +2259,27 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp) | |||
2239 | * RETURN VALUES | 2259 | * RETURN VALUES |
2240 | * erp pointer to new ERP-chain head | 2260 | * erp pointer to new ERP-chain head |
2241 | */ | 2261 | */ |
2242 | static struct dasd_ccw_req * | 2262 | static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr) |
2243 | dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) | ||
2244 | { | 2263 | { |
2245 | 2264 | ||
2246 | struct dasd_device *device = cqr->startdev; | 2265 | struct dasd_device *device = cqr->startdev; |
2247 | struct ccw1 *ccw; | 2266 | struct ccw1 *ccw; |
2248 | |||
2249 | /* allocate additional request block */ | ||
2250 | struct dasd_ccw_req *erp; | 2267 | struct dasd_ccw_req *erp; |
2268 | int cplength, datasize; | ||
2269 | struct tcw *tcw; | ||
2270 | struct tsb *tsb; | ||
2271 | |||
2272 | if (cqr->cpmode == 1) { | ||
2273 | cplength = 0; | ||
2274 | datasize = sizeof(struct tcw) + sizeof(struct tsb); | ||
2275 | } else { | ||
2276 | cplength = 2; | ||
2277 | datasize = 0; | ||
2278 | } | ||
2251 | 2279 | ||
2252 | erp = dasd_alloc_erp_request((char *) &cqr->magic, 2, 0, device); | 2280 | /* allocate additional request block */ |
2281 | erp = dasd_alloc_erp_request((char *) &cqr->magic, | ||
2282 | cplength, datasize, device); | ||
2253 | if (IS_ERR(erp)) { | 2283 | if (IS_ERR(erp)) { |
2254 | if (cqr->retries <= 0) { | 2284 | if (cqr->retries <= 0) { |
2255 | DEV_MESSAGE(KERN_ERR, device, "%s", | 2285 | DEV_MESSAGE(KERN_ERR, device, "%s", |
@@ -2266,13 +2296,24 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) | |||
2266 | return cqr; | 2296 | return cqr; |
2267 | } | 2297 | } |
2268 | 2298 | ||
2269 | /* initialize request with default TIC to current ERP/CQR */ | 2299 | if (cqr->cpmode == 1) { |
2270 | ccw = erp->cpaddr; | 2300 | /* make a shallow copy of the original tcw but set new tsb */ |
2271 | ccw->cmd_code = CCW_CMD_NOOP; | 2301 | erp->cpmode = 1; |
2272 | ccw->flags = CCW_FLAG_CC; | 2302 | erp->cpaddr = erp->data; |
2273 | ccw++; | 2303 | tcw = erp->data; |
2274 | ccw->cmd_code = CCW_CMD_TIC; | 2304 | tsb = (struct tsb *) &tcw[1]; |
2275 | ccw->cda = (long)(cqr->cpaddr); | 2305 | *tcw = *((struct tcw *)cqr->cpaddr); |
2306 | tcw->tsb = (long)tsb; | ||
2307 | } else { | ||
2308 | /* initialize request with default TIC to current ERP/CQR */ | ||
2309 | ccw = erp->cpaddr; | ||
2310 | ccw->cmd_code = CCW_CMD_NOOP; | ||
2311 | ccw->flags = CCW_FLAG_CC; | ||
2312 | ccw++; | ||
2313 | ccw->cmd_code = CCW_CMD_TIC; | ||
2314 | ccw->cda = (long)(cqr->cpaddr); | ||
2315 | } | ||
2316 | |||
2276 | erp->function = dasd_3990_erp_add_erp; | 2317 | erp->function = dasd_3990_erp_add_erp; |
2277 | erp->refers = cqr; | 2318 | erp->refers = cqr; |
2278 | erp->startdev = device; | 2319 | erp->startdev = device; |
@@ -2282,7 +2323,6 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) | |||
2282 | erp->expires = 0; | 2323 | erp->expires = 0; |
2283 | erp->retries = 256; | 2324 | erp->retries = 256; |
2284 | erp->buildclk = get_clock(); | 2325 | erp->buildclk = get_clock(); |
2285 | |||
2286 | erp->status = DASD_CQR_FILLED; | 2326 | erp->status = DASD_CQR_FILLED; |
2287 | 2327 | ||
2288 | return erp; | 2328 | return erp; |
@@ -2340,28 +2380,33 @@ dasd_3990_erp_additional_erp(struct dasd_ccw_req * cqr) | |||
2340 | * match 'boolean' for match found | 2380 | * match 'boolean' for match found |
2341 | * returns 1 if match found, otherwise 0. | 2381 | * returns 1 if match found, otherwise 0. |
2342 | */ | 2382 | */ |
2343 | static int | 2383 | static int dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, |
2344 | dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2) | 2384 | struct dasd_ccw_req *cqr2) |
2345 | { | 2385 | { |
2386 | char *sense1, *sense2; | ||
2346 | 2387 | ||
2347 | if (cqr1->startdev != cqr2->startdev) | 2388 | if (cqr1->startdev != cqr2->startdev) |
2348 | return 0; | 2389 | return 0; |
2349 | 2390 | ||
2350 | if (cqr1->irb.esw.esw0.erw.cons != cqr2->irb.esw.esw0.erw.cons) | 2391 | sense1 = dasd_get_sense(&cqr1->irb); |
2351 | return 0; | 2392 | sense2 = dasd_get_sense(&cqr2->irb); |
2352 | 2393 | ||
2353 | if ((cqr1->irb.esw.esw0.erw.cons == 0) && | 2394 | /* one request has sense data, the other not -> no match, return 0 */ |
2354 | (cqr2->irb.esw.esw0.erw.cons == 0)) { | 2395 | if (!sense1 != !sense2) |
2355 | if ((cqr1->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK | | 2396 | return 0; |
2356 | SCHN_STAT_CHN_CTRL_CHK)) == | 2397 | /* no sense data in both cases -> check cstat for IFCC */ |
2357 | (cqr2->irb.scsw.cmd.cstat & (SCHN_STAT_INTF_CTRL_CHK | | 2398 | if (!sense1 && !sense2) { |
2358 | SCHN_STAT_CHN_CTRL_CHK))) | 2399 | if ((scsw_cstat(&cqr1->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK | |
2400 | SCHN_STAT_CHN_CTRL_CHK)) == | ||
2401 | (scsw_cstat(&cqr2->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK | | ||
2402 | SCHN_STAT_CHN_CTRL_CHK))) | ||
2359 | return 1; /* match with ifcc*/ | 2403 | return 1; /* match with ifcc*/ |
2360 | } | 2404 | } |
2361 | /* check sense data; byte 0-2,25,27 */ | 2405 | /* check sense data; byte 0-2,25,27 */ |
2362 | if (!((memcmp (cqr1->irb.ecw, cqr2->irb.ecw, 3) == 0) && | 2406 | if (!(sense1 && sense2 && |
2363 | (cqr1->irb.ecw[27] == cqr2->irb.ecw[27]) && | 2407 | (memcmp(sense1, sense2, 3) == 0) && |
2364 | (cqr1->irb.ecw[25] == cqr2->irb.ecw[25]))) { | 2408 | (sense1[27] == sense2[27]) && |
2409 | (sense1[25] == sense2[25]))) { | ||
2365 | 2410 | ||
2366 | return 0; /* sense doesn't match */ | 2411 | return 0; /* sense doesn't match */ |
2367 | } | 2412 | } |
@@ -2434,7 +2479,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) | |||
2434 | { | 2479 | { |
2435 | 2480 | ||
2436 | struct dasd_device *device = erp->startdev; | 2481 | struct dasd_device *device = erp->startdev; |
2437 | char *sense = erp->irb.ecw; | 2482 | char *sense = dasd_get_sense(&erp->irb); |
2438 | 2483 | ||
2439 | /* check for 24 byte sense ERP */ | 2484 | /* check for 24 byte sense ERP */ |
2440 | if ((erp->function == dasd_3990_erp_bus_out) || | 2485 | if ((erp->function == dasd_3990_erp_bus_out) || |
@@ -2449,7 +2494,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) | |||
2449 | /* prepare erp for retry on different channel path */ | 2494 | /* prepare erp for retry on different channel path */ |
2450 | erp = dasd_3990_erp_action_1(erp); | 2495 | erp = dasd_3990_erp_action_1(erp); |
2451 | 2496 | ||
2452 | if (!(sense[2] & DASD_SENSE_BIT_0)) { | 2497 | if (sense && !(sense[2] & DASD_SENSE_BIT_0)) { |
2453 | 2498 | ||
2454 | /* issue a Diagnostic Control command with an | 2499 | /* issue a Diagnostic Control command with an |
2455 | * Inhibit Write subcommand */ | 2500 | * Inhibit Write subcommand */ |
@@ -2479,10 +2524,11 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) | |||
2479 | } | 2524 | } |
2480 | 2525 | ||
2481 | /* check for 32 byte sense ERP */ | 2526 | /* check for 32 byte sense ERP */ |
2482 | } else if ((erp->function == dasd_3990_erp_compound_retry) || | 2527 | } else if (sense && |
2483 | (erp->function == dasd_3990_erp_compound_path) || | 2528 | ((erp->function == dasd_3990_erp_compound_retry) || |
2484 | (erp->function == dasd_3990_erp_compound_code) || | 2529 | (erp->function == dasd_3990_erp_compound_path) || |
2485 | (erp->function == dasd_3990_erp_compound_config)) { | 2530 | (erp->function == dasd_3990_erp_compound_code) || |
2531 | (erp->function == dasd_3990_erp_compound_config))) { | ||
2486 | 2532 | ||
2487 | erp = dasd_3990_erp_compound(erp, sense); | 2533 | erp = dasd_3990_erp_compound(erp, sense); |
2488 | 2534 | ||
@@ -2548,18 +2594,19 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head, | |||
2548 | 2594 | ||
2549 | if (erp->retries > 0) { | 2595 | if (erp->retries > 0) { |
2550 | 2596 | ||
2551 | char *sense = erp->refers->irb.ecw; | 2597 | char *sense = dasd_get_sense(&erp->refers->irb); |
2552 | 2598 | ||
2553 | /* check for special retries */ | 2599 | /* check for special retries */ |
2554 | if (erp->function == dasd_3990_erp_action_4) { | 2600 | if (sense && erp->function == dasd_3990_erp_action_4) { |
2555 | 2601 | ||
2556 | erp = dasd_3990_erp_action_4(erp, sense); | 2602 | erp = dasd_3990_erp_action_4(erp, sense); |
2557 | 2603 | ||
2558 | } else if (erp->function == dasd_3990_erp_action_1B_32) { | 2604 | } else if (sense && |
2605 | erp->function == dasd_3990_erp_action_1B_32) { | ||
2559 | 2606 | ||
2560 | erp = dasd_3990_update_1B(erp, sense); | 2607 | erp = dasd_3990_update_1B(erp, sense); |
2561 | 2608 | ||
2562 | } else if (erp->function == dasd_3990_erp_int_req) { | 2609 | } else if (sense && erp->function == dasd_3990_erp_int_req) { |
2563 | 2610 | ||
2564 | erp = dasd_3990_erp_int_req(erp); | 2611 | erp = dasd_3990_erp_int_req(erp); |
2565 | 2612 | ||
@@ -2622,8 +2669,8 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) | |||
2622 | } | 2669 | } |
2623 | 2670 | ||
2624 | /* double-check if current erp/cqr was successful */ | 2671 | /* double-check if current erp/cqr was successful */ |
2625 | if ((cqr->irb.scsw.cmd.cstat == 0x00) && | 2672 | if ((scsw_cstat(&cqr->irb.scsw) == 0x00) && |
2626 | (cqr->irb.scsw.cmd.dstat == | 2673 | (scsw_dstat(&cqr->irb.scsw) == |
2627 | (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) { | 2674 | (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) { |
2628 | 2675 | ||
2629 | DEV_MESSAGE(KERN_DEBUG, device, | 2676 | DEV_MESSAGE(KERN_DEBUG, device, |