2816 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Author(s)......: Horst Hummel <Horst.Hummel@de.ibm.com>4 * Holger Smolinski <Holger.Smolinski@de.ibm.com>5 * Bugreports.to..: <Linux390@de.ibm.com>6 * Copyright IBM Corp. 2000, 20017 *8 */9 10#include <linux/timer.h>11#include <asm/idals.h>12 13#include "dasd_int.h"14#include "dasd_eckd.h"15 16 17struct DCTL_data {18 unsigned char subcommand; /* e.g Inhibit Write, Enable Write,... */19 unsigned char modifier; /* Subcommand modifier */20 unsigned short res; /* reserved */21} __attribute__ ((packed));22 23/*24 *****************************************************************************25 * SECTION ERP HANDLING26 *****************************************************************************27 */28/*29 *****************************************************************************30 * 24 and 32 byte sense ERP functions31 *****************************************************************************32 */33 34/*35 * DASD_3990_ERP_CLEANUP36 *37 * DESCRIPTION38 * Removes the already build but not necessary ERP request and sets39 * the status of the original cqr / erp to the given (final) status40 *41 * PARAMETER42 * erp request to be blocked43 * final_status either DASD_CQR_DONE or DASD_CQR_FAILED44 *45 * RETURN VALUES46 * cqr original cqr47 */48static struct dasd_ccw_req *49dasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status)50{51 struct dasd_ccw_req *cqr = erp->refers;52 53 dasd_free_erp_request(erp, erp->memdev);54 cqr->status = final_status;55 return cqr;56 57} /* end dasd_3990_erp_cleanup */58 59/*60 * DASD_3990_ERP_BLOCK_QUEUE61 *62 * DESCRIPTION63 * Block the given device request queue to prevent from further64 * processing until the started timer has expired or an related65 * interrupt was received.66 */67static void dasd_3990_erp_block_queue(struct dasd_ccw_req *erp, int expires)68{69 70 struct dasd_device *device = erp->startdev;71 unsigned long flags;72 73 DBF_DEV_EVENT(DBF_INFO, device,74 "blocking request queue for %is", expires/HZ);75 76 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);77 dasd_device_set_stop_bits(device, DASD_STOPPED_PENDING);78 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);79 erp->status = DASD_CQR_FILLED;80 if (erp->block)81 dasd_block_set_timer(erp->block, expires);82 else83 dasd_device_set_timer(device, expires);84}85 86/*87 * DASD_3990_ERP_INT_REQ88 *89 * DESCRIPTION90 * Handles 'Intervention Required' error.91 * This means either device offline or not installed.92 *93 * PARAMETER94 * erp current erp95 * RETURN VALUES96 * erp modified erp97 */98static struct dasd_ccw_req *99dasd_3990_erp_int_req(struct dasd_ccw_req * erp)100{101 102 struct dasd_device *device = erp->startdev;103 104 /* first time set initial retry counter and erp_function */105 /* and retry once without blocking queue */106 /* (this enables easier enqueing of the cqr) */107 if (erp->function != dasd_3990_erp_int_req) {108 109 erp->retries = 256;110 erp->function = dasd_3990_erp_int_req;111 112 } else {113 114 /* issue a message and wait for 'device ready' interrupt */115 dev_err(&device->cdev->dev,116 "is offline or not installed - "117 "INTERVENTION REQUIRED!!\n");118 119 dasd_3990_erp_block_queue(erp, 60*HZ);120 }121 122 return erp;123 124} /* end dasd_3990_erp_int_req */125 126/*127 * DASD_3990_ERP_ALTERNATE_PATH128 *129 * DESCRIPTION130 * Repeat the operation on a different channel path.131 * If all alternate paths have been tried, the request is posted with a132 * permanent error.133 *134 * PARAMETER135 * erp pointer to the current ERP136 *137 * RETURN VALUES138 * erp modified pointer to the ERP139 */140static void141dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)142{143 struct dasd_device *device = erp->startdev;144 __u8 opm;145 unsigned long flags;146 147 /* try alternate valid path */148 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);149 opm = ccw_device_get_path_mask(device->cdev);150 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);151 if (erp->lpm == 0)152 erp->lpm = dasd_path_get_opm(device) &153 ~(erp->irb.esw.esw0.sublog.lpum);154 else155 erp->lpm &= ~(erp->irb.esw.esw0.sublog.lpum);156 157 if ((erp->lpm & opm) != 0x00) {158 159 DBF_DEV_EVENT(DBF_WARNING, device,160 "try alternate lpm=%x (lpum=%x / opm=%x)",161 erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm);162 163 /* reset status to submit the request again... */164 erp->status = DASD_CQR_FILLED;165 erp->retries = 10;166 } else {167 dev_err(&device->cdev->dev,168 "The DASD cannot be reached on any path (lpum=%x"169 "/opm=%x)\n", erp->irb.esw.esw0.sublog.lpum, opm);170 171 /* post request with permanent error */172 erp->status = DASD_CQR_FAILED;173 }174} /* end dasd_3990_erp_alternate_path */175 176/*177 * DASD_3990_ERP_DCTL178 *179 * DESCRIPTION180 * Setup cqr to do the Diagnostic Control (DCTL) command with an181 * Inhibit Write subcommand (0x20) and the given modifier.182 *183 * PARAMETER184 * erp pointer to the current (failed) ERP185 * modifier subcommand modifier186 *187 * RETURN VALUES188 * dctl_cqr pointer to NEW dctl_cqr189 *190 */191static struct dasd_ccw_req *192dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier)193{194 195 struct dasd_device *device = erp->startdev;196 struct DCTL_data *DCTL_data;197 struct ccw1 *ccw;198 struct dasd_ccw_req *dctl_cqr;199 200 dctl_cqr = dasd_alloc_erp_request(erp->magic, 1,201 sizeof(struct DCTL_data),202 device);203 if (IS_ERR(dctl_cqr)) {204 dev_err(&device->cdev->dev,205 "Unable to allocate DCTL-CQR\n");206 erp->status = DASD_CQR_FAILED;207 return erp;208 }209 210 DCTL_data = dctl_cqr->data;211 212 DCTL_data->subcommand = 0x02; /* Inhibit Write */213 DCTL_data->modifier = modifier;214 215 ccw = dctl_cqr->cpaddr;216 memset(ccw, 0, sizeof(struct ccw1));217 ccw->cmd_code = CCW_CMD_DCTL;218 ccw->count = 4;219 ccw->cda = virt_to_dma32(DCTL_data);220 dctl_cqr->flags = erp->flags;221 dctl_cqr->function = dasd_3990_erp_DCTL;222 dctl_cqr->refers = erp;223 dctl_cqr->startdev = device;224 dctl_cqr->memdev = device;225 dctl_cqr->magic = erp->magic;226 dctl_cqr->expires = 5 * 60 * HZ;227 dctl_cqr->retries = 2;228 229 dctl_cqr->buildclk = get_tod_clock();230 231 dctl_cqr->status = DASD_CQR_FILLED;232 233 return dctl_cqr;234 235} /* end dasd_3990_erp_DCTL */236 237/*238 * DASD_3990_ERP_ACTION_1239 *240 * DESCRIPTION241 * Setup ERP to do the ERP action 1 (see Reference manual).242 * Repeat the operation on a different channel path.243 * As deviation from the recommended recovery action, we reset the path mask244 * after we have tried each path and go through all paths a second time.245 * This will cover situations where only one path at a time is actually down,246 * but all paths fail and recover just with the same sequence and timing as247 * we try to use them (flapping links).248 * If all alternate paths have been tried twice, the request is posted with249 * a permanent error.250 *251 * PARAMETER252 * erp pointer to the current ERP253 *254 * RETURN VALUES255 * erp pointer to the ERP256 *257 */258static struct dasd_ccw_req *dasd_3990_erp_action_1_sec(struct dasd_ccw_req *erp)259{260 erp->function = dasd_3990_erp_action_1_sec;261 dasd_3990_erp_alternate_path(erp);262 return erp;263}264 265static struct dasd_ccw_req *dasd_3990_erp_action_1(struct dasd_ccw_req *erp)266{267 erp->function = dasd_3990_erp_action_1;268 dasd_3990_erp_alternate_path(erp);269 if (erp->status == DASD_CQR_FAILED &&270 !test_bit(DASD_CQR_VERIFY_PATH, &erp->flags)) {271 erp->status = DASD_CQR_FILLED;272 erp->retries = 10;273 erp->lpm = dasd_path_get_opm(erp->startdev);274 erp->function = dasd_3990_erp_action_1_sec;275 }276 return erp;277} /* end dasd_3990_erp_action_1(b) */278 279/*280 * DASD_3990_ERP_ACTION_4281 *282 * DESCRIPTION283 * Setup ERP to do the ERP action 4 (see Reference manual).284 * Set the current request to PENDING to block the CQR queue for that device285 * until the state change interrupt appears.286 * Use a timer (20 seconds) to retry the cqr if the interrupt is still287 * missing.288 *289 * PARAMETER290 * sense sense data of the actual error291 * erp pointer to the current ERP292 *293 * RETURN VALUES294 * erp pointer to the ERP295 *296 */297static struct dasd_ccw_req *298dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)299{300 301 struct dasd_device *device = erp->startdev;302 303 /* first time set initial retry counter and erp_function */304 /* and retry once without waiting for state change pending */305 /* interrupt (this enables easier enqueing of the cqr) */306 if (erp->function != dasd_3990_erp_action_4) {307 308 DBF_DEV_EVENT(DBF_INFO, device, "%s",309 "dasd_3990_erp_action_4: first time retry");310 311 erp->retries = 256;312 erp->function = dasd_3990_erp_action_4;313 314 } else {315 if (sense && (sense[25] == 0x1D)) { /* state change pending */316 317 DBF_DEV_EVENT(DBF_INFO, device,318 "waiting for state change pending "319 "interrupt, %d retries left",320 erp->retries);321 322 dasd_3990_erp_block_queue(erp, 30*HZ);323 324 } else if (sense && (sense[25] == 0x1E)) { /* busy */325 DBF_DEV_EVENT(DBF_INFO, device,326 "busy - redriving request later, "327 "%d retries left",328 erp->retries);329 dasd_3990_erp_block_queue(erp, HZ);330 } else {331 /* no state change pending - retry */332 DBF_DEV_EVENT(DBF_INFO, device,333 "redriving request immediately, "334 "%d retries left",335 erp->retries);336 erp->status = DASD_CQR_FILLED;337 }338 }339 340 return erp;341 342} /* end dasd_3990_erp_action_4 */343 344/*345 *****************************************************************************346 * 24 byte sense ERP functions (only)347 *****************************************************************************348 */349 350/*351 * DASD_3990_ERP_ACTION_5352 *353 * DESCRIPTION354 * Setup ERP to do the ERP action 5 (see Reference manual).355 * NOTE: Further handling is done in xxx_further_erp after the retries.356 *357 * PARAMETER358 * erp pointer to the current ERP359 *360 * RETURN VALUES361 * erp pointer to the ERP362 *363 */364static struct dasd_ccw_req *365dasd_3990_erp_action_5(struct dasd_ccw_req * erp)366{367 368 /* first of all retry */369 erp->retries = 10;370 erp->function = dasd_3990_erp_action_5;371 372 return erp;373 374} /* end dasd_3990_erp_action_5 */375 376/*377 * DASD_3990_HANDLE_ENV_DATA378 *379 * DESCRIPTION380 * Handles 24 byte 'Environmental data present'.381 * Does a analysis of the sense data (message Format)382 * and prints the error messages.383 *384 * PARAMETER385 * sense current sense data386 *387 * RETURN VALUES388 * void389 */390static void391dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)392{393 394 struct dasd_device *device = erp->startdev;395 char msg_format = (sense[7] & 0xF0);396 char msg_no = (sense[7] & 0x0F);397 398 switch (msg_format) {399 case 0x00: /* Format 0 - Program or System Checks */400 401 if (sense[1] & 0x10) { /* check message to operator bit */402 403 switch (msg_no) {404 case 0x00: /* No Message */405 break;406 case 0x01:407 dev_warn(&device->cdev->dev,408 "FORMAT 0 - Invalid Command\n");409 break;410 case 0x02:411 dev_warn(&device->cdev->dev,412 "FORMAT 0 - Invalid Command "413 "Sequence\n");414 break;415 case 0x03:416 dev_warn(&device->cdev->dev,417 "FORMAT 0 - CCW Count less than "418 "required\n");419 break;420 case 0x04:421 dev_warn(&device->cdev->dev,422 "FORMAT 0 - Invalid Parameter\n");423 break;424 case 0x05:425 dev_warn(&device->cdev->dev,426 "FORMAT 0 - Diagnostic of Special"427 " Command Violates File Mask\n");428 break;429 case 0x07:430 dev_warn(&device->cdev->dev,431 "FORMAT 0 - Channel Returned with "432 "Incorrect retry CCW\n");433 break;434 case 0x08:435 dev_warn(&device->cdev->dev,436 "FORMAT 0 - Reset Notification\n");437 break;438 case 0x09:439 dev_warn(&device->cdev->dev,440 "FORMAT 0 - Storage Path Restart\n");441 break;442 case 0x0A:443 dev_warn(&device->cdev->dev,444 "FORMAT 0 - Channel requested "445 "... %02x\n", sense[8]);446 break;447 case 0x0B:448 dev_warn(&device->cdev->dev,449 "FORMAT 0 - Invalid Defective/"450 "Alternate Track Pointer\n");451 break;452 case 0x0C:453 dev_warn(&device->cdev->dev,454 "FORMAT 0 - DPS Installation "455 "Check\n");456 break;457 case 0x0E:458 dev_warn(&device->cdev->dev,459 "FORMAT 0 - Command Invalid on "460 "Secondary Address\n");461 break;462 case 0x0F:463 dev_warn(&device->cdev->dev,464 "FORMAT 0 - Status Not As "465 "Required: reason %02x\n",466 sense[8]);467 break;468 default:469 dev_warn(&device->cdev->dev,470 "FORMAT 0 - Reserved\n");471 }472 } else {473 switch (msg_no) {474 case 0x00: /* No Message */475 break;476 case 0x01:477 dev_warn(&device->cdev->dev,478 "FORMAT 0 - Device Error "479 "Source\n");480 break;481 case 0x02:482 dev_warn(&device->cdev->dev,483 "FORMAT 0 - Reserved\n");484 break;485 case 0x03:486 dev_warn(&device->cdev->dev,487 "FORMAT 0 - Device Fenced - "488 "device = %02x\n", sense[4]);489 break;490 case 0x04:491 dev_warn(&device->cdev->dev,492 "FORMAT 0 - Data Pinned for "493 "Device\n");494 break;495 default:496 dev_warn(&device->cdev->dev,497 "FORMAT 0 - Reserved\n");498 }499 }500 break;501 502 case 0x10: /* Format 1 - Device Equipment Checks */503 switch (msg_no) {504 case 0x00: /* No Message */505 break;506 case 0x01:507 dev_warn(&device->cdev->dev,508 "FORMAT 1 - Device Status 1 not as "509 "expected\n");510 break;511 case 0x03:512 dev_warn(&device->cdev->dev,513 "FORMAT 1 - Index missing\n");514 break;515 case 0x04:516 dev_warn(&device->cdev->dev,517 "FORMAT 1 - Interruption cannot be "518 "reset\n");519 break;520 case 0x05:521 dev_warn(&device->cdev->dev,522 "FORMAT 1 - Device did not respond to "523 "selection\n");524 break;525 case 0x06:526 dev_warn(&device->cdev->dev,527 "FORMAT 1 - Device check-2 error or Set "528 "Sector is not complete\n");529 break;530 case 0x07:531 dev_warn(&device->cdev->dev,532 "FORMAT 1 - Head address does not "533 "compare\n");534 break;535 case 0x08:536 dev_warn(&device->cdev->dev,537 "FORMAT 1 - Device status 1 not valid\n");538 break;539 case 0x09:540 dev_warn(&device->cdev->dev,541 "FORMAT 1 - Device not ready\n");542 break;543 case 0x0A:544 dev_warn(&device->cdev->dev,545 "FORMAT 1 - Track physical address did "546 "not compare\n");547 break;548 case 0x0B:549 dev_warn(&device->cdev->dev,550 "FORMAT 1 - Missing device address bit\n");551 break;552 case 0x0C:553 dev_warn(&device->cdev->dev,554 "FORMAT 1 - Drive motor switch is off\n");555 break;556 case 0x0D:557 dev_warn(&device->cdev->dev,558 "FORMAT 1 - Seek incomplete\n");559 break;560 case 0x0E:561 dev_warn(&device->cdev->dev,562 "FORMAT 1 - Cylinder address did not "563 "compare\n");564 break;565 case 0x0F:566 dev_warn(&device->cdev->dev,567 "FORMAT 1 - Offset active cannot be "568 "reset\n");569 break;570 default:571 dev_warn(&device->cdev->dev,572 "FORMAT 1 - Reserved\n");573 }574 break;575 576 case 0x20: /* Format 2 - 3990 Equipment Checks */577 switch (msg_no) {578 case 0x08:579 dev_warn(&device->cdev->dev,580 "FORMAT 2 - 3990 check-2 error\n");581 break;582 case 0x0E:583 dev_warn(&device->cdev->dev,584 "FORMAT 2 - Support facility errors\n");585 break;586 case 0x0F:587 dev_warn(&device->cdev->dev,588 "FORMAT 2 - Microcode detected error "589 "%02x\n",590 sense[8]);591 break;592 default:593 dev_warn(&device->cdev->dev,594 "FORMAT 2 - Reserved\n");595 }596 break;597 598 case 0x30: /* Format 3 - 3990 Control Checks */599 switch (msg_no) {600 case 0x0F:601 dev_warn(&device->cdev->dev,602 "FORMAT 3 - Allegiance terminated\n");603 break;604 default:605 dev_warn(&device->cdev->dev,606 "FORMAT 3 - Reserved\n");607 }608 break;609 610 case 0x40: /* Format 4 - Data Checks */611 switch (msg_no) {612 case 0x00:613 dev_warn(&device->cdev->dev,614 "FORMAT 4 - Home address area error\n");615 break;616 case 0x01:617 dev_warn(&device->cdev->dev,618 "FORMAT 4 - Count area error\n");619 break;620 case 0x02:621 dev_warn(&device->cdev->dev,622 "FORMAT 4 - Key area error\n");623 break;624 case 0x03:625 dev_warn(&device->cdev->dev,626 "FORMAT 4 - Data area error\n");627 break;628 case 0x04:629 dev_warn(&device->cdev->dev,630 "FORMAT 4 - No sync byte in home address "631 "area\n");632 break;633 case 0x05:634 dev_warn(&device->cdev->dev,635 "FORMAT 4 - No sync byte in count address "636 "area\n");637 break;638 case 0x06:639 dev_warn(&device->cdev->dev,640 "FORMAT 4 - No sync byte in key area\n");641 break;642 case 0x07:643 dev_warn(&device->cdev->dev,644 "FORMAT 4 - No sync byte in data area\n");645 break;646 case 0x08:647 dev_warn(&device->cdev->dev,648 "FORMAT 4 - Home address area error; "649 "offset active\n");650 break;651 case 0x09:652 dev_warn(&device->cdev->dev,653 "FORMAT 4 - Count area error; offset "654 "active\n");655 break;656 case 0x0A:657 dev_warn(&device->cdev->dev,658 "FORMAT 4 - Key area error; offset "659 "active\n");660 break;661 case 0x0B:662 dev_warn(&device->cdev->dev,663 "FORMAT 4 - Data area error; "664 "offset active\n");665 break;666 case 0x0C:667 dev_warn(&device->cdev->dev,668 "FORMAT 4 - No sync byte in home "669 "address area; offset active\n");670 break;671 case 0x0D:672 dev_warn(&device->cdev->dev,673 "FORMAT 4 - No sync byte in count "674 "address area; offset active\n");675 break;676 case 0x0E:677 dev_warn(&device->cdev->dev,678 "FORMAT 4 - No sync byte in key area; "679 "offset active\n");680 break;681 case 0x0F:682 dev_warn(&device->cdev->dev,683 "FORMAT 4 - No sync byte in data area; "684 "offset active\n");685 break;686 default:687 dev_warn(&device->cdev->dev,688 "FORMAT 4 - Reserved\n");689 }690 break;691 692 case 0x50: /* Format 5 - Data Check with displacement information */693 switch (msg_no) {694 case 0x00:695 dev_warn(&device->cdev->dev,696 "FORMAT 5 - Data Check in the "697 "home address area\n");698 break;699 case 0x01:700 dev_warn(&device->cdev->dev,701 "FORMAT 5 - Data Check in the count "702 "area\n");703 break;704 case 0x02:705 dev_warn(&device->cdev->dev,706 "FORMAT 5 - Data Check in the key area\n");707 break;708 case 0x03:709 dev_warn(&device->cdev->dev,710 "FORMAT 5 - Data Check in the data "711 "area\n");712 break;713 case 0x08:714 dev_warn(&device->cdev->dev,715 "FORMAT 5 - Data Check in the "716 "home address area; offset active\n");717 break;718 case 0x09:719 dev_warn(&device->cdev->dev,720 "FORMAT 5 - Data Check in the count area; "721 "offset active\n");722 break;723 case 0x0A:724 dev_warn(&device->cdev->dev,725 "FORMAT 5 - Data Check in the key area; "726 "offset active\n");727 break;728 case 0x0B:729 dev_warn(&device->cdev->dev,730 "FORMAT 5 - Data Check in the data area; "731 "offset active\n");732 break;733 default:734 dev_warn(&device->cdev->dev,735 "FORMAT 5 - Reserved\n");736 }737 break;738 739 case 0x60: /* Format 6 - Usage Statistics/Overrun Errors */740 switch (msg_no) {741 case 0x00:742 dev_warn(&device->cdev->dev,743 "FORMAT 6 - Overrun on channel A\n");744 break;745 case 0x01:746 dev_warn(&device->cdev->dev,747 "FORMAT 6 - Overrun on channel B\n");748 break;749 case 0x02:750 dev_warn(&device->cdev->dev,751 "FORMAT 6 - Overrun on channel C\n");752 break;753 case 0x03:754 dev_warn(&device->cdev->dev,755 "FORMAT 6 - Overrun on channel D\n");756 break;757 case 0x04:758 dev_warn(&device->cdev->dev,759 "FORMAT 6 - Overrun on channel E\n");760 break;761 case 0x05:762 dev_warn(&device->cdev->dev,763 "FORMAT 6 - Overrun on channel F\n");764 break;765 case 0x06:766 dev_warn(&device->cdev->dev,767 "FORMAT 6 - Overrun on channel G\n");768 break;769 case 0x07:770 dev_warn(&device->cdev->dev,771 "FORMAT 6 - Overrun on channel H\n");772 break;773 default:774 dev_warn(&device->cdev->dev,775 "FORMAT 6 - Reserved\n");776 }777 break;778 779 case 0x70: /* Format 7 - Device Connection Control Checks */780 switch (msg_no) {781 case 0x00:782 dev_warn(&device->cdev->dev,783 "FORMAT 7 - RCC initiated by a connection "784 "check alert\n");785 break;786 case 0x01:787 dev_warn(&device->cdev->dev,788 "FORMAT 7 - RCC 1 sequence not "789 "successful\n");790 break;791 case 0x02:792 dev_warn(&device->cdev->dev,793 "FORMAT 7 - RCC 1 and RCC 2 sequences not "794 "successful\n");795 break;796 case 0x03:797 dev_warn(&device->cdev->dev,798 "FORMAT 7 - Invalid tag-in during "799 "selection sequence\n");800 break;801 case 0x04:802 dev_warn(&device->cdev->dev,803 "FORMAT 7 - extra RCC required\n");804 break;805 case 0x05:806 dev_warn(&device->cdev->dev,807 "FORMAT 7 - Invalid DCC selection "808 "response or timeout\n");809 break;810 case 0x06:811 dev_warn(&device->cdev->dev,812 "FORMAT 7 - Missing end operation; device "813 "transfer complete\n");814 break;815 case 0x07:816 dev_warn(&device->cdev->dev,817 "FORMAT 7 - Missing end operation; device "818 "transfer incomplete\n");819 break;820 case 0x08:821 dev_warn(&device->cdev->dev,822 "FORMAT 7 - Invalid tag-in for an "823 "immediate command sequence\n");824 break;825 case 0x09:826 dev_warn(&device->cdev->dev,827 "FORMAT 7 - Invalid tag-in for an "828 "extended command sequence\n");829 break;830 case 0x0A:831 dev_warn(&device->cdev->dev,832 "FORMAT 7 - 3990 microcode time out when "833 "stopping selection\n");834 break;835 case 0x0B:836 dev_warn(&device->cdev->dev,837 "FORMAT 7 - No response to selection "838 "after a poll interruption\n");839 break;840 case 0x0C:841 dev_warn(&device->cdev->dev,842 "FORMAT 7 - Permanent path error (DASD "843 "controller not available)\n");844 break;845 case 0x0D:846 dev_warn(&device->cdev->dev,847 "FORMAT 7 - DASD controller not available"848 " on disconnected command chain\n");849 break;850 default:851 dev_warn(&device->cdev->dev,852 "FORMAT 7 - Reserved\n");853 }854 break;855 856 case 0x80: /* Format 8 - Additional Device Equipment Checks */857 switch (msg_no) {858 case 0x00: /* No Message */859 case 0x01:860 dev_warn(&device->cdev->dev,861 "FORMAT 8 - Error correction code "862 "hardware fault\n");863 break;864 case 0x03:865 dev_warn(&device->cdev->dev,866 "FORMAT 8 - Unexpected end operation "867 "response code\n");868 break;869 case 0x04:870 dev_warn(&device->cdev->dev,871 "FORMAT 8 - End operation with transfer "872 "count not zero\n");873 break;874 case 0x05:875 dev_warn(&device->cdev->dev,876 "FORMAT 8 - End operation with transfer "877 "count zero\n");878 break;879 case 0x06:880 dev_warn(&device->cdev->dev,881 "FORMAT 8 - DPS checks after a system "882 "reset or selective reset\n");883 break;884 case 0x07:885 dev_warn(&device->cdev->dev,886 "FORMAT 8 - DPS cannot be filled\n");887 break;888 case 0x08:889 dev_warn(&device->cdev->dev,890 "FORMAT 8 - Short busy time-out during "891 "device selection\n");892 break;893 case 0x09:894 dev_warn(&device->cdev->dev,895 "FORMAT 8 - DASD controller failed to "896 "set or reset the long busy latch\n");897 break;898 case 0x0A:899 dev_warn(&device->cdev->dev,900 "FORMAT 8 - No interruption from device "901 "during a command chain\n");902 break;903 default:904 dev_warn(&device->cdev->dev,905 "FORMAT 8 - Reserved\n");906 }907 break;908 909 case 0x90: /* Format 9 - Device Read, Write, and Seek Checks */910 switch (msg_no) {911 case 0x00:912 break; /* No Message */913 case 0x06:914 dev_warn(&device->cdev->dev,915 "FORMAT 9 - Device check-2 error\n");916 break;917 case 0x07:918 dev_warn(&device->cdev->dev,919 "FORMAT 9 - Head address did not "920 "compare\n");921 break;922 case 0x0A:923 dev_warn(&device->cdev->dev,924 "FORMAT 9 - Track physical address did "925 "not compare while oriented\n");926 break;927 case 0x0E:928 dev_warn(&device->cdev->dev,929 "FORMAT 9 - Cylinder address did not "930 "compare\n");931 break;932 default:933 dev_warn(&device->cdev->dev,934 "FORMAT 9 - Reserved\n");935 }936 break;937 938 case 0xF0: /* Format F - Cache Storage Checks */939 switch (msg_no) {940 case 0x00:941 dev_warn(&device->cdev->dev,942 "FORMAT F - Operation Terminated\n");943 break;944 case 0x01:945 dev_warn(&device->cdev->dev,946 "FORMAT F - Subsystem Processing Error\n");947 break;948 case 0x02:949 dev_warn(&device->cdev->dev,950 "FORMAT F - Cache or nonvolatile storage "951 "equipment failure\n");952 break;953 case 0x04:954 dev_warn(&device->cdev->dev,955 "FORMAT F - Caching terminated\n");956 break;957 case 0x06:958 dev_warn(&device->cdev->dev,959 "FORMAT F - Cache fast write access not "960 "authorized\n");961 break;962 case 0x07:963 dev_warn(&device->cdev->dev,964 "FORMAT F - Track format incorrect\n");965 break;966 case 0x09:967 dev_warn(&device->cdev->dev,968 "FORMAT F - Caching reinitiated\n");969 break;970 case 0x0A:971 dev_warn(&device->cdev->dev,972 "FORMAT F - Nonvolatile storage "973 "terminated\n");974 break;975 case 0x0B:976 dev_warn(&device->cdev->dev,977 "FORMAT F - Volume is suspended duplex\n");978 /* call extended error reporting (EER) */979 dasd_eer_write(device, erp->refers,980 DASD_EER_PPRCSUSPEND);981 break;982 case 0x0C:983 dev_warn(&device->cdev->dev,984 "FORMAT F - Subsystem status cannot be "985 "determined\n");986 break;987 case 0x0D:988 dev_warn(&device->cdev->dev,989 "FORMAT F - Caching status reset to "990 "default\n");991 break;992 case 0x0E:993 dev_warn(&device->cdev->dev,994 "FORMAT F - DASD Fast Write inhibited\n");995 break;996 default:997 dev_warn(&device->cdev->dev,998 "FORMAT F - Reserved\n");999 }1000 break;1001 1002 default:1003 dev_err(&device->cdev->dev,1004 "Unknown message format %02x", msg_format);1005 break;1006 } /* end switch message format */1007 1008} /* end dasd_3990_handle_env_data */1009 1010/*1011 * DASD_3990_ERP_COM_REJ1012 *1013 * DESCRIPTION1014 * Handles 24 byte 'Command Reject' error.1015 *1016 * PARAMETER1017 * erp current erp_head1018 * sense current sense data1019 *1020 * RETURN VALUES1021 * erp 'new' erp_head - pointer to new ERP1022 */1023static struct dasd_ccw_req *1024dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense)1025{1026 1027 struct dasd_device *device = erp->startdev;1028 1029 erp->function = dasd_3990_erp_com_rej;1030 1031 /* env data present (ACTION 10 - retry should work) */1032 if (sense[2] & SNS2_ENV_DATA_PRESENT) {1033 1034 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1035 "Command Reject - environmental data present");1036 1037 dasd_3990_handle_env_data(erp, sense);1038 1039 erp->retries = 5;1040 1041 } else if (sense[1] & SNS1_WRITE_INHIBITED) {1042 dev_err(&device->cdev->dev, "An I/O request was rejected"1043 " because writing is inhibited\n");1044 erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);1045 } else if (sense[7] == SNS7_INVALID_ON_SEC) {1046 dev_err(&device->cdev->dev, "An I/O request was rejected on a copy pair secondary device\n");1047 /* suppress dump of sense data for this error */1048 set_bit(DASD_CQR_SUPPRESS_CR, &erp->refers->flags);1049 erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);1050 } else {1051 if (!test_bit(DASD_CQR_SUPPRESS_CR, &erp->flags))1052 dev_err(&device->cdev->dev,1053 "An I/O command request was rejected\n");1054 1055 erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);1056 }1057 1058 return erp;1059 1060} /* end dasd_3990_erp_com_rej */1061 1062/*1063 * DASD_3990_ERP_BUS_OUT1064 *1065 * DESCRIPTION1066 * Handles 24 byte 'Bus Out Parity Check' error.1067 *1068 * PARAMETER1069 * erp current erp_head1070 * RETURN VALUES1071 * erp new erp_head - pointer to new ERP1072 */1073static struct dasd_ccw_req *1074dasd_3990_erp_bus_out(struct dasd_ccw_req * erp)1075{1076 1077 struct dasd_device *device = erp->startdev;1078 1079 /* first time set initial retry counter and erp_function */1080 /* and retry once without blocking queue */1081 /* (this enables easier enqueing of the cqr) */1082 if (erp->function != dasd_3990_erp_bus_out) {1083 erp->retries = 256;1084 erp->function = dasd_3990_erp_bus_out;1085 1086 } else {1087 1088 /* issue a message and wait for 'device ready' interrupt */1089 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1090 "bus out parity error or BOPC requested by "1091 "channel");1092 1093 dasd_3990_erp_block_queue(erp, 60*HZ);1094 1095 }1096 1097 return erp;1098 1099} /* end dasd_3990_erp_bus_out */1100 1101/*1102 * DASD_3990_ERP_EQUIP_CHECK1103 *1104 * DESCRIPTION1105 * Handles 24 byte 'Equipment Check' error.1106 *1107 * PARAMETER1108 * erp current erp_head1109 * RETURN VALUES1110 * erp new erp_head - pointer to new ERP1111 */1112static struct dasd_ccw_req *1113dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense)1114{1115 1116 struct dasd_device *device = erp->startdev;1117 1118 erp->function = dasd_3990_erp_equip_check;1119 1120 if (sense[1] & SNS1_WRITE_INHIBITED) {1121 dev_err(&device->cdev->dev, "Write inhibited path encountered\n");1122 1123 erp = dasd_3990_erp_action_1(erp);1124 1125 } else if (sense[2] & SNS2_ENV_DATA_PRESENT) {1126 1127 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1128 "Equipment Check - " "environmental data present");1129 1130 dasd_3990_handle_env_data(erp, sense);1131 1132 erp = dasd_3990_erp_action_4(erp, sense);1133 1134 } else if (sense[1] & SNS1_PERM_ERR) {1135 1136 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1137 "Equipment Check - retry exhausted or "1138 "undesirable");1139 1140 erp = dasd_3990_erp_action_1(erp);1141 1142 } else {1143 /* all other equipment checks - Action 5 */1144 /* rest is done when retries == 0 */1145 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1146 "Equipment check or processing error");1147 1148 erp = dasd_3990_erp_action_5(erp);1149 }1150 return erp;1151 1152} /* end dasd_3990_erp_equip_check */1153 1154/*1155 * DASD_3990_ERP_DATA_CHECK1156 *1157 * DESCRIPTION1158 * Handles 24 byte 'Data Check' error.1159 *1160 * PARAMETER1161 * erp current erp_head1162 * RETURN VALUES1163 * erp new erp_head - pointer to new ERP1164 */1165static struct dasd_ccw_req *1166dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense)1167{1168 1169 struct dasd_device *device = erp->startdev;1170 1171 erp->function = dasd_3990_erp_data_check;1172 1173 if (sense[2] & SNS2_CORRECTABLE) { /* correctable data check */1174 1175 /* issue message that the data has been corrected */1176 dev_emerg(&device->cdev->dev,1177 "Data recovered during retry with PCI "1178 "fetch mode active\n");1179 1180 /* not possible to handle this situation in Linux */1181 panic("No way to inform application about the possibly "1182 "incorrect data");1183 1184 } else if (sense[2] & SNS2_ENV_DATA_PRESENT) {1185 1186 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1187 "Uncorrectable data check recovered secondary "1188 "addr of duplex pair");1189 1190 erp = dasd_3990_erp_action_4(erp, sense);1191 1192 } else if (sense[1] & SNS1_PERM_ERR) {1193 1194 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1195 "Uncorrectable data check with internal "1196 "retry exhausted");1197 1198 erp = dasd_3990_erp_action_1(erp);1199 1200 } else {1201 /* all other data checks */1202 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1203 "Uncorrectable data check with retry count "1204 "exhausted...");1205 1206 erp = dasd_3990_erp_action_5(erp);1207 }1208 1209 return erp;1210 1211} /* end dasd_3990_erp_data_check */1212 1213/*1214 * DASD_3990_ERP_OVERRUN1215 *1216 * DESCRIPTION1217 * Handles 24 byte 'Overrun' error.1218 *1219 * PARAMETER1220 * erp current erp_head1221 * RETURN VALUES1222 * erp new erp_head - pointer to new ERP1223 */1224static struct dasd_ccw_req *1225dasd_3990_erp_overrun(struct dasd_ccw_req * erp, char *sense)1226{1227 1228 struct dasd_device *device = erp->startdev;1229 1230 erp->function = dasd_3990_erp_overrun;1231 1232 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1233 "Overrun - service overrun or overrun"1234 " error requested by channel");1235 1236 erp = dasd_3990_erp_action_5(erp);1237 1238 return erp;1239 1240} /* end dasd_3990_erp_overrun */1241 1242/*1243 * DASD_3990_ERP_INV_FORMAT1244 *1245 * DESCRIPTION1246 * Handles 24 byte 'Invalid Track Format' error.1247 *1248 * PARAMETER1249 * erp current erp_head1250 * RETURN VALUES1251 * erp new erp_head - pointer to new ERP1252 */1253static struct dasd_ccw_req *1254dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense)1255{1256 1257 struct dasd_device *device = erp->startdev;1258 1259 erp->function = dasd_3990_erp_inv_format;1260 1261 if (sense[2] & SNS2_ENV_DATA_PRESENT) {1262 1263 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1264 "Track format error when destaging or "1265 "staging data");1266 1267 dasd_3990_handle_env_data(erp, sense);1268 1269 erp = dasd_3990_erp_action_4(erp, sense);1270 1271 } else {1272 dev_err(&device->cdev->dev, "Track format is not valid\n");1273 erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);1274 }1275 1276 return erp;1277 1278} /* end dasd_3990_erp_inv_format */1279 1280/*1281 * DASD_3990_ERP_EOC1282 *1283 * DESCRIPTION1284 * Handles 24 byte 'End-of-Cylinder' error.1285 *1286 * PARAMETER1287 * erp already added default erp1288 * RETURN VALUES1289 * erp pointer to original (failed) cqr.1290 */1291static struct dasd_ccw_req *1292dasd_3990_erp_EOC(struct dasd_ccw_req * default_erp, char *sense)1293{1294 1295 struct dasd_device *device = default_erp->startdev;1296 1297 dev_err(&device->cdev->dev,1298 "The cylinder data for accessing the DASD is inconsistent\n");1299 1300 /* implement action 7 - BUG */1301 return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);1302 1303} /* end dasd_3990_erp_EOC */1304 1305/*1306 * DASD_3990_ERP_ENV_DATA1307 *1308 * DESCRIPTION1309 * Handles 24 byte 'Environmental-Data Present' error.1310 *1311 * PARAMETER1312 * erp current erp_head1313 * RETURN VALUES1314 * erp new erp_head - pointer to new ERP1315 */1316static struct dasd_ccw_req *1317dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense)1318{1319 1320 struct dasd_device *device = erp->startdev;1321 1322 erp->function = dasd_3990_erp_env_data;1323 1324 DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Environmental data present");1325 1326 dasd_3990_handle_env_data(erp, sense);1327 1328 /* don't retry on disabled interface */1329 if (sense[7] != 0x0F) {1330 erp = dasd_3990_erp_action_4(erp, sense);1331 } else {1332 erp->status = DASD_CQR_FILLED;1333 }1334 1335 return erp;1336 1337} /* end dasd_3990_erp_env_data */1338 1339/*1340 * DASD_3990_ERP_NO_REC1341 *1342 * DESCRIPTION1343 * Handles 24 byte 'No Record Found' error.1344 *1345 * PARAMETER1346 * erp already added default ERP1347 *1348 * RETURN VALUES1349 * erp new erp_head - pointer to new ERP1350 */1351static struct dasd_ccw_req *1352dasd_3990_erp_no_rec(struct dasd_ccw_req * default_erp, char *sense)1353{1354 1355 struct dasd_device *device = default_erp->startdev;1356 1357 /*1358 * In some cases the 'No Record Found' error might be expected and1359 * log messages shouldn't be written then.1360 * Check if the according suppress bit is set.1361 */1362 if (!test_bit(DASD_CQR_SUPPRESS_NRF, &default_erp->flags))1363 dev_err(&device->cdev->dev,1364 "The specified record was not found\n");1365 1366 return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);1367 1368} /* end dasd_3990_erp_no_rec */1369 1370/*1371 * DASD_3990_ERP_FILE_PROT1372 *1373 * DESCRIPTION1374 * Handles 24 byte 'File Protected' error.1375 * Note: Seek related recovery is not implemented because1376 * wee don't use the seek command yet.1377 *1378 * PARAMETER1379 * erp current erp_head1380 * RETURN VALUES1381 * erp new erp_head - pointer to new ERP1382 */1383static struct dasd_ccw_req *1384dasd_3990_erp_file_prot(struct dasd_ccw_req * erp)1385{1386 1387 struct dasd_device *device = erp->startdev;1388 1389 dev_err(&device->cdev->dev,1390 "Accessing the DASD failed because of a hardware error\n");1391 1392 return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);1393 1394} /* end dasd_3990_erp_file_prot */1395 1396/*1397 * DASD_3990_ERP_INSPECT_ALIAS1398 *1399 * DESCRIPTION1400 * Checks if the original request was started on an alias device.1401 * If yes, it modifies the original and the erp request so that1402 * the erp request can be started on a base device.1403 *1404 * PARAMETER1405 * erp pointer to the currently created default ERP1406 *1407 * RETURN VALUES1408 * erp pointer to the modified ERP, or NULL1409 */1410 1411static struct dasd_ccw_req *dasd_3990_erp_inspect_alias(1412 struct dasd_ccw_req *erp)1413{1414 struct dasd_ccw_req *cqr = erp->refers;1415 char *sense;1416 1417 if (cqr->block &&1418 (cqr->block->base != cqr->startdev)) {1419 1420 sense = dasd_get_sense(&erp->refers->irb);1421 /*1422 * dynamic pav may have changed base alias mapping1423 */1424 if (!test_bit(DASD_FLAG_OFFLINE, &cqr->startdev->flags) && sense1425 && (sense[0] == 0x10) && (sense[7] == 0x0F)1426 && (sense[8] == 0x67)) {1427 /*1428 * remove device from alias handling to prevent new1429 * requests from being scheduled on the1430 * wrong alias device1431 */1432 dasd_alias_remove_device(cqr->startdev);1433 1434 /* schedule worker to reload device */1435 dasd_reload_device(cqr->startdev);1436 }1437 1438 if (cqr->startdev->features & DASD_FEATURE_ERPLOG) {1439 DBF_DEV_EVENT(DBF_ERR, cqr->startdev,1440 "ERP on alias device for request %p,"1441 " recover on base device %s", cqr,1442 dev_name(&cqr->block->base->cdev->dev));1443 }1444 dasd_eckd_reset_ccw_to_base_io(cqr);1445 erp->startdev = cqr->block->base;1446 erp->function = dasd_3990_erp_inspect_alias;1447 return erp;1448 } else1449 return NULL;1450}1451 1452 1453/*1454 * DASD_3990_ERP_INSPECT_241455 *1456 * DESCRIPTION1457 * Does a detailed inspection of the 24 byte sense data1458 * and sets up a related error recovery action.1459 *1460 * PARAMETER1461 * sense sense data of the actual error1462 * erp pointer to the currently created default ERP1463 *1464 * RETURN VALUES1465 * erp pointer to the (addtitional) ERP1466 */1467static struct dasd_ccw_req *1468dasd_3990_erp_inspect_24(struct dasd_ccw_req * erp, char *sense)1469{1470 1471 struct dasd_ccw_req *erp_filled = NULL;1472 1473 /* Check sense for .... */1474 /* 'Command Reject' */1475 if ((erp_filled == NULL) && (sense[0] & SNS0_CMD_REJECT)) {1476 erp_filled = dasd_3990_erp_com_rej(erp, sense);1477 }1478 /* 'Intervention Required' */1479 if ((erp_filled == NULL) && (sense[0] & SNS0_INTERVENTION_REQ)) {1480 erp_filled = dasd_3990_erp_int_req(erp);1481 }1482 /* 'Bus Out Parity Check' */1483 if ((erp_filled == NULL) && (sense[0] & SNS0_BUS_OUT_CHECK)) {1484 erp_filled = dasd_3990_erp_bus_out(erp);1485 }1486 /* 'Equipment Check' */1487 if ((erp_filled == NULL) && (sense[0] & SNS0_EQUIPMENT_CHECK)) {1488 erp_filled = dasd_3990_erp_equip_check(erp, sense);1489 }1490 /* 'Data Check' */1491 if ((erp_filled == NULL) && (sense[0] & SNS0_DATA_CHECK)) {1492 erp_filled = dasd_3990_erp_data_check(erp, sense);1493 }1494 /* 'Overrun' */1495 if ((erp_filled == NULL) && (sense[0] & SNS0_OVERRUN)) {1496 erp_filled = dasd_3990_erp_overrun(erp, sense);1497 }1498 /* 'Invalid Track Format' */1499 if ((erp_filled == NULL) && (sense[1] & SNS1_INV_TRACK_FORMAT)) {1500 erp_filled = dasd_3990_erp_inv_format(erp, sense);1501 }1502 /* 'End-of-Cylinder' */1503 if ((erp_filled == NULL) && (sense[1] & SNS1_EOC)) {1504 erp_filled = dasd_3990_erp_EOC(erp, sense);1505 }1506 /* 'Environmental Data' */1507 if ((erp_filled == NULL) && (sense[2] & SNS2_ENV_DATA_PRESENT)) {1508 erp_filled = dasd_3990_erp_env_data(erp, sense);1509 }1510 /* 'No Record Found' */1511 if ((erp_filled == NULL) && (sense[1] & SNS1_NO_REC_FOUND)) {1512 erp_filled = dasd_3990_erp_no_rec(erp, sense);1513 }1514 /* 'File Protected' */1515 if ((erp_filled == NULL) && (sense[1] & SNS1_FILE_PROTECTED)) {1516 erp_filled = dasd_3990_erp_file_prot(erp);1517 }1518 /* other (unknown) error - do default ERP */1519 if (erp_filled == NULL) {1520 1521 erp_filled = erp;1522 }1523 1524 return erp_filled;1525 1526} /* END dasd_3990_erp_inspect_24 */1527 1528/*1529 *****************************************************************************1530 * 32 byte sense ERP functions (only)1531 *****************************************************************************1532 */1533 1534/*1535 * DASD_3990_ERPACTION_10_321536 *1537 * DESCRIPTION1538 * Handles 32 byte 'Action 10' of Single Program Action Codes.1539 * Just retry and if retry doesn't work, return with error.1540 *1541 * PARAMETER1542 * erp current erp_head1543 * sense current sense data1544 * RETURN VALUES1545 * erp modified erp_head1546 */1547static struct dasd_ccw_req *1548dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense)1549{1550 1551 struct dasd_device *device = erp->startdev;1552 1553 erp->retries = 256;1554 erp->function = dasd_3990_erp_action_10_32;1555 1556 DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Perform logging requested");1557 1558 return erp;1559 1560} /* end dasd_3990_erp_action_10_32 */1561 1562/*1563 * DASD_3990_ERP_ACTION_1B_321564 *1565 * DESCRIPTION1566 * Handles 32 byte 'Action 1B' of Single Program Action Codes.1567 * A write operation could not be finished because of an unexpected1568 * condition.1569 * The already created 'default erp' is used to get the link to1570 * the erp chain, but it can not be used for this recovery1571 * action because it contains no DE/LO data space.1572 *1573 * PARAMETER1574 * default_erp already added default erp.1575 * sense current sense data1576 *1577 * RETURN VALUES1578 * erp new erp or1579 * default_erp in case of imprecise ending or error1580 */1581static struct dasd_ccw_req *1582dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)1583{1584 1585 struct dasd_device *device = default_erp->startdev;1586 dma32_t cpa = 0;1587 struct dasd_ccw_req *cqr;1588 struct dasd_ccw_req *erp;1589 struct DE_eckd_data *DE_data;1590 struct PFX_eckd_data *PFX_data;1591 char *LO_data; /* LO_eckd_data_t */1592 struct ccw1 *ccw, *oldccw;1593 1594 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1595 "Write not finished because of unexpected condition");1596 1597 default_erp->function = dasd_3990_erp_action_1B_32;1598 1599 /* determine the original cqr */1600 cqr = default_erp;1601 1602 while (cqr->refers != NULL) {1603 cqr = cqr->refers;1604 }1605 1606 if (scsw_is_tm(&cqr->irb.scsw)) {1607 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1608 "32 bit sense, action 1B is not defined"1609 " in transport mode - just retry");1610 return default_erp;1611 }1612 1613 /* for imprecise ending just do default erp */1614 if (sense[1] & 0x01) {1615 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1616 "Imprecise ending is set - just retry");1617 1618 return default_erp;1619 }1620 1621 /* determine the address of the CCW to be restarted */1622 /* Imprecise ending is not set -> addr from IRB-SCSW */1623 cpa = default_erp->refers->irb.scsw.cmd.cpa;1624 1625 if (cpa == 0) {1626 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1627 "Unable to determine address of the CCW "1628 "to be restarted");1629 1630 return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);1631 }1632 1633 /* Build new ERP request including DE/LO */1634 erp = dasd_alloc_erp_request(cqr->magic,1635 2 + 1,/* DE/LO + TIC */1636 sizeof(struct DE_eckd_data) +1637 sizeof(struct LO_eckd_data), device);1638 1639 if (IS_ERR(erp)) {1640 DBF_DEV_EVENT(DBF_ERR, device, "%s",1641 "Unable to allocate ERP request (1B 32)");1642 return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);1643 }1644 1645 /* use original DE */1646 DE_data = erp->data;1647 oldccw = cqr->cpaddr;1648 if (oldccw->cmd_code == DASD_ECKD_CCW_PFX) {1649 PFX_data = cqr->data;1650 memcpy(DE_data, &PFX_data->define_extent,1651 sizeof(struct DE_eckd_data));1652 } else1653 memcpy(DE_data, cqr->data, sizeof(struct DE_eckd_data));1654 1655 /* create LO */1656 LO_data = erp->data + sizeof(struct DE_eckd_data);1657 1658 if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) {1659 /* should not */1660 return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);1661 }1662 1663 if ((sense[7] & 0x3F) == 0x01) {1664 /* operation code is WRITE DATA -> data area orientation */1665 LO_data[0] = 0x81;1666 1667 } else if ((sense[7] & 0x3F) == 0x03) {1668 /* operation code is FORMAT WRITE -> index orientation */1669 LO_data[0] = 0xC3;1670 1671 } else {1672 LO_data[0] = sense[7]; /* operation */1673 }1674 1675 LO_data[1] = sense[8]; /* auxiliary */1676 LO_data[2] = sense[9];1677 LO_data[3] = sense[3]; /* count */1678 LO_data[4] = sense[29]; /* seek_addr.cyl */1679 LO_data[5] = sense[30]; /* seek_addr.cyl 2nd byte */1680 LO_data[7] = sense[31]; /* seek_addr.head 2nd byte */1681 1682 memcpy(&(LO_data[8]), &(sense[11]), 8);1683 1684 /* create DE ccw */1685 ccw = erp->cpaddr;1686 memset(ccw, 0, sizeof(struct ccw1));1687 ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT;1688 ccw->flags = CCW_FLAG_CC;1689 ccw->count = 16;1690 ccw->cda = virt_to_dma32(DE_data);1691 1692 /* create LO ccw */1693 ccw++;1694 memset(ccw, 0, sizeof(struct ccw1));1695 ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;1696 ccw->flags = CCW_FLAG_CC;1697 ccw->count = 16;1698 ccw->cda = virt_to_dma32(LO_data);1699 1700 /* TIC to the failed ccw */1701 ccw++;1702 ccw->cmd_code = CCW_CMD_TIC;1703 ccw->cda = cpa;1704 1705 /* fill erp related fields */1706 erp->flags = default_erp->flags;1707 erp->function = dasd_3990_erp_action_1B_32;1708 erp->refers = default_erp->refers;1709 erp->startdev = device;1710 erp->memdev = device;1711 erp->magic = default_erp->magic;1712 erp->expires = default_erp->expires;1713 erp->retries = 256;1714 erp->buildclk = get_tod_clock();1715 erp->status = DASD_CQR_FILLED;1716 1717 /* remove the default erp */1718 dasd_free_erp_request(default_erp, device);1719 1720 return erp;1721 1722} /* end dasd_3990_erp_action_1B_32 */1723 1724/*1725 * DASD_3990_UPDATE_1B1726 *1727 * DESCRIPTION1728 * Handles the update to the 32 byte 'Action 1B' of Single Program1729 * Action Codes in case the first action was not successful.1730 * The already created 'previous_erp' is the currently not successful1731 * ERP.1732 *1733 * PARAMETER1734 * previous_erp already created previous erp.1735 * sense current sense data1736 * RETURN VALUES1737 * erp modified erp1738 */1739static struct dasd_ccw_req *1740dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)1741{1742 1743 struct dasd_device *device = previous_erp->startdev;1744 dma32_t cpa = 0;1745 struct dasd_ccw_req *cqr;1746 struct dasd_ccw_req *erp;1747 char *LO_data; /* struct LO_eckd_data */1748 struct ccw1 *ccw;1749 1750 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1751 "Write not finished because of unexpected condition"1752 " - follow on");1753 1754 /* determine the original cqr */1755 cqr = previous_erp;1756 1757 while (cqr->refers != NULL) {1758 cqr = cqr->refers;1759 }1760 1761 if (scsw_is_tm(&cqr->irb.scsw)) {1762 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1763 "32 bit sense, action 1B, update,"1764 " in transport mode - just retry");1765 return previous_erp;1766 }1767 1768 /* for imprecise ending just do default erp */1769 if (sense[1] & 0x01) {1770 DBF_DEV_EVENT(DBF_WARNING, device, "%s",1771 "Imprecise ending is set - just retry");1772 1773 previous_erp->status = DASD_CQR_FILLED;1774 1775 return previous_erp;1776 }1777 1778 /* determine the address of the CCW to be restarted */1779 /* Imprecise ending is not set -> addr from IRB-SCSW */1780 cpa = previous_erp->irb.scsw.cmd.cpa;1781 1782 if (cpa == 0) {1783 dev_err(&device->cdev->dev,1784 "Unable to determine address of to be restarted CCW\n");1785 1786 previous_erp->status = DASD_CQR_FAILED;1787 1788 return previous_erp;1789 }1790 1791 erp = previous_erp;1792 1793 /* update the LO with the new returned sense data */1794 LO_data = erp->data + sizeof(struct DE_eckd_data);1795 1796 if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) {1797 /* should not happen */1798 previous_erp->status = DASD_CQR_FAILED;1799 1800 return previous_erp;1801 }1802 1803 if ((sense[7] & 0x3F) == 0x01) {1804 /* operation code is WRITE DATA -> data area orientation */1805 LO_data[0] = 0x81;1806 1807 } else if ((sense[7] & 0x3F) == 0x03) {1808 /* operation code is FORMAT WRITE -> index orientation */1809 LO_data[0] = 0xC3;1810 1811 } else {1812 LO_data[0] = sense[7]; /* operation */1813 }1814 1815 LO_data[1] = sense[8]; /* auxiliary */1816 LO_data[2] = sense[9];1817 LO_data[3] = sense[3]; /* count */1818 LO_data[4] = sense[29]; /* seek_addr.cyl */1819 LO_data[5] = sense[30]; /* seek_addr.cyl 2nd byte */1820 LO_data[7] = sense[31]; /* seek_addr.head 2nd byte */1821 1822 memcpy(&(LO_data[8]), &(sense[11]), 8);1823 1824 /* TIC to the failed ccw */1825 ccw = erp->cpaddr; /* addr of DE ccw */1826 ccw++; /* addr of LE ccw */1827 ccw++; /* addr of TIC ccw */1828 ccw->cda = cpa;1829 1830 erp->status = DASD_CQR_FILLED;1831 1832 return erp;1833 1834} /* end dasd_3990_update_1B */1835 1836/*1837 * DASD_3990_ERP_COMPOUND_RETRY1838 *1839 * DESCRIPTION1840 * Handles the compound ERP action retry code.1841 * NOTE: At least one retry is done even if zero is specified1842 * by the sense data. This makes enqueueing of the request1843 * easier.1844 *1845 * PARAMETER1846 * sense sense data of the actual error1847 * erp pointer to the currently created ERP1848 *1849 * RETURN VALUES1850 * erp modified ERP pointer1851 *1852 */1853static void1854dasd_3990_erp_compound_retry(struct dasd_ccw_req * erp, char *sense)1855{1856 1857 switch (sense[25] & 0x03) {1858 case 0x00: /* no not retry */1859 erp->retries = 1;1860 break;1861 1862 case 0x01: /* retry 2 times */1863 erp->retries = 2;1864 break;1865 1866 case 0x02: /* retry 10 times */1867 erp->retries = 10;1868 break;1869 1870 case 0x03: /* retry 256 times */1871 erp->retries = 256;1872 break;1873 1874 default:1875 BUG();1876 }1877 1878 erp->function = dasd_3990_erp_compound_retry;1879 1880} /* end dasd_3990_erp_compound_retry */1881 1882/*1883 * DASD_3990_ERP_COMPOUND_PATH1884 *1885 * DESCRIPTION1886 * Handles the compound ERP action for retry on alternate1887 * channel path.1888 *1889 * PARAMETER1890 * sense sense data of the actual error1891 * erp pointer to the currently created ERP1892 *1893 * RETURN VALUES1894 * erp modified ERP pointer1895 *1896 */1897static void1898dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense)1899{1900 if (sense[25] & DASD_SENSE_BIT_3) {1901 dasd_3990_erp_alternate_path(erp);1902 1903 if (erp->status == DASD_CQR_FAILED &&1904 !test_bit(DASD_CQR_VERIFY_PATH, &erp->flags)) {1905 /* reset the lpm and the status to be able to1906 * try further actions. */1907 erp->lpm = dasd_path_get_opm(erp->startdev);1908 erp->status = DASD_CQR_NEED_ERP;1909 }1910 }1911 1912 erp->function = dasd_3990_erp_compound_path;1913 1914} /* end dasd_3990_erp_compound_path */1915 1916/*1917 * DASD_3990_ERP_COMPOUND_CODE1918 *1919 * DESCRIPTION1920 * Handles the compound ERP action for retry code.1921 *1922 * PARAMETER1923 * sense sense data of the actual error1924 * erp pointer to the currently created ERP1925 *1926 * RETURN VALUES1927 * erp NEW ERP pointer1928 *1929 */1930static struct dasd_ccw_req *1931dasd_3990_erp_compound_code(struct dasd_ccw_req * erp, char *sense)1932{1933 1934 if (sense[25] & DASD_SENSE_BIT_2) {1935 1936 switch (sense[28]) {1937 case 0x17:1938 /* issue a Diagnostic Control command with an1939 * Inhibit Write subcommand and controller modifier */1940 erp = dasd_3990_erp_DCTL(erp, 0x20);1941 break;1942 1943 case 0x25:1944 /* wait for 5 seconds and retry again */1945 erp->retries = 1;1946 1947 dasd_3990_erp_block_queue (erp, 5*HZ);1948 break;1949 1950 default:1951 /* should not happen - continue */1952 break;1953 }1954 }1955 1956 erp->function = dasd_3990_erp_compound_code;1957 1958 return erp;1959 1960} /* end dasd_3990_erp_compound_code */1961 1962/*1963 * DASD_3990_ERP_COMPOUND_CONFIG1964 *1965 * DESCRIPTION1966 * Handles the compound ERP action for configuration1967 * dependent error.1968 * Note: duplex handling is not implemented (yet).1969 *1970 * PARAMETER1971 * sense sense data of the actual error1972 * erp pointer to the currently created ERP1973 *1974 * RETURN VALUES1975 * erp modified ERP pointer1976 *1977 */1978static void1979dasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense)1980{1981 1982 if ((sense[25] & DASD_SENSE_BIT_1) && (sense[26] & DASD_SENSE_BIT_2)) {1983 struct dasd_device *device = erp->startdev;1984 dev_err(&device->cdev->dev,1985 "Compound configuration error occurred\n");1986 }1987 1988 erp->function = dasd_3990_erp_compound_config;1989 1990} /* end dasd_3990_erp_compound_config */1991 1992/*1993 * DASD_3990_ERP_COMPOUND1994 *1995 * DESCRIPTION1996 * Does the further compound program action if1997 * compound retry was not successful.1998 *1999 * PARAMETER2000 * sense sense data of the actual error2001 * erp pointer to the current (failed) ERP2002 *2003 * RETURN VALUES2004 * erp (additional) ERP pointer2005 *2006 */2007static struct dasd_ccw_req *2008dasd_3990_erp_compound(struct dasd_ccw_req * erp, char *sense)2009{2010 2011 if ((erp->function == dasd_3990_erp_compound_retry) &&2012 (erp->status == DASD_CQR_NEED_ERP)) {2013 2014 dasd_3990_erp_compound_path(erp, sense);2015 }2016 2017 if ((erp->function == dasd_3990_erp_compound_path) &&2018 (erp->status == DASD_CQR_NEED_ERP)) {2019 2020 erp = dasd_3990_erp_compound_code(erp, sense);2021 }2022 2023 if ((erp->function == dasd_3990_erp_compound_code) &&2024 (erp->status == DASD_CQR_NEED_ERP)) {2025 2026 dasd_3990_erp_compound_config(erp, sense);2027 }2028 2029 /* if no compound action ERP specified, the request failed */2030 if (erp->status == DASD_CQR_NEED_ERP)2031 erp->status = DASD_CQR_FAILED;2032 2033 return erp;2034 2035} /* end dasd_3990_erp_compound */2036 2037/*2038 *DASD_3990_ERP_HANDLE_SIM2039 *2040 *DESCRIPTION2041 * inspects the SIM SENSE data and starts an appropriate action2042 *2043 * PARAMETER2044 * sense sense data of the actual error2045 *2046 * RETURN VALUES2047 * none2048 */2049void2050dasd_3990_erp_handle_sim(struct dasd_device *device, char *sense)2051{2052 /* print message according to log or message to operator mode */2053 if ((sense[24] & DASD_SIM_MSG_TO_OP) || (sense[1] & 0x10)) {2054 /* print SIM SRC from RefCode */2055 dev_err(&device->cdev->dev, "SIM - SRC: "2056 "%02x%02x%02x%02x\n", sense[22],2057 sense[23], sense[11], sense[12]);2058 } else if (sense[24] & DASD_SIM_LOG) {2059 /* print SIM SRC Refcode */2060 dev_warn(&device->cdev->dev, "log SIM - SRC: "2061 "%02x%02x%02x%02x\n", sense[22],2062 sense[23], sense[11], sense[12]);2063 }2064}2065 2066/*2067 * DASD_3990_ERP_INSPECT_322068 *2069 * DESCRIPTION2070 * Does a detailed inspection of the 32 byte sense data2071 * and sets up a related error recovery action.2072 *2073 * PARAMETER2074 * sense sense data of the actual error2075 * erp pointer to the currently created default ERP2076 *2077 * RETURN VALUES2078 * erp_filled pointer to the ERP2079 *2080 */2081static struct dasd_ccw_req *2082dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)2083{2084 2085 struct dasd_device *device = erp->startdev;2086 2087 erp->function = dasd_3990_erp_inspect_32;2088 2089 /* check for SIM sense data */2090 if ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)2091 dasd_3990_erp_handle_sim(device, sense);2092 2093 if (sense[25] & DASD_SENSE_BIT_0) {2094 2095 /* compound program action codes (byte25 bit 0 == '1') */2096 dasd_3990_erp_compound_retry(erp, sense);2097 2098 } else {2099 2100 /* single program action codes (byte25 bit 0 == '0') */2101 switch (sense[25]) {2102 2103 case 0x00: /* success - use default ERP for retries */2104 DBF_DEV_EVENT(DBF_DEBUG, device, "%s",2105 "ERP called for successful request"2106 " - just retry");2107 break;2108 2109 case 0x01: /* fatal error */2110 dev_err(&device->cdev->dev,2111 "ERP failed for the DASD\n");2112 2113 erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);2114 break;2115 2116 case 0x02: /* intervention required */2117 case 0x03: /* intervention required during dual copy */2118 erp = dasd_3990_erp_int_req(erp);2119 break;2120 2121 case 0x0F:2122 dev_err(&device->cdev->dev,2123 "Update write command error occurred\n");2124 2125 erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);2126 break;2127 2128 case 0x10: /* logging required for other channel program */2129 erp = dasd_3990_erp_action_10_32(erp, sense);2130 break;2131 2132 case 0x15:2133 dev_err(&device->cdev->dev,2134 "Track outside defined extent error occurred\n");2135 2136 erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);2137 break;2138 2139 case 0x1B: /* unexpected condition during write */2140 2141 erp = dasd_3990_erp_action_1B_32(erp, sense);2142 break;2143 2144 case 0x1C: /* invalid data */2145 dev_emerg(&device->cdev->dev,2146 "Data recovered during retry with PCI "2147 "fetch mode active\n");2148 2149 /* not possible to handle this situation in Linux */2150 panic2151 ("Invalid data - No way to inform application "2152 "about the possibly incorrect data");2153 break;2154 2155 case 0x1D: /* state-change pending */2156 DBF_DEV_EVENT(DBF_WARNING, device, "%s",2157 "A State change pending condition exists "2158 "for the subsystem or device");2159 2160 erp = dasd_3990_erp_action_4(erp, sense);2161 break;2162 2163 case 0x1E: /* busy */2164 DBF_DEV_EVENT(DBF_WARNING, device, "%s",2165 "Busy condition exists "2166 "for the subsystem or device");2167 erp = dasd_3990_erp_action_4(erp, sense);2168 break;2169 2170 default: /* all others errors - default erp */2171 break;2172 }2173 }2174 2175 return erp;2176 2177} /* end dasd_3990_erp_inspect_32 */2178 2179static void dasd_3990_erp_disable_path(struct dasd_device *device, __u8 lpum)2180{2181 int pos = pathmask_to_pos(lpum);2182 2183 if (!(device->features & DASD_FEATURE_PATH_AUTODISABLE)) {2184 dev_err(&device->cdev->dev,2185 "Path %x.%02x (pathmask %02x) is operational despite excessive IFCCs\n",2186 device->path[pos].cssid, device->path[pos].chpid, lpum);2187 goto out;2188 }2189 2190 /* no remaining path, cannot disable */2191 if (!(dasd_path_get_opm(device) & ~lpum)) {2192 dev_err(&device->cdev->dev,2193 "Last path %x.%02x (pathmask %02x) is operational despite excessive IFCCs\n",2194 device->path[pos].cssid, device->path[pos].chpid, lpum);2195 goto out;2196 }2197 2198 dev_err(&device->cdev->dev,2199 "Path %x.%02x (pathmask %02x) is disabled - IFCC threshold exceeded\n",2200 device->path[pos].cssid, device->path[pos].chpid, lpum);2201 dasd_path_remove_opm(device, lpum);2202 dasd_path_add_ifccpm(device, lpum);2203 2204out:2205 device->path[pos].errorclk = 0;2206 atomic_set(&device->path[pos].error_count, 0);2207}2208 2209static void dasd_3990_erp_account_error(struct dasd_ccw_req *erp)2210{2211 struct dasd_device *device = erp->startdev;2212 __u8 lpum = erp->refers->irb.esw.esw1.lpum;2213 int pos = pathmask_to_pos(lpum);2214 unsigned long clk;2215 2216 if (!device->path_thrhld)2217 return;2218 2219 clk = get_tod_clock();2220 /*2221 * check if the last error is longer ago than the timeout,2222 * if so reset error state2223 */2224 if ((tod_to_ns(clk - device->path[pos].errorclk) / NSEC_PER_SEC)2225 >= device->path_interval) {2226 atomic_set(&device->path[pos].error_count, 0);2227 device->path[pos].errorclk = 0;2228 }2229 atomic_inc(&device->path[pos].error_count);2230 device->path[pos].errorclk = clk;2231 /* threshold exceeded disable path if possible */2232 if (atomic_read(&device->path[pos].error_count) >=2233 device->path_thrhld)2234 dasd_3990_erp_disable_path(device, lpum);2235}2236 2237/*2238 *****************************************************************************2239 * main ERP control functions (24 and 32 byte sense)2240 *****************************************************************************2241 */2242 2243/*2244 * DASD_3990_ERP_CONTROL_CHECK2245 *2246 * DESCRIPTION2247 * Does a generic inspection if a control check occurred and sets up2248 * the related error recovery procedure2249 *2250 * PARAMETER2251 * erp pointer to the currently created default ERP2252 *2253 * RETURN VALUES2254 * erp_filled pointer to the erp2255 */2256 2257static struct dasd_ccw_req *2258dasd_3990_erp_control_check(struct dasd_ccw_req *erp)2259{2260 struct dasd_device *device = erp->startdev;2261 2262 if (scsw_cstat(&erp->refers->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK2263 | SCHN_STAT_CHN_CTRL_CHK)) {2264 DBF_DEV_EVENT(DBF_WARNING, device, "%s",2265 "channel or interface control check");2266 dasd_3990_erp_account_error(erp);2267 erp = dasd_3990_erp_action_4(erp, NULL);2268 }2269 return erp;2270}2271 2272/*2273 * DASD_3990_ERP_INSPECT2274 *2275 * DESCRIPTION2276 * Does a detailed inspection for sense data by calling either2277 * the 24-byte or the 32-byte inspection routine.2278 *2279 * PARAMETER2280 * erp pointer to the currently created default ERP2281 * RETURN VALUES2282 * erp_new contens was possibly modified2283 */2284static struct dasd_ccw_req *2285dasd_3990_erp_inspect(struct dasd_ccw_req *erp)2286{2287 2288 struct dasd_ccw_req *erp_new = NULL;2289 char *sense;2290 2291 /* if this problem occurred on an alias retry on base */2292 erp_new = dasd_3990_erp_inspect_alias(erp);2293 if (erp_new)2294 return erp_new;2295 2296 /* sense data are located in the refers record of the2297 * already set up new ERP !2298 * check if concurrent sens is available2299 */2300 sense = dasd_get_sense(&erp->refers->irb);2301 if (!sense)2302 erp_new = dasd_3990_erp_control_check(erp);2303 /* distinguish between 24 and 32 byte sense data */2304 else if (sense[27] & DASD_SENSE_BIT_0) {2305 2306 /* inspect the 24 byte sense data */2307 erp_new = dasd_3990_erp_inspect_24(erp, sense);2308 2309 } else {2310 2311 /* inspect the 32 byte sense data */2312 erp_new = dasd_3990_erp_inspect_32(erp, sense);2313 2314 } /* end distinguish between 24 and 32 byte sense data */2315 2316 return erp_new;2317}2318 2319/*2320 * DASD_3990_ERP_ADD_ERP2321 *2322 * DESCRIPTION2323 * This function adds an additional request block (ERP) to the head of2324 * the given cqr (or erp).2325 * For a command mode cqr the erp is initialized as an default erp2326 * (retry TIC).2327 * For transport mode we make a copy of the original TCW (points to2328 * the original TCCB, TIDALs, etc.) but give it a fresh2329 * TSB so the original sense data will not be changed.2330 *2331 * PARAMETER2332 * cqr head of the current ERP-chain (or single cqr if2333 * first error)2334 * RETURN VALUES2335 * erp pointer to new ERP-chain head2336 */2337static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr)2338{2339 2340 struct dasd_device *device = cqr->startdev;2341 struct ccw1 *ccw;2342 struct dasd_ccw_req *erp;2343 int cplength, datasize;2344 struct tcw *tcw;2345 struct tsb *tsb;2346 2347 if (cqr->cpmode == 1) {2348 cplength = 0;2349 /* TCW needs to be 64 byte aligned, so leave enough room */2350 datasize = 64 + sizeof(struct tcw) + sizeof(struct tsb);2351 } else {2352 cplength = 2;2353 datasize = 0;2354 }2355 2356 /* allocate additional request block */2357 erp = dasd_alloc_erp_request(cqr->magic,2358 cplength, datasize, device);2359 if (IS_ERR(erp)) {2360 if (cqr->retries <= 0) {2361 DBF_DEV_EVENT(DBF_ERR, device, "%s",2362 "Unable to allocate ERP request");2363 cqr->status = DASD_CQR_FAILED;2364 cqr->stopclk = get_tod_clock();2365 } else {2366 DBF_DEV_EVENT(DBF_ERR, device,2367 "Unable to allocate ERP request "2368 "(%i retries left)",2369 cqr->retries);2370 dasd_block_set_timer(device->block, (HZ << 3));2371 }2372 return erp;2373 }2374 2375 ccw = cqr->cpaddr;2376 if (cqr->cpmode == 1) {2377 /* make a shallow copy of the original tcw but set new tsb */2378 erp->cpmode = 1;2379 erp->cpaddr = PTR_ALIGN(erp->data, 64);2380 tcw = erp->cpaddr;2381 tsb = (struct tsb *) &tcw[1];2382 *tcw = *((struct tcw *)cqr->cpaddr);2383 tcw->tsb = virt_to_dma64(tsb);2384 } else if (ccw->cmd_code == DASD_ECKD_CCW_PSF) {2385 /* PSF cannot be chained from NOOP/TIC */2386 erp->cpaddr = cqr->cpaddr;2387 } else {2388 /* initialize request with default TIC to current ERP/CQR */2389 ccw = erp->cpaddr;2390 ccw->cmd_code = CCW_CMD_NOOP;2391 ccw->flags = CCW_FLAG_CC;2392 ccw++;2393 ccw->cmd_code = CCW_CMD_TIC;2394 ccw->cda = virt_to_dma32(cqr->cpaddr);2395 }2396 2397 erp->flags = cqr->flags;2398 erp->function = dasd_3990_erp_add_erp;2399 erp->refers = cqr;2400 erp->startdev = device;2401 erp->memdev = device;2402 erp->block = cqr->block;2403 erp->magic = cqr->magic;2404 erp->expires = cqr->expires;2405 erp->retries = device->default_retries;2406 erp->buildclk = get_tod_clock();2407 erp->status = DASD_CQR_FILLED;2408 2409 return erp;2410}2411 2412/*2413 * DASD_3990_ERP_ADDITIONAL_ERP2414 *2415 * DESCRIPTION2416 * An additional ERP is needed to handle the current error.2417 * Add ERP to the head of the ERP-chain containing the ERP processing2418 * determined based on the sense data.2419 *2420 * PARAMETER2421 * cqr head of the current ERP-chain (or single cqr if2422 * first error)2423 *2424 * RETURN VALUES2425 * erp pointer to new ERP-chain head2426 */2427static struct dasd_ccw_req *2428dasd_3990_erp_additional_erp(struct dasd_ccw_req * cqr)2429{2430 2431 struct dasd_ccw_req *erp = NULL;2432 2433 /* add erp and initialize with default TIC */2434 erp = dasd_3990_erp_add_erp(cqr);2435 2436 if (IS_ERR(erp))2437 return erp;2438 2439 /* inspect sense, determine specific ERP if possible */2440 if (erp != cqr) {2441 2442 erp = dasd_3990_erp_inspect(erp);2443 }2444 2445 return erp;2446 2447} /* end dasd_3990_erp_additional_erp */2448 2449/*2450 * DASD_3990_ERP_ERROR_MATCH2451 *2452 * DESCRIPTION2453 * Check if the device status of the given cqr is the same.2454 * This means that the failed CCW and the relevant sense data2455 * must match.2456 * I don't distinguish between 24 and 32 byte sense because in case of2457 * 24 byte sense byte 25 and 27 is set as well.2458 *2459 * PARAMETER2460 * cqr1 first cqr, which will be compared with the2461 * cqr2 second cqr.2462 *2463 * RETURN VALUES2464 * match 'boolean' for match found2465 * returns 1 if match found, otherwise 0.2466 */2467static int dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1,2468 struct dasd_ccw_req *cqr2)2469{2470 char *sense1, *sense2;2471 2472 if (cqr1->startdev != cqr2->startdev)2473 return 0;2474 2475 sense1 = dasd_get_sense(&cqr1->irb);2476 sense2 = dasd_get_sense(&cqr2->irb);2477 2478 /* one request has sense data, the other not -> no match, return 0 */2479 if (!sense1 != !sense2)2480 return 0;2481 /* no sense data in both cases -> check cstat for IFCC */2482 if (!sense1 && !sense2) {2483 if ((scsw_cstat(&cqr1->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK |2484 SCHN_STAT_CHN_CTRL_CHK)) ==2485 (scsw_cstat(&cqr2->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK |2486 SCHN_STAT_CHN_CTRL_CHK)))2487 return 1; /* match with ifcc*/2488 }2489 /* check sense data; byte 0-2,25,27 */2490 if (!(sense1 && sense2 &&2491 (memcmp(sense1, sense2, 3) == 0) &&2492 (sense1[27] == sense2[27]) &&2493 (sense1[25] == sense2[25]))) {2494 2495 return 0; /* sense doesn't match */2496 }2497 2498 return 1; /* match */2499 2500} /* end dasd_3990_erp_error_match */2501 2502/*2503 * DASD_3990_ERP_IN_ERP2504 *2505 * DESCRIPTION2506 * check if the current error already happened before.2507 * quick exit if current cqr is not an ERP (cqr->refers=NULL)2508 *2509 * PARAMETER2510 * cqr failed cqr (either original cqr or already an erp)2511 *2512 * RETURN VALUES2513 * erp erp-pointer to the already defined error2514 * recovery procedure OR2515 * NULL if a 'new' error occurred.2516 */2517static struct dasd_ccw_req *2518dasd_3990_erp_in_erp(struct dasd_ccw_req *cqr)2519{2520 2521 struct dasd_ccw_req *erp_head = cqr, /* save erp chain head */2522 *erp_match = NULL; /* save erp chain head */2523 int match = 0; /* 'boolean' for matching error found */2524 2525 if (cqr->refers == NULL) { /* return if not in erp */2526 return NULL;2527 }2528 2529 /* check the erp/cqr chain for current error */2530 do {2531 match = dasd_3990_erp_error_match(erp_head, cqr->refers);2532 erp_match = cqr; /* save possible matching erp */2533 cqr = cqr->refers; /* check next erp/cqr in queue */2534 2535 } while ((cqr->refers != NULL) && (!match));2536 2537 if (!match) {2538 return NULL; /* no match was found */2539 }2540 2541 return erp_match; /* return address of matching erp */2542 2543} /* END dasd_3990_erp_in_erp */2544 2545/*2546 * DASD_3990_ERP_FURTHER_ERP (24 & 32 byte sense)2547 *2548 * DESCRIPTION2549 * No retry is left for the current ERP. Check what has to be done2550 * with the ERP.2551 * - do further defined ERP action or2552 * - wait for interrupt or2553 * - exit with permanent error2554 *2555 * PARAMETER2556 * erp ERP which is in progress with no retry left2557 *2558 * RETURN VALUES2559 * erp modified/additional ERP2560 */2561static struct dasd_ccw_req *2562dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)2563{2564 2565 struct dasd_device *device = erp->startdev;2566 char *sense = dasd_get_sense(&erp->irb);2567 2568 /* check for 24 byte sense ERP */2569 if ((erp->function == dasd_3990_erp_bus_out) ||2570 (erp->function == dasd_3990_erp_action_1) ||2571 (erp->function == dasd_3990_erp_action_4)) {2572 2573 erp = dasd_3990_erp_action_1(erp);2574 2575 } else if (erp->function == dasd_3990_erp_action_1_sec) {2576 erp = dasd_3990_erp_action_1_sec(erp);2577 } else if (erp->function == dasd_3990_erp_action_5) {2578 2579 /* retries have not been successful */2580 /* prepare erp for retry on different channel path */2581 erp = dasd_3990_erp_action_1(erp);2582 2583 if (sense && !(sense[2] & DASD_SENSE_BIT_0)) {2584 2585 /* issue a Diagnostic Control command with an2586 * Inhibit Write subcommand */2587 2588 switch (sense[25]) {2589 case 0x17:2590 case 0x57:{ /* controller */2591 erp = dasd_3990_erp_DCTL(erp, 0x20);2592 break;2593 }2594 case 0x18:2595 case 0x58:{ /* channel path */2596 erp = dasd_3990_erp_DCTL(erp, 0x40);2597 break;2598 }2599 case 0x19:2600 case 0x59:{ /* storage director */2601 erp = dasd_3990_erp_DCTL(erp, 0x80);2602 break;2603 }2604 default:2605 DBF_DEV_EVENT(DBF_WARNING, device,2606 "invalid subcommand modifier 0x%x "2607 "for Diagnostic Control Command",2608 sense[25]);2609 }2610 }2611 2612 /* check for 32 byte sense ERP */2613 } else if (sense &&2614 ((erp->function == dasd_3990_erp_compound_retry) ||2615 (erp->function == dasd_3990_erp_compound_path) ||2616 (erp->function == dasd_3990_erp_compound_code) ||2617 (erp->function == dasd_3990_erp_compound_config))) {2618 2619 erp = dasd_3990_erp_compound(erp, sense);2620 2621 } else {2622 /*2623 * No retry left and no additional special handling2624 * necessary2625 */2626 dev_err(&device->cdev->dev,2627 "ERP %px has run out of retries and failed\n", erp);2628 2629 erp->status = DASD_CQR_FAILED;2630 }2631 2632 return erp;2633 2634} /* end dasd_3990_erp_further_erp */2635 2636/*2637 * DASD_3990_ERP_HANDLE_MATCH_ERP2638 *2639 * DESCRIPTION2640 * An error occurred again and an ERP has been detected which is already2641 * used to handle this error (e.g. retries).2642 * All prior ERP's are asumed to be successful and therefore removed2643 * from queue.2644 * If retry counter of matching erp is already 0, it is checked if further2645 * action is needed (besides retry) or if the ERP has failed.2646 *2647 * PARAMETER2648 * erp_head first ERP in ERP-chain2649 * erp ERP that handles the actual error.2650 * (matching erp)2651 *2652 * RETURN VALUES2653 * erp modified/additional ERP2654 */2655static struct dasd_ccw_req *2656dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,2657 struct dasd_ccw_req *erp)2658{2659 2660 struct dasd_device *device = erp_head->startdev;2661 struct dasd_ccw_req *erp_done = erp_head; /* finished req */2662 struct dasd_ccw_req *erp_free = NULL; /* req to be freed */2663 2664 /* loop over successful ERPs and remove them from chanq */2665 while (erp_done != erp) {2666 2667 if (erp_done == NULL) /* end of chain reached */2668 panic("Programming error in ERP! The original request was lost\n");2669 2670 /* remove the request from the device queue */2671 list_del(&erp_done->blocklist);2672 2673 erp_free = erp_done;2674 erp_done = erp_done->refers;2675 2676 /* free the finished erp request */2677 dasd_free_erp_request(erp_free, erp_free->memdev);2678 2679 } /* end while */2680 2681 if (erp->retries > 0) {2682 2683 char *sense = dasd_get_sense(&erp->refers->irb);2684 2685 /* check for special retries */2686 if (sense && erp->function == dasd_3990_erp_action_4) {2687 2688 erp = dasd_3990_erp_action_4(erp, sense);2689 2690 } else if (sense &&2691 erp->function == dasd_3990_erp_action_1B_32) {2692 2693 erp = dasd_3990_update_1B(erp, sense);2694 2695 } else if (sense && erp->function == dasd_3990_erp_int_req) {2696 2697 erp = dasd_3990_erp_int_req(erp);2698 2699 } else {2700 /* simple retry */2701 DBF_DEV_EVENT(DBF_DEBUG, device,2702 "%i retries left for erp %p",2703 erp->retries, erp);2704 2705 /* handle the request again... */2706 erp->status = DASD_CQR_FILLED;2707 }2708 2709 } else {2710 /* no retry left - check for further necessary action */2711 /* if no further actions, handle rest as permanent error */2712 erp = dasd_3990_erp_further_erp(erp);2713 }2714 2715 return erp;2716 2717} /* end dasd_3990_erp_handle_match_erp */2718 2719/*2720 * DASD_3990_ERP_ACTION2721 *2722 * DESCRIPTION2723 * control routine for 3990 erp actions.2724 * Has to be called with the queue lock (namely the s390_irq_lock) acquired.2725 *2726 * PARAMETER2727 * cqr failed cqr (either original cqr or already an erp)2728 *2729 * RETURN VALUES2730 * erp erp-pointer to the head of the ERP action chain.2731 * This means:2732 * - either a ptr to an additional ERP cqr or2733 * - the original given cqr (which's status might2734 * be modified)2735 */2736struct dasd_ccw_req *2737dasd_3990_erp_action(struct dasd_ccw_req * cqr)2738{2739 struct dasd_ccw_req *erp = NULL;2740 struct dasd_device *device = cqr->startdev;2741 struct dasd_ccw_req *temp_erp = NULL;2742 2743 if (device->features & DASD_FEATURE_ERPLOG) {2744 /* print current erp_chain */2745 dev_err(&device->cdev->dev,2746 "ERP chain at BEGINNING of ERP-ACTION\n");2747 for (temp_erp = cqr;2748 temp_erp != NULL; temp_erp = temp_erp->refers) {2749 dev_err(&device->cdev->dev,2750 "ERP %px (%02x) refers to %px\n",2751 temp_erp, temp_erp->status, temp_erp->refers);2752 }2753 }2754 2755 /* double-check if current erp/cqr was successful */2756 if ((scsw_cstat(&cqr->irb.scsw) == 0x00) &&2757 (scsw_dstat(&cqr->irb.scsw) ==2758 (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) {2759 2760 DBF_DEV_EVENT(DBF_DEBUG, device,2761 "ERP called for successful request %p"2762 " - NO ERP necessary", cqr);2763 2764 cqr->status = DASD_CQR_DONE;2765 2766 return cqr;2767 }2768 2769 /* check if error happened before */2770 erp = dasd_3990_erp_in_erp(cqr);2771 2772 if (erp == NULL) {2773 /* no matching erp found - set up erp */2774 erp = dasd_3990_erp_additional_erp(cqr);2775 if (IS_ERR(erp))2776 return erp;2777 } else {2778 /* matching erp found - set all leading erp's to DONE */2779 erp = dasd_3990_erp_handle_match_erp(cqr, erp);2780 }2781 2782 2783 /*2784 * For path verification work we need to stick with the path that was2785 * originally chosen so that the per path configuration data is2786 * assigned correctly.2787 */2788 if (test_bit(DASD_CQR_VERIFY_PATH, &erp->flags) && cqr->lpm) {2789 erp->lpm = cqr->lpm;2790 }2791 2792 if (device->features & DASD_FEATURE_ERPLOG) {2793 /* print current erp_chain */2794 dev_err(&device->cdev->dev,2795 "ERP chain at END of ERP-ACTION\n");2796 for (temp_erp = erp;2797 temp_erp != NULL; temp_erp = temp_erp->refers) {2798 dev_err(&device->cdev->dev,2799 "ERP %px (%02x) refers to %px\n",2800 temp_erp, temp_erp->status, temp_erp->refers);2801 }2802 }2803 2804 /* enqueue ERP request if it's a new one */2805 if (list_empty(&erp->blocklist)) {2806 cqr->status = DASD_CQR_IN_ERP;2807 /* add erp request before the cqr */2808 list_add_tail(&erp->blocklist, &cqr->blocklist);2809 }2810 2811 2812 2813 return erp;2814 2815} /* end dasd_3990_erp_action */2816