aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd_3990_erp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/block/dasd_3990_erp.c')
-rw-r--r--drivers/s390/block/dasd_3990_erp.c141
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 */
2195static struct dasd_ccw_req * 2209static struct dasd_ccw_req *
2196dasd_3990_erp_inspect(struct dasd_ccw_req * erp) 2210dasd_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 */
2242static struct dasd_ccw_req * 2262static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr)
2243dasd_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 */
2343static int 2383static int dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1,
2344dasd_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,