18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Author(s)......: Horst Hummel <Horst.Hummel@de.ibm.com> 48c2ecf20Sopenharmony_ci * Holger Smolinski <Holger.Smolinski@de.ibm.com> 58c2ecf20Sopenharmony_ci * Bugreports.to..: <Linux390@de.ibm.com> 68c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2000, 2001 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#define KMSG_COMPONENT "dasd-eckd" 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/timer.h> 138c2ecf20Sopenharmony_ci#include <asm/idals.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define PRINTK_HEADER "dasd_erp(3990): " 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "dasd_int.h" 188c2ecf20Sopenharmony_ci#include "dasd_eckd.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistruct DCTL_data { 228c2ecf20Sopenharmony_ci unsigned char subcommand; /* e.g Inhibit Write, Enable Write,... */ 238c2ecf20Sopenharmony_ci unsigned char modifier; /* Subcommand modifier */ 248c2ecf20Sopenharmony_ci unsigned short res; /* reserved */ 258c2ecf20Sopenharmony_ci} __attribute__ ((packed)); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* 288c2ecf20Sopenharmony_ci ***************************************************************************** 298c2ecf20Sopenharmony_ci * SECTION ERP HANDLING 308c2ecf20Sopenharmony_ci ***************************************************************************** 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci/* 338c2ecf20Sopenharmony_ci ***************************************************************************** 348c2ecf20Sopenharmony_ci * 24 and 32 byte sense ERP functions 358c2ecf20Sopenharmony_ci ***************************************************************************** 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* 398c2ecf20Sopenharmony_ci * DASD_3990_ERP_CLEANUP 408c2ecf20Sopenharmony_ci * 418c2ecf20Sopenharmony_ci * DESCRIPTION 428c2ecf20Sopenharmony_ci * Removes the already build but not necessary ERP request and sets 438c2ecf20Sopenharmony_ci * the status of the original cqr / erp to the given (final) status 448c2ecf20Sopenharmony_ci * 458c2ecf20Sopenharmony_ci * PARAMETER 468c2ecf20Sopenharmony_ci * erp request to be blocked 478c2ecf20Sopenharmony_ci * final_status either DASD_CQR_DONE or DASD_CQR_FAILED 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci * RETURN VALUES 508c2ecf20Sopenharmony_ci * cqr original cqr 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 538c2ecf20Sopenharmony_cidasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci struct dasd_ccw_req *cqr = erp->refers; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci dasd_free_erp_request(erp, erp->memdev); 588c2ecf20Sopenharmony_ci cqr->status = final_status; 598c2ecf20Sopenharmony_ci return cqr; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_cleanup */ 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* 648c2ecf20Sopenharmony_ci * DASD_3990_ERP_BLOCK_QUEUE 658c2ecf20Sopenharmony_ci * 668c2ecf20Sopenharmony_ci * DESCRIPTION 678c2ecf20Sopenharmony_ci * Block the given device request queue to prevent from further 688c2ecf20Sopenharmony_ci * processing until the started timer has expired or an related 698c2ecf20Sopenharmony_ci * interrupt was received. 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_cistatic void dasd_3990_erp_block_queue(struct dasd_ccw_req *erp, int expires) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 758c2ecf20Sopenharmony_ci unsigned long flags; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_INFO, device, 788c2ecf20Sopenharmony_ci "blocking request queue for %is", expires/HZ); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); 818c2ecf20Sopenharmony_ci dasd_device_set_stop_bits(device, DASD_STOPPED_PENDING); 828c2ecf20Sopenharmony_ci spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); 838c2ecf20Sopenharmony_ci erp->status = DASD_CQR_FILLED; 848c2ecf20Sopenharmony_ci if (erp->block) 858c2ecf20Sopenharmony_ci dasd_block_set_timer(erp->block, expires); 868c2ecf20Sopenharmony_ci else 878c2ecf20Sopenharmony_ci dasd_device_set_timer(device, expires); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/* 918c2ecf20Sopenharmony_ci * DASD_3990_ERP_INT_REQ 928c2ecf20Sopenharmony_ci * 938c2ecf20Sopenharmony_ci * DESCRIPTION 948c2ecf20Sopenharmony_ci * Handles 'Intervention Required' error. 958c2ecf20Sopenharmony_ci * This means either device offline or not installed. 968c2ecf20Sopenharmony_ci * 978c2ecf20Sopenharmony_ci * PARAMETER 988c2ecf20Sopenharmony_ci * erp current erp 998c2ecf20Sopenharmony_ci * RETURN VALUES 1008c2ecf20Sopenharmony_ci * erp modified erp 1018c2ecf20Sopenharmony_ci */ 1028c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 1038c2ecf20Sopenharmony_cidasd_3990_erp_int_req(struct dasd_ccw_req * erp) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* first time set initial retry counter and erp_function */ 1098c2ecf20Sopenharmony_ci /* and retry once without blocking queue */ 1108c2ecf20Sopenharmony_ci /* (this enables easier enqueing of the cqr) */ 1118c2ecf20Sopenharmony_ci if (erp->function != dasd_3990_erp_int_req) { 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci erp->retries = 256; 1148c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_int_req; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci } else { 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* issue a message and wait for 'device ready' interrupt */ 1198c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 1208c2ecf20Sopenharmony_ci "is offline or not installed - " 1218c2ecf20Sopenharmony_ci "INTERVENTION REQUIRED!!\n"); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci dasd_3990_erp_block_queue(erp, 60*HZ); 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci return erp; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_int_req */ 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* 1318c2ecf20Sopenharmony_ci * DASD_3990_ERP_ALTERNATE_PATH 1328c2ecf20Sopenharmony_ci * 1338c2ecf20Sopenharmony_ci * DESCRIPTION 1348c2ecf20Sopenharmony_ci * Repeat the operation on a different channel path. 1358c2ecf20Sopenharmony_ci * If all alternate paths have been tried, the request is posted with a 1368c2ecf20Sopenharmony_ci * permanent error. 1378c2ecf20Sopenharmony_ci * 1388c2ecf20Sopenharmony_ci * PARAMETER 1398c2ecf20Sopenharmony_ci * erp pointer to the current ERP 1408c2ecf20Sopenharmony_ci * 1418c2ecf20Sopenharmony_ci * RETURN VALUES 1428c2ecf20Sopenharmony_ci * erp modified pointer to the ERP 1438c2ecf20Sopenharmony_ci */ 1448c2ecf20Sopenharmony_cistatic void 1458c2ecf20Sopenharmony_cidasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 1488c2ecf20Sopenharmony_ci __u8 opm; 1498c2ecf20Sopenharmony_ci unsigned long flags; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci /* try alternate valid path */ 1528c2ecf20Sopenharmony_ci spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); 1538c2ecf20Sopenharmony_ci opm = ccw_device_get_path_mask(device->cdev); 1548c2ecf20Sopenharmony_ci spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); 1558c2ecf20Sopenharmony_ci if (erp->lpm == 0) 1568c2ecf20Sopenharmony_ci erp->lpm = dasd_path_get_opm(device) & 1578c2ecf20Sopenharmony_ci ~(erp->irb.esw.esw0.sublog.lpum); 1588c2ecf20Sopenharmony_ci else 1598c2ecf20Sopenharmony_ci erp->lpm &= ~(erp->irb.esw.esw0.sublog.lpum); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci if ((erp->lpm & opm) != 0x00) { 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, 1648c2ecf20Sopenharmony_ci "try alternate lpm=%x (lpum=%x / opm=%x)", 1658c2ecf20Sopenharmony_ci erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci /* reset status to submit the request again... */ 1688c2ecf20Sopenharmony_ci erp->status = DASD_CQR_FILLED; 1698c2ecf20Sopenharmony_ci erp->retries = 10; 1708c2ecf20Sopenharmony_ci } else { 1718c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 1728c2ecf20Sopenharmony_ci "The DASD cannot be reached on any path (lpum=%x" 1738c2ecf20Sopenharmony_ci "/opm=%x)\n", erp->irb.esw.esw0.sublog.lpum, opm); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* post request with permanent error */ 1768c2ecf20Sopenharmony_ci erp->status = DASD_CQR_FAILED; 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_alternate_path */ 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci/* 1818c2ecf20Sopenharmony_ci * DASD_3990_ERP_DCTL 1828c2ecf20Sopenharmony_ci * 1838c2ecf20Sopenharmony_ci * DESCRIPTION 1848c2ecf20Sopenharmony_ci * Setup cqr to do the Diagnostic Control (DCTL) command with an 1858c2ecf20Sopenharmony_ci * Inhibit Write subcommand (0x20) and the given modifier. 1868c2ecf20Sopenharmony_ci * 1878c2ecf20Sopenharmony_ci * PARAMETER 1888c2ecf20Sopenharmony_ci * erp pointer to the current (failed) ERP 1898c2ecf20Sopenharmony_ci * modifier subcommand modifier 1908c2ecf20Sopenharmony_ci * 1918c2ecf20Sopenharmony_ci * RETURN VALUES 1928c2ecf20Sopenharmony_ci * dctl_cqr pointer to NEW dctl_cqr 1938c2ecf20Sopenharmony_ci * 1948c2ecf20Sopenharmony_ci */ 1958c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 1968c2ecf20Sopenharmony_cidasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 2008c2ecf20Sopenharmony_ci struct DCTL_data *DCTL_data; 2018c2ecf20Sopenharmony_ci struct ccw1 *ccw; 2028c2ecf20Sopenharmony_ci struct dasd_ccw_req *dctl_cqr; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci dctl_cqr = dasd_alloc_erp_request((char *) &erp->magic, 1, 2058c2ecf20Sopenharmony_ci sizeof(struct DCTL_data), 2068c2ecf20Sopenharmony_ci device); 2078c2ecf20Sopenharmony_ci if (IS_ERR(dctl_cqr)) { 2088c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 2098c2ecf20Sopenharmony_ci "Unable to allocate DCTL-CQR\n"); 2108c2ecf20Sopenharmony_ci erp->status = DASD_CQR_FAILED; 2118c2ecf20Sopenharmony_ci return erp; 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci DCTL_data = dctl_cqr->data; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci DCTL_data->subcommand = 0x02; /* Inhibit Write */ 2178c2ecf20Sopenharmony_ci DCTL_data->modifier = modifier; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci ccw = dctl_cqr->cpaddr; 2208c2ecf20Sopenharmony_ci memset(ccw, 0, sizeof(struct ccw1)); 2218c2ecf20Sopenharmony_ci ccw->cmd_code = CCW_CMD_DCTL; 2228c2ecf20Sopenharmony_ci ccw->count = 4; 2238c2ecf20Sopenharmony_ci ccw->cda = (__u32)(addr_t) DCTL_data; 2248c2ecf20Sopenharmony_ci dctl_cqr->flags = erp->flags; 2258c2ecf20Sopenharmony_ci dctl_cqr->function = dasd_3990_erp_DCTL; 2268c2ecf20Sopenharmony_ci dctl_cqr->refers = erp; 2278c2ecf20Sopenharmony_ci dctl_cqr->startdev = device; 2288c2ecf20Sopenharmony_ci dctl_cqr->memdev = device; 2298c2ecf20Sopenharmony_ci dctl_cqr->magic = erp->magic; 2308c2ecf20Sopenharmony_ci dctl_cqr->expires = 5 * 60 * HZ; 2318c2ecf20Sopenharmony_ci dctl_cqr->retries = 2; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci dctl_cqr->buildclk = get_tod_clock(); 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci dctl_cqr->status = DASD_CQR_FILLED; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci return dctl_cqr; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_DCTL */ 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci/* 2428c2ecf20Sopenharmony_ci * DASD_3990_ERP_ACTION_1 2438c2ecf20Sopenharmony_ci * 2448c2ecf20Sopenharmony_ci * DESCRIPTION 2458c2ecf20Sopenharmony_ci * Setup ERP to do the ERP action 1 (see Reference manual). 2468c2ecf20Sopenharmony_ci * Repeat the operation on a different channel path. 2478c2ecf20Sopenharmony_ci * As deviation from the recommended recovery action, we reset the path mask 2488c2ecf20Sopenharmony_ci * after we have tried each path and go through all paths a second time. 2498c2ecf20Sopenharmony_ci * This will cover situations where only one path at a time is actually down, 2508c2ecf20Sopenharmony_ci * but all paths fail and recover just with the same sequence and timing as 2518c2ecf20Sopenharmony_ci * we try to use them (flapping links). 2528c2ecf20Sopenharmony_ci * If all alternate paths have been tried twice, the request is posted with 2538c2ecf20Sopenharmony_ci * a permanent error. 2548c2ecf20Sopenharmony_ci * 2558c2ecf20Sopenharmony_ci * PARAMETER 2568c2ecf20Sopenharmony_ci * erp pointer to the current ERP 2578c2ecf20Sopenharmony_ci * 2588c2ecf20Sopenharmony_ci * RETURN VALUES 2598c2ecf20Sopenharmony_ci * erp pointer to the ERP 2608c2ecf20Sopenharmony_ci * 2618c2ecf20Sopenharmony_ci */ 2628c2ecf20Sopenharmony_cistatic struct dasd_ccw_req *dasd_3990_erp_action_1_sec(struct dasd_ccw_req *erp) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_action_1_sec; 2658c2ecf20Sopenharmony_ci dasd_3990_erp_alternate_path(erp); 2668c2ecf20Sopenharmony_ci return erp; 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_cistatic struct dasd_ccw_req *dasd_3990_erp_action_1(struct dasd_ccw_req *erp) 2708c2ecf20Sopenharmony_ci{ 2718c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_action_1; 2728c2ecf20Sopenharmony_ci dasd_3990_erp_alternate_path(erp); 2738c2ecf20Sopenharmony_ci if (erp->status == DASD_CQR_FAILED && 2748c2ecf20Sopenharmony_ci !test_bit(DASD_CQR_VERIFY_PATH, &erp->flags)) { 2758c2ecf20Sopenharmony_ci erp->status = DASD_CQR_FILLED; 2768c2ecf20Sopenharmony_ci erp->retries = 10; 2778c2ecf20Sopenharmony_ci erp->lpm = dasd_path_get_opm(erp->startdev); 2788c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_action_1_sec; 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci return erp; 2818c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_action_1(b) */ 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci/* 2848c2ecf20Sopenharmony_ci * DASD_3990_ERP_ACTION_4 2858c2ecf20Sopenharmony_ci * 2868c2ecf20Sopenharmony_ci * DESCRIPTION 2878c2ecf20Sopenharmony_ci * Setup ERP to do the ERP action 4 (see Reference manual). 2888c2ecf20Sopenharmony_ci * Set the current request to PENDING to block the CQR queue for that device 2898c2ecf20Sopenharmony_ci * until the state change interrupt appears. 2908c2ecf20Sopenharmony_ci * Use a timer (20 seconds) to retry the cqr if the interrupt is still 2918c2ecf20Sopenharmony_ci * missing. 2928c2ecf20Sopenharmony_ci * 2938c2ecf20Sopenharmony_ci * PARAMETER 2948c2ecf20Sopenharmony_ci * sense sense data of the actual error 2958c2ecf20Sopenharmony_ci * erp pointer to the current ERP 2968c2ecf20Sopenharmony_ci * 2978c2ecf20Sopenharmony_ci * RETURN VALUES 2988c2ecf20Sopenharmony_ci * erp pointer to the ERP 2998c2ecf20Sopenharmony_ci * 3008c2ecf20Sopenharmony_ci */ 3018c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 3028c2ecf20Sopenharmony_cidasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) 3038c2ecf20Sopenharmony_ci{ 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci /* first time set initial retry counter and erp_function */ 3088c2ecf20Sopenharmony_ci /* and retry once without waiting for state change pending */ 3098c2ecf20Sopenharmony_ci /* interrupt (this enables easier enqueing of the cqr) */ 3108c2ecf20Sopenharmony_ci if (erp->function != dasd_3990_erp_action_4) { 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_INFO, device, "%s", 3138c2ecf20Sopenharmony_ci "dasd_3990_erp_action_4: first time retry"); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci erp->retries = 256; 3168c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_action_4; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci } else { 3198c2ecf20Sopenharmony_ci if (sense && (sense[25] == 0x1D)) { /* state change pending */ 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_INFO, device, 3228c2ecf20Sopenharmony_ci "waiting for state change pending " 3238c2ecf20Sopenharmony_ci "interrupt, %d retries left", 3248c2ecf20Sopenharmony_ci erp->retries); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci dasd_3990_erp_block_queue(erp, 30*HZ); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci } else if (sense && (sense[25] == 0x1E)) { /* busy */ 3298c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_INFO, device, 3308c2ecf20Sopenharmony_ci "busy - redriving request later, " 3318c2ecf20Sopenharmony_ci "%d retries left", 3328c2ecf20Sopenharmony_ci erp->retries); 3338c2ecf20Sopenharmony_ci dasd_3990_erp_block_queue(erp, HZ); 3348c2ecf20Sopenharmony_ci } else { 3358c2ecf20Sopenharmony_ci /* no state change pending - retry */ 3368c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_INFO, device, 3378c2ecf20Sopenharmony_ci "redriving request immediately, " 3388c2ecf20Sopenharmony_ci "%d retries left", 3398c2ecf20Sopenharmony_ci erp->retries); 3408c2ecf20Sopenharmony_ci erp->status = DASD_CQR_FILLED; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci return erp; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_action_4 */ 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci/* 3498c2ecf20Sopenharmony_ci ***************************************************************************** 3508c2ecf20Sopenharmony_ci * 24 byte sense ERP functions (only) 3518c2ecf20Sopenharmony_ci ***************************************************************************** 3528c2ecf20Sopenharmony_ci */ 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci/* 3558c2ecf20Sopenharmony_ci * DASD_3990_ERP_ACTION_5 3568c2ecf20Sopenharmony_ci * 3578c2ecf20Sopenharmony_ci * DESCRIPTION 3588c2ecf20Sopenharmony_ci * Setup ERP to do the ERP action 5 (see Reference manual). 3598c2ecf20Sopenharmony_ci * NOTE: Further handling is done in xxx_further_erp after the retries. 3608c2ecf20Sopenharmony_ci * 3618c2ecf20Sopenharmony_ci * PARAMETER 3628c2ecf20Sopenharmony_ci * erp pointer to the current ERP 3638c2ecf20Sopenharmony_ci * 3648c2ecf20Sopenharmony_ci * RETURN VALUES 3658c2ecf20Sopenharmony_ci * erp pointer to the ERP 3668c2ecf20Sopenharmony_ci * 3678c2ecf20Sopenharmony_ci */ 3688c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 3698c2ecf20Sopenharmony_cidasd_3990_erp_action_5(struct dasd_ccw_req * erp) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci /* first of all retry */ 3738c2ecf20Sopenharmony_ci erp->retries = 10; 3748c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_action_5; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci return erp; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_action_5 */ 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci/* 3818c2ecf20Sopenharmony_ci * DASD_3990_HANDLE_ENV_DATA 3828c2ecf20Sopenharmony_ci * 3838c2ecf20Sopenharmony_ci * DESCRIPTION 3848c2ecf20Sopenharmony_ci * Handles 24 byte 'Environmental data present'. 3858c2ecf20Sopenharmony_ci * Does a analysis of the sense data (message Format) 3868c2ecf20Sopenharmony_ci * and prints the error messages. 3878c2ecf20Sopenharmony_ci * 3888c2ecf20Sopenharmony_ci * PARAMETER 3898c2ecf20Sopenharmony_ci * sense current sense data 3908c2ecf20Sopenharmony_ci * 3918c2ecf20Sopenharmony_ci * RETURN VALUES 3928c2ecf20Sopenharmony_ci * void 3938c2ecf20Sopenharmony_ci */ 3948c2ecf20Sopenharmony_cistatic void 3958c2ecf20Sopenharmony_cidasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) 3968c2ecf20Sopenharmony_ci{ 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 3998c2ecf20Sopenharmony_ci char msg_format = (sense[7] & 0xF0); 4008c2ecf20Sopenharmony_ci char msg_no = (sense[7] & 0x0F); 4018c2ecf20Sopenharmony_ci char errorstring[ERRORLENGTH]; 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci switch (msg_format) { 4048c2ecf20Sopenharmony_ci case 0x00: /* Format 0 - Program or System Checks */ 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci if (sense[1] & 0x10) { /* check message to operator bit */ 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci switch (msg_no) { 4098c2ecf20Sopenharmony_ci case 0x00: /* No Message */ 4108c2ecf20Sopenharmony_ci break; 4118c2ecf20Sopenharmony_ci case 0x01: 4128c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4138c2ecf20Sopenharmony_ci "FORMAT 0 - Invalid Command\n"); 4148c2ecf20Sopenharmony_ci break; 4158c2ecf20Sopenharmony_ci case 0x02: 4168c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4178c2ecf20Sopenharmony_ci "FORMAT 0 - Invalid Command " 4188c2ecf20Sopenharmony_ci "Sequence\n"); 4198c2ecf20Sopenharmony_ci break; 4208c2ecf20Sopenharmony_ci case 0x03: 4218c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4228c2ecf20Sopenharmony_ci "FORMAT 0 - CCW Count less than " 4238c2ecf20Sopenharmony_ci "required\n"); 4248c2ecf20Sopenharmony_ci break; 4258c2ecf20Sopenharmony_ci case 0x04: 4268c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4278c2ecf20Sopenharmony_ci "FORMAT 0 - Invalid Parameter\n"); 4288c2ecf20Sopenharmony_ci break; 4298c2ecf20Sopenharmony_ci case 0x05: 4308c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4318c2ecf20Sopenharmony_ci "FORMAT 0 - Diagnostic of Special" 4328c2ecf20Sopenharmony_ci " Command Violates File Mask\n"); 4338c2ecf20Sopenharmony_ci break; 4348c2ecf20Sopenharmony_ci case 0x07: 4358c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4368c2ecf20Sopenharmony_ci "FORMAT 0 - Channel Returned with " 4378c2ecf20Sopenharmony_ci "Incorrect retry CCW\n"); 4388c2ecf20Sopenharmony_ci break; 4398c2ecf20Sopenharmony_ci case 0x08: 4408c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4418c2ecf20Sopenharmony_ci "FORMAT 0 - Reset Notification\n"); 4428c2ecf20Sopenharmony_ci break; 4438c2ecf20Sopenharmony_ci case 0x09: 4448c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4458c2ecf20Sopenharmony_ci "FORMAT 0 - Storage Path Restart\n"); 4468c2ecf20Sopenharmony_ci break; 4478c2ecf20Sopenharmony_ci case 0x0A: 4488c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4498c2ecf20Sopenharmony_ci "FORMAT 0 - Channel requested " 4508c2ecf20Sopenharmony_ci "... %02x\n", sense[8]); 4518c2ecf20Sopenharmony_ci break; 4528c2ecf20Sopenharmony_ci case 0x0B: 4538c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4548c2ecf20Sopenharmony_ci "FORMAT 0 - Invalid Defective/" 4558c2ecf20Sopenharmony_ci "Alternate Track Pointer\n"); 4568c2ecf20Sopenharmony_ci break; 4578c2ecf20Sopenharmony_ci case 0x0C: 4588c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4598c2ecf20Sopenharmony_ci "FORMAT 0 - DPS Installation " 4608c2ecf20Sopenharmony_ci "Check\n"); 4618c2ecf20Sopenharmony_ci break; 4628c2ecf20Sopenharmony_ci case 0x0E: 4638c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4648c2ecf20Sopenharmony_ci "FORMAT 0 - Command Invalid on " 4658c2ecf20Sopenharmony_ci "Secondary Address\n"); 4668c2ecf20Sopenharmony_ci break; 4678c2ecf20Sopenharmony_ci case 0x0F: 4688c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4698c2ecf20Sopenharmony_ci "FORMAT 0 - Status Not As " 4708c2ecf20Sopenharmony_ci "Required: reason %02x\n", 4718c2ecf20Sopenharmony_ci sense[8]); 4728c2ecf20Sopenharmony_ci break; 4738c2ecf20Sopenharmony_ci default: 4748c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4758c2ecf20Sopenharmony_ci "FORMAT 0 - Reserved\n"); 4768c2ecf20Sopenharmony_ci } 4778c2ecf20Sopenharmony_ci } else { 4788c2ecf20Sopenharmony_ci switch (msg_no) { 4798c2ecf20Sopenharmony_ci case 0x00: /* No Message */ 4808c2ecf20Sopenharmony_ci break; 4818c2ecf20Sopenharmony_ci case 0x01: 4828c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4838c2ecf20Sopenharmony_ci "FORMAT 0 - Device Error " 4848c2ecf20Sopenharmony_ci "Source\n"); 4858c2ecf20Sopenharmony_ci break; 4868c2ecf20Sopenharmony_ci case 0x02: 4878c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4888c2ecf20Sopenharmony_ci "FORMAT 0 - Reserved\n"); 4898c2ecf20Sopenharmony_ci break; 4908c2ecf20Sopenharmony_ci case 0x03: 4918c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4928c2ecf20Sopenharmony_ci "FORMAT 0 - Device Fenced - " 4938c2ecf20Sopenharmony_ci "device = %02x\n", sense[4]); 4948c2ecf20Sopenharmony_ci break; 4958c2ecf20Sopenharmony_ci case 0x04: 4968c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 4978c2ecf20Sopenharmony_ci "FORMAT 0 - Data Pinned for " 4988c2ecf20Sopenharmony_ci "Device\n"); 4998c2ecf20Sopenharmony_ci break; 5008c2ecf20Sopenharmony_ci default: 5018c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5028c2ecf20Sopenharmony_ci "FORMAT 0 - Reserved\n"); 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci break; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci case 0x10: /* Format 1 - Device Equipment Checks */ 5088c2ecf20Sopenharmony_ci switch (msg_no) { 5098c2ecf20Sopenharmony_ci case 0x00: /* No Message */ 5108c2ecf20Sopenharmony_ci break; 5118c2ecf20Sopenharmony_ci case 0x01: 5128c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5138c2ecf20Sopenharmony_ci "FORMAT 1 - Device Status 1 not as " 5148c2ecf20Sopenharmony_ci "expected\n"); 5158c2ecf20Sopenharmony_ci break; 5168c2ecf20Sopenharmony_ci case 0x03: 5178c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5188c2ecf20Sopenharmony_ci "FORMAT 1 - Index missing\n"); 5198c2ecf20Sopenharmony_ci break; 5208c2ecf20Sopenharmony_ci case 0x04: 5218c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5228c2ecf20Sopenharmony_ci "FORMAT 1 - Interruption cannot be " 5238c2ecf20Sopenharmony_ci "reset\n"); 5248c2ecf20Sopenharmony_ci break; 5258c2ecf20Sopenharmony_ci case 0x05: 5268c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5278c2ecf20Sopenharmony_ci "FORMAT 1 - Device did not respond to " 5288c2ecf20Sopenharmony_ci "selection\n"); 5298c2ecf20Sopenharmony_ci break; 5308c2ecf20Sopenharmony_ci case 0x06: 5318c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5328c2ecf20Sopenharmony_ci "FORMAT 1 - Device check-2 error or Set " 5338c2ecf20Sopenharmony_ci "Sector is not complete\n"); 5348c2ecf20Sopenharmony_ci break; 5358c2ecf20Sopenharmony_ci case 0x07: 5368c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5378c2ecf20Sopenharmony_ci "FORMAT 1 - Head address does not " 5388c2ecf20Sopenharmony_ci "compare\n"); 5398c2ecf20Sopenharmony_ci break; 5408c2ecf20Sopenharmony_ci case 0x08: 5418c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5428c2ecf20Sopenharmony_ci "FORMAT 1 - Device status 1 not valid\n"); 5438c2ecf20Sopenharmony_ci break; 5448c2ecf20Sopenharmony_ci case 0x09: 5458c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5468c2ecf20Sopenharmony_ci "FORMAT 1 - Device not ready\n"); 5478c2ecf20Sopenharmony_ci break; 5488c2ecf20Sopenharmony_ci case 0x0A: 5498c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5508c2ecf20Sopenharmony_ci "FORMAT 1 - Track physical address did " 5518c2ecf20Sopenharmony_ci "not compare\n"); 5528c2ecf20Sopenharmony_ci break; 5538c2ecf20Sopenharmony_ci case 0x0B: 5548c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5558c2ecf20Sopenharmony_ci "FORMAT 1 - Missing device address bit\n"); 5568c2ecf20Sopenharmony_ci break; 5578c2ecf20Sopenharmony_ci case 0x0C: 5588c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5598c2ecf20Sopenharmony_ci "FORMAT 1 - Drive motor switch is off\n"); 5608c2ecf20Sopenharmony_ci break; 5618c2ecf20Sopenharmony_ci case 0x0D: 5628c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5638c2ecf20Sopenharmony_ci "FORMAT 1 - Seek incomplete\n"); 5648c2ecf20Sopenharmony_ci break; 5658c2ecf20Sopenharmony_ci case 0x0E: 5668c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5678c2ecf20Sopenharmony_ci "FORMAT 1 - Cylinder address did not " 5688c2ecf20Sopenharmony_ci "compare\n"); 5698c2ecf20Sopenharmony_ci break; 5708c2ecf20Sopenharmony_ci case 0x0F: 5718c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5728c2ecf20Sopenharmony_ci "FORMAT 1 - Offset active cannot be " 5738c2ecf20Sopenharmony_ci "reset\n"); 5748c2ecf20Sopenharmony_ci break; 5758c2ecf20Sopenharmony_ci default: 5768c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5778c2ecf20Sopenharmony_ci "FORMAT 1 - Reserved\n"); 5788c2ecf20Sopenharmony_ci } 5798c2ecf20Sopenharmony_ci break; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci case 0x20: /* Format 2 - 3990 Equipment Checks */ 5828c2ecf20Sopenharmony_ci switch (msg_no) { 5838c2ecf20Sopenharmony_ci case 0x08: 5848c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5858c2ecf20Sopenharmony_ci "FORMAT 2 - 3990 check-2 error\n"); 5868c2ecf20Sopenharmony_ci break; 5878c2ecf20Sopenharmony_ci case 0x0E: 5888c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5898c2ecf20Sopenharmony_ci "FORMAT 2 - Support facility errors\n"); 5908c2ecf20Sopenharmony_ci break; 5918c2ecf20Sopenharmony_ci case 0x0F: 5928c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5938c2ecf20Sopenharmony_ci "FORMAT 2 - Microcode detected error " 5948c2ecf20Sopenharmony_ci "%02x\n", 5958c2ecf20Sopenharmony_ci sense[8]); 5968c2ecf20Sopenharmony_ci break; 5978c2ecf20Sopenharmony_ci default: 5988c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 5998c2ecf20Sopenharmony_ci "FORMAT 2 - Reserved\n"); 6008c2ecf20Sopenharmony_ci } 6018c2ecf20Sopenharmony_ci break; 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci case 0x30: /* Format 3 - 3990 Control Checks */ 6048c2ecf20Sopenharmony_ci switch (msg_no) { 6058c2ecf20Sopenharmony_ci case 0x0F: 6068c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6078c2ecf20Sopenharmony_ci "FORMAT 3 - Allegiance terminated\n"); 6088c2ecf20Sopenharmony_ci break; 6098c2ecf20Sopenharmony_ci default: 6108c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6118c2ecf20Sopenharmony_ci "FORMAT 3 - Reserved\n"); 6128c2ecf20Sopenharmony_ci } 6138c2ecf20Sopenharmony_ci break; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci case 0x40: /* Format 4 - Data Checks */ 6168c2ecf20Sopenharmony_ci switch (msg_no) { 6178c2ecf20Sopenharmony_ci case 0x00: 6188c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6198c2ecf20Sopenharmony_ci "FORMAT 4 - Home address area error\n"); 6208c2ecf20Sopenharmony_ci break; 6218c2ecf20Sopenharmony_ci case 0x01: 6228c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6238c2ecf20Sopenharmony_ci "FORMAT 4 - Count area error\n"); 6248c2ecf20Sopenharmony_ci break; 6258c2ecf20Sopenharmony_ci case 0x02: 6268c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6278c2ecf20Sopenharmony_ci "FORMAT 4 - Key area error\n"); 6288c2ecf20Sopenharmony_ci break; 6298c2ecf20Sopenharmony_ci case 0x03: 6308c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6318c2ecf20Sopenharmony_ci "FORMAT 4 - Data area error\n"); 6328c2ecf20Sopenharmony_ci break; 6338c2ecf20Sopenharmony_ci case 0x04: 6348c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6358c2ecf20Sopenharmony_ci "FORMAT 4 - No sync byte in home address " 6368c2ecf20Sopenharmony_ci "area\n"); 6378c2ecf20Sopenharmony_ci break; 6388c2ecf20Sopenharmony_ci case 0x05: 6398c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6408c2ecf20Sopenharmony_ci "FORMAT 4 - No sync byte in count address " 6418c2ecf20Sopenharmony_ci "area\n"); 6428c2ecf20Sopenharmony_ci break; 6438c2ecf20Sopenharmony_ci case 0x06: 6448c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6458c2ecf20Sopenharmony_ci "FORMAT 4 - No sync byte in key area\n"); 6468c2ecf20Sopenharmony_ci break; 6478c2ecf20Sopenharmony_ci case 0x07: 6488c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6498c2ecf20Sopenharmony_ci "FORMAT 4 - No sync byte in data area\n"); 6508c2ecf20Sopenharmony_ci break; 6518c2ecf20Sopenharmony_ci case 0x08: 6528c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6538c2ecf20Sopenharmony_ci "FORMAT 4 - Home address area error; " 6548c2ecf20Sopenharmony_ci "offset active\n"); 6558c2ecf20Sopenharmony_ci break; 6568c2ecf20Sopenharmony_ci case 0x09: 6578c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6588c2ecf20Sopenharmony_ci "FORMAT 4 - Count area error; offset " 6598c2ecf20Sopenharmony_ci "active\n"); 6608c2ecf20Sopenharmony_ci break; 6618c2ecf20Sopenharmony_ci case 0x0A: 6628c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6638c2ecf20Sopenharmony_ci "FORMAT 4 - Key area error; offset " 6648c2ecf20Sopenharmony_ci "active\n"); 6658c2ecf20Sopenharmony_ci break; 6668c2ecf20Sopenharmony_ci case 0x0B: 6678c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6688c2ecf20Sopenharmony_ci "FORMAT 4 - Data area error; " 6698c2ecf20Sopenharmony_ci "offset active\n"); 6708c2ecf20Sopenharmony_ci break; 6718c2ecf20Sopenharmony_ci case 0x0C: 6728c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6738c2ecf20Sopenharmony_ci "FORMAT 4 - No sync byte in home " 6748c2ecf20Sopenharmony_ci "address area; offset active\n"); 6758c2ecf20Sopenharmony_ci break; 6768c2ecf20Sopenharmony_ci case 0x0D: 6778c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6788c2ecf20Sopenharmony_ci "FORMAT 4 - No sync byte in count " 6798c2ecf20Sopenharmony_ci "address area; offset active\n"); 6808c2ecf20Sopenharmony_ci break; 6818c2ecf20Sopenharmony_ci case 0x0E: 6828c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6838c2ecf20Sopenharmony_ci "FORMAT 4 - No sync byte in key area; " 6848c2ecf20Sopenharmony_ci "offset active\n"); 6858c2ecf20Sopenharmony_ci break; 6868c2ecf20Sopenharmony_ci case 0x0F: 6878c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6888c2ecf20Sopenharmony_ci "FORMAT 4 - No sync byte in data area; " 6898c2ecf20Sopenharmony_ci "offset active\n"); 6908c2ecf20Sopenharmony_ci break; 6918c2ecf20Sopenharmony_ci default: 6928c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 6938c2ecf20Sopenharmony_ci "FORMAT 4 - Reserved\n"); 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci break; 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci case 0x50: /* Format 5 - Data Check with displacement information */ 6988c2ecf20Sopenharmony_ci switch (msg_no) { 6998c2ecf20Sopenharmony_ci case 0x00: 7008c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7018c2ecf20Sopenharmony_ci "FORMAT 5 - Data Check in the " 7028c2ecf20Sopenharmony_ci "home address area\n"); 7038c2ecf20Sopenharmony_ci break; 7048c2ecf20Sopenharmony_ci case 0x01: 7058c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7068c2ecf20Sopenharmony_ci "FORMAT 5 - Data Check in the count " 7078c2ecf20Sopenharmony_ci "area\n"); 7088c2ecf20Sopenharmony_ci break; 7098c2ecf20Sopenharmony_ci case 0x02: 7108c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7118c2ecf20Sopenharmony_ci "FORMAT 5 - Data Check in the key area\n"); 7128c2ecf20Sopenharmony_ci break; 7138c2ecf20Sopenharmony_ci case 0x03: 7148c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7158c2ecf20Sopenharmony_ci "FORMAT 5 - Data Check in the data " 7168c2ecf20Sopenharmony_ci "area\n"); 7178c2ecf20Sopenharmony_ci break; 7188c2ecf20Sopenharmony_ci case 0x08: 7198c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7208c2ecf20Sopenharmony_ci "FORMAT 5 - Data Check in the " 7218c2ecf20Sopenharmony_ci "home address area; offset active\n"); 7228c2ecf20Sopenharmony_ci break; 7238c2ecf20Sopenharmony_ci case 0x09: 7248c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7258c2ecf20Sopenharmony_ci "FORMAT 5 - Data Check in the count area; " 7268c2ecf20Sopenharmony_ci "offset active\n"); 7278c2ecf20Sopenharmony_ci break; 7288c2ecf20Sopenharmony_ci case 0x0A: 7298c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7308c2ecf20Sopenharmony_ci "FORMAT 5 - Data Check in the key area; " 7318c2ecf20Sopenharmony_ci "offset active\n"); 7328c2ecf20Sopenharmony_ci break; 7338c2ecf20Sopenharmony_ci case 0x0B: 7348c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7358c2ecf20Sopenharmony_ci "FORMAT 5 - Data Check in the data area; " 7368c2ecf20Sopenharmony_ci "offset active\n"); 7378c2ecf20Sopenharmony_ci break; 7388c2ecf20Sopenharmony_ci default: 7398c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7408c2ecf20Sopenharmony_ci "FORMAT 5 - Reserved\n"); 7418c2ecf20Sopenharmony_ci } 7428c2ecf20Sopenharmony_ci break; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci case 0x60: /* Format 6 - Usage Statistics/Overrun Errors */ 7458c2ecf20Sopenharmony_ci switch (msg_no) { 7468c2ecf20Sopenharmony_ci case 0x00: 7478c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7488c2ecf20Sopenharmony_ci "FORMAT 6 - Overrun on channel A\n"); 7498c2ecf20Sopenharmony_ci break; 7508c2ecf20Sopenharmony_ci case 0x01: 7518c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7528c2ecf20Sopenharmony_ci "FORMAT 6 - Overrun on channel B\n"); 7538c2ecf20Sopenharmony_ci break; 7548c2ecf20Sopenharmony_ci case 0x02: 7558c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7568c2ecf20Sopenharmony_ci "FORMAT 6 - Overrun on channel C\n"); 7578c2ecf20Sopenharmony_ci break; 7588c2ecf20Sopenharmony_ci case 0x03: 7598c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7608c2ecf20Sopenharmony_ci "FORMAT 6 - Overrun on channel D\n"); 7618c2ecf20Sopenharmony_ci break; 7628c2ecf20Sopenharmony_ci case 0x04: 7638c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7648c2ecf20Sopenharmony_ci "FORMAT 6 - Overrun on channel E\n"); 7658c2ecf20Sopenharmony_ci break; 7668c2ecf20Sopenharmony_ci case 0x05: 7678c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7688c2ecf20Sopenharmony_ci "FORMAT 6 - Overrun on channel F\n"); 7698c2ecf20Sopenharmony_ci break; 7708c2ecf20Sopenharmony_ci case 0x06: 7718c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7728c2ecf20Sopenharmony_ci "FORMAT 6 - Overrun on channel G\n"); 7738c2ecf20Sopenharmony_ci break; 7748c2ecf20Sopenharmony_ci case 0x07: 7758c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7768c2ecf20Sopenharmony_ci "FORMAT 6 - Overrun on channel H\n"); 7778c2ecf20Sopenharmony_ci break; 7788c2ecf20Sopenharmony_ci default: 7798c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7808c2ecf20Sopenharmony_ci "FORMAT 6 - Reserved\n"); 7818c2ecf20Sopenharmony_ci } 7828c2ecf20Sopenharmony_ci break; 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci case 0x70: /* Format 7 - Device Connection Control Checks */ 7858c2ecf20Sopenharmony_ci switch (msg_no) { 7868c2ecf20Sopenharmony_ci case 0x00: 7878c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7888c2ecf20Sopenharmony_ci "FORMAT 7 - RCC initiated by a connection " 7898c2ecf20Sopenharmony_ci "check alert\n"); 7908c2ecf20Sopenharmony_ci break; 7918c2ecf20Sopenharmony_ci case 0x01: 7928c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7938c2ecf20Sopenharmony_ci "FORMAT 7 - RCC 1 sequence not " 7948c2ecf20Sopenharmony_ci "successful\n"); 7958c2ecf20Sopenharmony_ci break; 7968c2ecf20Sopenharmony_ci case 0x02: 7978c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 7988c2ecf20Sopenharmony_ci "FORMAT 7 - RCC 1 and RCC 2 sequences not " 7998c2ecf20Sopenharmony_ci "successful\n"); 8008c2ecf20Sopenharmony_ci break; 8018c2ecf20Sopenharmony_ci case 0x03: 8028c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8038c2ecf20Sopenharmony_ci "FORMAT 7 - Invalid tag-in during " 8048c2ecf20Sopenharmony_ci "selection sequence\n"); 8058c2ecf20Sopenharmony_ci break; 8068c2ecf20Sopenharmony_ci case 0x04: 8078c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8088c2ecf20Sopenharmony_ci "FORMAT 7 - extra RCC required\n"); 8098c2ecf20Sopenharmony_ci break; 8108c2ecf20Sopenharmony_ci case 0x05: 8118c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8128c2ecf20Sopenharmony_ci "FORMAT 7 - Invalid DCC selection " 8138c2ecf20Sopenharmony_ci "response or timeout\n"); 8148c2ecf20Sopenharmony_ci break; 8158c2ecf20Sopenharmony_ci case 0x06: 8168c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8178c2ecf20Sopenharmony_ci "FORMAT 7 - Missing end operation; device " 8188c2ecf20Sopenharmony_ci "transfer complete\n"); 8198c2ecf20Sopenharmony_ci break; 8208c2ecf20Sopenharmony_ci case 0x07: 8218c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8228c2ecf20Sopenharmony_ci "FORMAT 7 - Missing end operation; device " 8238c2ecf20Sopenharmony_ci "transfer incomplete\n"); 8248c2ecf20Sopenharmony_ci break; 8258c2ecf20Sopenharmony_ci case 0x08: 8268c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8278c2ecf20Sopenharmony_ci "FORMAT 7 - Invalid tag-in for an " 8288c2ecf20Sopenharmony_ci "immediate command sequence\n"); 8298c2ecf20Sopenharmony_ci break; 8308c2ecf20Sopenharmony_ci case 0x09: 8318c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8328c2ecf20Sopenharmony_ci "FORMAT 7 - Invalid tag-in for an " 8338c2ecf20Sopenharmony_ci "extended command sequence\n"); 8348c2ecf20Sopenharmony_ci break; 8358c2ecf20Sopenharmony_ci case 0x0A: 8368c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8378c2ecf20Sopenharmony_ci "FORMAT 7 - 3990 microcode time out when " 8388c2ecf20Sopenharmony_ci "stopping selection\n"); 8398c2ecf20Sopenharmony_ci break; 8408c2ecf20Sopenharmony_ci case 0x0B: 8418c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8428c2ecf20Sopenharmony_ci "FORMAT 7 - No response to selection " 8438c2ecf20Sopenharmony_ci "after a poll interruption\n"); 8448c2ecf20Sopenharmony_ci break; 8458c2ecf20Sopenharmony_ci case 0x0C: 8468c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8478c2ecf20Sopenharmony_ci "FORMAT 7 - Permanent path error (DASD " 8488c2ecf20Sopenharmony_ci "controller not available)\n"); 8498c2ecf20Sopenharmony_ci break; 8508c2ecf20Sopenharmony_ci case 0x0D: 8518c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8528c2ecf20Sopenharmony_ci "FORMAT 7 - DASD controller not available" 8538c2ecf20Sopenharmony_ci " on disconnected command chain\n"); 8548c2ecf20Sopenharmony_ci break; 8558c2ecf20Sopenharmony_ci default: 8568c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8578c2ecf20Sopenharmony_ci "FORMAT 7 - Reserved\n"); 8588c2ecf20Sopenharmony_ci } 8598c2ecf20Sopenharmony_ci break; 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci case 0x80: /* Format 8 - Additional Device Equipment Checks */ 8628c2ecf20Sopenharmony_ci switch (msg_no) { 8638c2ecf20Sopenharmony_ci case 0x00: /* No Message */ 8648c2ecf20Sopenharmony_ci case 0x01: 8658c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8668c2ecf20Sopenharmony_ci "FORMAT 8 - Error correction code " 8678c2ecf20Sopenharmony_ci "hardware fault\n"); 8688c2ecf20Sopenharmony_ci break; 8698c2ecf20Sopenharmony_ci case 0x03: 8708c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8718c2ecf20Sopenharmony_ci "FORMAT 8 - Unexpected end operation " 8728c2ecf20Sopenharmony_ci "response code\n"); 8738c2ecf20Sopenharmony_ci break; 8748c2ecf20Sopenharmony_ci case 0x04: 8758c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8768c2ecf20Sopenharmony_ci "FORMAT 8 - End operation with transfer " 8778c2ecf20Sopenharmony_ci "count not zero\n"); 8788c2ecf20Sopenharmony_ci break; 8798c2ecf20Sopenharmony_ci case 0x05: 8808c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8818c2ecf20Sopenharmony_ci "FORMAT 8 - End operation with transfer " 8828c2ecf20Sopenharmony_ci "count zero\n"); 8838c2ecf20Sopenharmony_ci break; 8848c2ecf20Sopenharmony_ci case 0x06: 8858c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8868c2ecf20Sopenharmony_ci "FORMAT 8 - DPS checks after a system " 8878c2ecf20Sopenharmony_ci "reset or selective reset\n"); 8888c2ecf20Sopenharmony_ci break; 8898c2ecf20Sopenharmony_ci case 0x07: 8908c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8918c2ecf20Sopenharmony_ci "FORMAT 8 - DPS cannot be filled\n"); 8928c2ecf20Sopenharmony_ci break; 8938c2ecf20Sopenharmony_ci case 0x08: 8948c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 8958c2ecf20Sopenharmony_ci "FORMAT 8 - Short busy time-out during " 8968c2ecf20Sopenharmony_ci "device selection\n"); 8978c2ecf20Sopenharmony_ci break; 8988c2ecf20Sopenharmony_ci case 0x09: 8998c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9008c2ecf20Sopenharmony_ci "FORMAT 8 - DASD controller failed to " 9018c2ecf20Sopenharmony_ci "set or reset the long busy latch\n"); 9028c2ecf20Sopenharmony_ci break; 9038c2ecf20Sopenharmony_ci case 0x0A: 9048c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9058c2ecf20Sopenharmony_ci "FORMAT 8 - No interruption from device " 9068c2ecf20Sopenharmony_ci "during a command chain\n"); 9078c2ecf20Sopenharmony_ci break; 9088c2ecf20Sopenharmony_ci default: 9098c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9108c2ecf20Sopenharmony_ci "FORMAT 8 - Reserved\n"); 9118c2ecf20Sopenharmony_ci } 9128c2ecf20Sopenharmony_ci break; 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci case 0x90: /* Format 9 - Device Read, Write, and Seek Checks */ 9158c2ecf20Sopenharmony_ci switch (msg_no) { 9168c2ecf20Sopenharmony_ci case 0x00: 9178c2ecf20Sopenharmony_ci break; /* No Message */ 9188c2ecf20Sopenharmony_ci case 0x06: 9198c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9208c2ecf20Sopenharmony_ci "FORMAT 9 - Device check-2 error\n"); 9218c2ecf20Sopenharmony_ci break; 9228c2ecf20Sopenharmony_ci case 0x07: 9238c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9248c2ecf20Sopenharmony_ci "FORMAT 9 - Head address did not " 9258c2ecf20Sopenharmony_ci "compare\n"); 9268c2ecf20Sopenharmony_ci break; 9278c2ecf20Sopenharmony_ci case 0x0A: 9288c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9298c2ecf20Sopenharmony_ci "FORMAT 9 - Track physical address did " 9308c2ecf20Sopenharmony_ci "not compare while oriented\n"); 9318c2ecf20Sopenharmony_ci break; 9328c2ecf20Sopenharmony_ci case 0x0E: 9338c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9348c2ecf20Sopenharmony_ci "FORMAT 9 - Cylinder address did not " 9358c2ecf20Sopenharmony_ci "compare\n"); 9368c2ecf20Sopenharmony_ci break; 9378c2ecf20Sopenharmony_ci default: 9388c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9398c2ecf20Sopenharmony_ci "FORMAT 9 - Reserved\n"); 9408c2ecf20Sopenharmony_ci } 9418c2ecf20Sopenharmony_ci break; 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci case 0xF0: /* Format F - Cache Storage Checks */ 9448c2ecf20Sopenharmony_ci switch (msg_no) { 9458c2ecf20Sopenharmony_ci case 0x00: 9468c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9478c2ecf20Sopenharmony_ci "FORMAT F - Operation Terminated\n"); 9488c2ecf20Sopenharmony_ci break; 9498c2ecf20Sopenharmony_ci case 0x01: 9508c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9518c2ecf20Sopenharmony_ci "FORMAT F - Subsystem Processing Error\n"); 9528c2ecf20Sopenharmony_ci break; 9538c2ecf20Sopenharmony_ci case 0x02: 9548c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9558c2ecf20Sopenharmony_ci "FORMAT F - Cache or nonvolatile storage " 9568c2ecf20Sopenharmony_ci "equipment failure\n"); 9578c2ecf20Sopenharmony_ci break; 9588c2ecf20Sopenharmony_ci case 0x04: 9598c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9608c2ecf20Sopenharmony_ci "FORMAT F - Caching terminated\n"); 9618c2ecf20Sopenharmony_ci break; 9628c2ecf20Sopenharmony_ci case 0x06: 9638c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9648c2ecf20Sopenharmony_ci "FORMAT F - Cache fast write access not " 9658c2ecf20Sopenharmony_ci "authorized\n"); 9668c2ecf20Sopenharmony_ci break; 9678c2ecf20Sopenharmony_ci case 0x07: 9688c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9698c2ecf20Sopenharmony_ci "FORMAT F - Track format incorrect\n"); 9708c2ecf20Sopenharmony_ci break; 9718c2ecf20Sopenharmony_ci case 0x09: 9728c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9738c2ecf20Sopenharmony_ci "FORMAT F - Caching reinitiated\n"); 9748c2ecf20Sopenharmony_ci break; 9758c2ecf20Sopenharmony_ci case 0x0A: 9768c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9778c2ecf20Sopenharmony_ci "FORMAT F - Nonvolatile storage " 9788c2ecf20Sopenharmony_ci "terminated\n"); 9798c2ecf20Sopenharmony_ci break; 9808c2ecf20Sopenharmony_ci case 0x0B: 9818c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9828c2ecf20Sopenharmony_ci "FORMAT F - Volume is suspended duplex\n"); 9838c2ecf20Sopenharmony_ci /* call extended error reporting (EER) */ 9848c2ecf20Sopenharmony_ci dasd_eer_write(device, erp->refers, 9858c2ecf20Sopenharmony_ci DASD_EER_PPRCSUSPEND); 9868c2ecf20Sopenharmony_ci break; 9878c2ecf20Sopenharmony_ci case 0x0C: 9888c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9898c2ecf20Sopenharmony_ci "FORMAT F - Subsystem status cannot be " 9908c2ecf20Sopenharmony_ci "determined\n"); 9918c2ecf20Sopenharmony_ci break; 9928c2ecf20Sopenharmony_ci case 0x0D: 9938c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9948c2ecf20Sopenharmony_ci "FORMAT F - Caching status reset to " 9958c2ecf20Sopenharmony_ci "default\n"); 9968c2ecf20Sopenharmony_ci break; 9978c2ecf20Sopenharmony_ci case 0x0E: 9988c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 9998c2ecf20Sopenharmony_ci "FORMAT F - DASD Fast Write inhibited\n"); 10008c2ecf20Sopenharmony_ci break; 10018c2ecf20Sopenharmony_ci default: 10028c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, 10038c2ecf20Sopenharmony_ci "FORMAT F - Reserved\n"); 10048c2ecf20Sopenharmony_ci } 10058c2ecf20Sopenharmony_ci break; 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci default: /* unknown message format - should not happen 10088c2ecf20Sopenharmony_ci internal error 03 - unknown message format */ 10098c2ecf20Sopenharmony_ci snprintf(errorstring, ERRORLENGTH, "03 %x02", msg_format); 10108c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 10118c2ecf20Sopenharmony_ci "An error occurred in the DASD device driver, " 10128c2ecf20Sopenharmony_ci "reason=%s\n", errorstring); 10138c2ecf20Sopenharmony_ci break; 10148c2ecf20Sopenharmony_ci } /* end switch message format */ 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci} /* end dasd_3990_handle_env_data */ 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci/* 10198c2ecf20Sopenharmony_ci * DASD_3990_ERP_COM_REJ 10208c2ecf20Sopenharmony_ci * 10218c2ecf20Sopenharmony_ci * DESCRIPTION 10228c2ecf20Sopenharmony_ci * Handles 24 byte 'Command Reject' error. 10238c2ecf20Sopenharmony_ci * 10248c2ecf20Sopenharmony_ci * PARAMETER 10258c2ecf20Sopenharmony_ci * erp current erp_head 10268c2ecf20Sopenharmony_ci * sense current sense data 10278c2ecf20Sopenharmony_ci * 10288c2ecf20Sopenharmony_ci * RETURN VALUES 10298c2ecf20Sopenharmony_ci * erp 'new' erp_head - pointer to new ERP 10308c2ecf20Sopenharmony_ci */ 10318c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 10328c2ecf20Sopenharmony_cidasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) 10338c2ecf20Sopenharmony_ci{ 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_com_rej; 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci /* env data present (ACTION 10 - retry should work) */ 10408c2ecf20Sopenharmony_ci if (sense[2] & SNS2_ENV_DATA_PRESENT) { 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 10438c2ecf20Sopenharmony_ci "Command Reject - environmental data present"); 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci dasd_3990_handle_env_data(erp, sense); 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci erp->retries = 5; 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci } else if (sense[1] & SNS1_WRITE_INHIBITED) { 10508c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, "An I/O request was rejected" 10518c2ecf20Sopenharmony_ci " because writing is inhibited\n"); 10528c2ecf20Sopenharmony_ci erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); 10538c2ecf20Sopenharmony_ci } else { 10548c2ecf20Sopenharmony_ci /* fatal error - set status to FAILED 10558c2ecf20Sopenharmony_ci internal error 09 - Command Reject */ 10568c2ecf20Sopenharmony_ci if (!test_bit(DASD_CQR_SUPPRESS_CR, &erp->flags)) 10578c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 10588c2ecf20Sopenharmony_ci "An error occurred in the DASD device driver, reason=09\n"); 10598c2ecf20Sopenharmony_ci 10608c2ecf20Sopenharmony_ci erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); 10618c2ecf20Sopenharmony_ci } 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci return erp; 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_com_rej */ 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci/* 10688c2ecf20Sopenharmony_ci * DASD_3990_ERP_BUS_OUT 10698c2ecf20Sopenharmony_ci * 10708c2ecf20Sopenharmony_ci * DESCRIPTION 10718c2ecf20Sopenharmony_ci * Handles 24 byte 'Bus Out Parity Check' error. 10728c2ecf20Sopenharmony_ci * 10738c2ecf20Sopenharmony_ci * PARAMETER 10748c2ecf20Sopenharmony_ci * erp current erp_head 10758c2ecf20Sopenharmony_ci * RETURN VALUES 10768c2ecf20Sopenharmony_ci * erp new erp_head - pointer to new ERP 10778c2ecf20Sopenharmony_ci */ 10788c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 10798c2ecf20Sopenharmony_cidasd_3990_erp_bus_out(struct dasd_ccw_req * erp) 10808c2ecf20Sopenharmony_ci{ 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci /* first time set initial retry counter and erp_function */ 10858c2ecf20Sopenharmony_ci /* and retry once without blocking queue */ 10868c2ecf20Sopenharmony_ci /* (this enables easier enqueing of the cqr) */ 10878c2ecf20Sopenharmony_ci if (erp->function != dasd_3990_erp_bus_out) { 10888c2ecf20Sopenharmony_ci erp->retries = 256; 10898c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_bus_out; 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci } else { 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci /* issue a message and wait for 'device ready' interrupt */ 10948c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 10958c2ecf20Sopenharmony_ci "bus out parity error or BOPC requested by " 10968c2ecf20Sopenharmony_ci "channel"); 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci dasd_3990_erp_block_queue(erp, 60*HZ); 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci } 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci return erp; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_bus_out */ 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci/* 11078c2ecf20Sopenharmony_ci * DASD_3990_ERP_EQUIP_CHECK 11088c2ecf20Sopenharmony_ci * 11098c2ecf20Sopenharmony_ci * DESCRIPTION 11108c2ecf20Sopenharmony_ci * Handles 24 byte 'Equipment Check' error. 11118c2ecf20Sopenharmony_ci * 11128c2ecf20Sopenharmony_ci * PARAMETER 11138c2ecf20Sopenharmony_ci * erp current erp_head 11148c2ecf20Sopenharmony_ci * RETURN VALUES 11158c2ecf20Sopenharmony_ci * erp new erp_head - pointer to new ERP 11168c2ecf20Sopenharmony_ci */ 11178c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 11188c2ecf20Sopenharmony_cidasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense) 11198c2ecf20Sopenharmony_ci{ 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_equip_check; 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci if (sense[1] & SNS1_WRITE_INHIBITED) { 11268c2ecf20Sopenharmony_ci dev_info(&device->cdev->dev, 11278c2ecf20Sopenharmony_ci "Write inhibited path encountered\n"); 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci /* vary path offline 11308c2ecf20Sopenharmony_ci internal error 04 - Path should be varied off-line.*/ 11318c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, "An error occurred in the DASD " 11328c2ecf20Sopenharmony_ci "device driver, reason=%s\n", "04"); 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_1(erp); 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci } else if (sense[2] & SNS2_ENV_DATA_PRESENT) { 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 11398c2ecf20Sopenharmony_ci "Equipment Check - " "environmental data present"); 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci dasd_3990_handle_env_data(erp, sense); 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_4(erp, sense); 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci } else if (sense[1] & SNS1_PERM_ERR) { 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 11488c2ecf20Sopenharmony_ci "Equipment Check - retry exhausted or " 11498c2ecf20Sopenharmony_ci "undesirable"); 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_1(erp); 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci } else { 11548c2ecf20Sopenharmony_ci /* all other equipment checks - Action 5 */ 11558c2ecf20Sopenharmony_ci /* rest is done when retries == 0 */ 11568c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 11578c2ecf20Sopenharmony_ci "Equipment check or processing error"); 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_5(erp); 11608c2ecf20Sopenharmony_ci } 11618c2ecf20Sopenharmony_ci return erp; 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_equip_check */ 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci/* 11668c2ecf20Sopenharmony_ci * DASD_3990_ERP_DATA_CHECK 11678c2ecf20Sopenharmony_ci * 11688c2ecf20Sopenharmony_ci * DESCRIPTION 11698c2ecf20Sopenharmony_ci * Handles 24 byte 'Data Check' error. 11708c2ecf20Sopenharmony_ci * 11718c2ecf20Sopenharmony_ci * PARAMETER 11728c2ecf20Sopenharmony_ci * erp current erp_head 11738c2ecf20Sopenharmony_ci * RETURN VALUES 11748c2ecf20Sopenharmony_ci * erp new erp_head - pointer to new ERP 11758c2ecf20Sopenharmony_ci */ 11768c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 11778c2ecf20Sopenharmony_cidasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense) 11788c2ecf20Sopenharmony_ci{ 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_data_check; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci if (sense[2] & SNS2_CORRECTABLE) { /* correctable data check */ 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci /* issue message that the data has been corrected */ 11878c2ecf20Sopenharmony_ci dev_emerg(&device->cdev->dev, 11888c2ecf20Sopenharmony_ci "Data recovered during retry with PCI " 11898c2ecf20Sopenharmony_ci "fetch mode active\n"); 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci /* not possible to handle this situation in Linux */ 11928c2ecf20Sopenharmony_ci panic("No way to inform application about the possibly " 11938c2ecf20Sopenharmony_ci "incorrect data"); 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci } else if (sense[2] & SNS2_ENV_DATA_PRESENT) { 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 11988c2ecf20Sopenharmony_ci "Uncorrectable data check recovered secondary " 11998c2ecf20Sopenharmony_ci "addr of duplex pair"); 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_4(erp, sense); 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci } else if (sense[1] & SNS1_PERM_ERR) { 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 12068c2ecf20Sopenharmony_ci "Uncorrectable data check with internal " 12078c2ecf20Sopenharmony_ci "retry exhausted"); 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_1(erp); 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci } else { 12128c2ecf20Sopenharmony_ci /* all other data checks */ 12138c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 12148c2ecf20Sopenharmony_ci "Uncorrectable data check with retry count " 12158c2ecf20Sopenharmony_ci "exhausted..."); 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_5(erp); 12188c2ecf20Sopenharmony_ci } 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci return erp; 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_data_check */ 12238c2ecf20Sopenharmony_ci 12248c2ecf20Sopenharmony_ci/* 12258c2ecf20Sopenharmony_ci * DASD_3990_ERP_OVERRUN 12268c2ecf20Sopenharmony_ci * 12278c2ecf20Sopenharmony_ci * DESCRIPTION 12288c2ecf20Sopenharmony_ci * Handles 24 byte 'Overrun' error. 12298c2ecf20Sopenharmony_ci * 12308c2ecf20Sopenharmony_ci * PARAMETER 12318c2ecf20Sopenharmony_ci * erp current erp_head 12328c2ecf20Sopenharmony_ci * RETURN VALUES 12338c2ecf20Sopenharmony_ci * erp new erp_head - pointer to new ERP 12348c2ecf20Sopenharmony_ci */ 12358c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 12368c2ecf20Sopenharmony_cidasd_3990_erp_overrun(struct dasd_ccw_req * erp, char *sense) 12378c2ecf20Sopenharmony_ci{ 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_overrun; 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 12448c2ecf20Sopenharmony_ci "Overrun - service overrun or overrun" 12458c2ecf20Sopenharmony_ci " error requested by channel"); 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_5(erp); 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci return erp; 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_overrun */ 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci/* 12548c2ecf20Sopenharmony_ci * DASD_3990_ERP_INV_FORMAT 12558c2ecf20Sopenharmony_ci * 12568c2ecf20Sopenharmony_ci * DESCRIPTION 12578c2ecf20Sopenharmony_ci * Handles 24 byte 'Invalid Track Format' error. 12588c2ecf20Sopenharmony_ci * 12598c2ecf20Sopenharmony_ci * PARAMETER 12608c2ecf20Sopenharmony_ci * erp current erp_head 12618c2ecf20Sopenharmony_ci * RETURN VALUES 12628c2ecf20Sopenharmony_ci * erp new erp_head - pointer to new ERP 12638c2ecf20Sopenharmony_ci */ 12648c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 12658c2ecf20Sopenharmony_cidasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense) 12668c2ecf20Sopenharmony_ci{ 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_inv_format; 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci if (sense[2] & SNS2_ENV_DATA_PRESENT) { 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 12758c2ecf20Sopenharmony_ci "Track format error when destaging or " 12768c2ecf20Sopenharmony_ci "staging data"); 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci dasd_3990_handle_env_data(erp, sense); 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_4(erp, sense); 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci } else { 12838c2ecf20Sopenharmony_ci /* internal error 06 - The track format is not valid*/ 12848c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 12858c2ecf20Sopenharmony_ci "An error occurred in the DASD device driver, " 12868c2ecf20Sopenharmony_ci "reason=%s\n", "06"); 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); 12898c2ecf20Sopenharmony_ci } 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci return erp; 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_inv_format */ 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci/* 12968c2ecf20Sopenharmony_ci * DASD_3990_ERP_EOC 12978c2ecf20Sopenharmony_ci * 12988c2ecf20Sopenharmony_ci * DESCRIPTION 12998c2ecf20Sopenharmony_ci * Handles 24 byte 'End-of-Cylinder' error. 13008c2ecf20Sopenharmony_ci * 13018c2ecf20Sopenharmony_ci * PARAMETER 13028c2ecf20Sopenharmony_ci * erp already added default erp 13038c2ecf20Sopenharmony_ci * RETURN VALUES 13048c2ecf20Sopenharmony_ci * erp pointer to original (failed) cqr. 13058c2ecf20Sopenharmony_ci */ 13068c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 13078c2ecf20Sopenharmony_cidasd_3990_erp_EOC(struct dasd_ccw_req * default_erp, char *sense) 13088c2ecf20Sopenharmony_ci{ 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci struct dasd_device *device = default_erp->startdev; 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 13138c2ecf20Sopenharmony_ci "The cylinder data for accessing the DASD is inconsistent\n"); 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci /* implement action 7 - BUG */ 13168c2ecf20Sopenharmony_ci return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_EOC */ 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci/* 13218c2ecf20Sopenharmony_ci * DASD_3990_ERP_ENV_DATA 13228c2ecf20Sopenharmony_ci * 13238c2ecf20Sopenharmony_ci * DESCRIPTION 13248c2ecf20Sopenharmony_ci * Handles 24 byte 'Environmental-Data Present' error. 13258c2ecf20Sopenharmony_ci * 13268c2ecf20Sopenharmony_ci * PARAMETER 13278c2ecf20Sopenharmony_ci * erp current erp_head 13288c2ecf20Sopenharmony_ci * RETURN VALUES 13298c2ecf20Sopenharmony_ci * erp new erp_head - pointer to new ERP 13308c2ecf20Sopenharmony_ci */ 13318c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 13328c2ecf20Sopenharmony_cidasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense) 13338c2ecf20Sopenharmony_ci{ 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_env_data; 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Environmental data present"); 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci dasd_3990_handle_env_data(erp, sense); 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_ci /* don't retry on disabled interface */ 13448c2ecf20Sopenharmony_ci if (sense[7] != 0x0F) { 13458c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_4(erp, sense); 13468c2ecf20Sopenharmony_ci } else { 13478c2ecf20Sopenharmony_ci erp->status = DASD_CQR_FILLED; 13488c2ecf20Sopenharmony_ci } 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci return erp; 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_env_data */ 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci/* 13558c2ecf20Sopenharmony_ci * DASD_3990_ERP_NO_REC 13568c2ecf20Sopenharmony_ci * 13578c2ecf20Sopenharmony_ci * DESCRIPTION 13588c2ecf20Sopenharmony_ci * Handles 24 byte 'No Record Found' error. 13598c2ecf20Sopenharmony_ci * 13608c2ecf20Sopenharmony_ci * PARAMETER 13618c2ecf20Sopenharmony_ci * erp already added default ERP 13628c2ecf20Sopenharmony_ci * 13638c2ecf20Sopenharmony_ci * RETURN VALUES 13648c2ecf20Sopenharmony_ci * erp new erp_head - pointer to new ERP 13658c2ecf20Sopenharmony_ci */ 13668c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 13678c2ecf20Sopenharmony_cidasd_3990_erp_no_rec(struct dasd_ccw_req * default_erp, char *sense) 13688c2ecf20Sopenharmony_ci{ 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_ci struct dasd_device *device = default_erp->startdev; 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci /* 13738c2ecf20Sopenharmony_ci * In some cases the 'No Record Found' error might be expected and 13748c2ecf20Sopenharmony_ci * log messages shouldn't be written then. 13758c2ecf20Sopenharmony_ci * Check if the according suppress bit is set. 13768c2ecf20Sopenharmony_ci */ 13778c2ecf20Sopenharmony_ci if (!test_bit(DASD_CQR_SUPPRESS_NRF, &default_erp->flags)) 13788c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 13798c2ecf20Sopenharmony_ci "The specified record was not found\n"); 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_no_rec */ 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci/* 13868c2ecf20Sopenharmony_ci * DASD_3990_ERP_FILE_PROT 13878c2ecf20Sopenharmony_ci * 13888c2ecf20Sopenharmony_ci * DESCRIPTION 13898c2ecf20Sopenharmony_ci * Handles 24 byte 'File Protected' error. 13908c2ecf20Sopenharmony_ci * Note: Seek related recovery is not implemented because 13918c2ecf20Sopenharmony_ci * wee don't use the seek command yet. 13928c2ecf20Sopenharmony_ci * 13938c2ecf20Sopenharmony_ci * PARAMETER 13948c2ecf20Sopenharmony_ci * erp current erp_head 13958c2ecf20Sopenharmony_ci * RETURN VALUES 13968c2ecf20Sopenharmony_ci * erp new erp_head - pointer to new ERP 13978c2ecf20Sopenharmony_ci */ 13988c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 13998c2ecf20Sopenharmony_cidasd_3990_erp_file_prot(struct dasd_ccw_req * erp) 14008c2ecf20Sopenharmony_ci{ 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci /* 14058c2ecf20Sopenharmony_ci * In some cases the 'File Protected' error might be expected and 14068c2ecf20Sopenharmony_ci * log messages shouldn't be written then. 14078c2ecf20Sopenharmony_ci * Check if the according suppress bit is set. 14088c2ecf20Sopenharmony_ci */ 14098c2ecf20Sopenharmony_ci if (!test_bit(DASD_CQR_SUPPRESS_FP, &erp->flags)) 14108c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 14118c2ecf20Sopenharmony_ci "Accessing the DASD failed because of a hardware error\n"); 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_ci return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_file_prot */ 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci/* 14188c2ecf20Sopenharmony_ci * DASD_3990_ERP_INSPECT_ALIAS 14198c2ecf20Sopenharmony_ci * 14208c2ecf20Sopenharmony_ci * DESCRIPTION 14218c2ecf20Sopenharmony_ci * Checks if the original request was started on an alias device. 14228c2ecf20Sopenharmony_ci * If yes, it modifies the original and the erp request so that 14238c2ecf20Sopenharmony_ci * the erp request can be started on a base device. 14248c2ecf20Sopenharmony_ci * 14258c2ecf20Sopenharmony_ci * PARAMETER 14268c2ecf20Sopenharmony_ci * erp pointer to the currently created default ERP 14278c2ecf20Sopenharmony_ci * 14288c2ecf20Sopenharmony_ci * RETURN VALUES 14298c2ecf20Sopenharmony_ci * erp pointer to the modified ERP, or NULL 14308c2ecf20Sopenharmony_ci */ 14318c2ecf20Sopenharmony_ci 14328c2ecf20Sopenharmony_cistatic struct dasd_ccw_req *dasd_3990_erp_inspect_alias( 14338c2ecf20Sopenharmony_ci struct dasd_ccw_req *erp) 14348c2ecf20Sopenharmony_ci{ 14358c2ecf20Sopenharmony_ci struct dasd_ccw_req *cqr = erp->refers; 14368c2ecf20Sopenharmony_ci char *sense; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci if (cqr->block && 14398c2ecf20Sopenharmony_ci (cqr->block->base != cqr->startdev)) { 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci sense = dasd_get_sense(&erp->refers->irb); 14428c2ecf20Sopenharmony_ci /* 14438c2ecf20Sopenharmony_ci * dynamic pav may have changed base alias mapping 14448c2ecf20Sopenharmony_ci */ 14458c2ecf20Sopenharmony_ci if (!test_bit(DASD_FLAG_OFFLINE, &cqr->startdev->flags) && sense 14468c2ecf20Sopenharmony_ci && (sense[0] == 0x10) && (sense[7] == 0x0F) 14478c2ecf20Sopenharmony_ci && (sense[8] == 0x67)) { 14488c2ecf20Sopenharmony_ci /* 14498c2ecf20Sopenharmony_ci * remove device from alias handling to prevent new 14508c2ecf20Sopenharmony_ci * requests from being scheduled on the 14518c2ecf20Sopenharmony_ci * wrong alias device 14528c2ecf20Sopenharmony_ci */ 14538c2ecf20Sopenharmony_ci dasd_alias_remove_device(cqr->startdev); 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci /* schedule worker to reload device */ 14568c2ecf20Sopenharmony_ci dasd_reload_device(cqr->startdev); 14578c2ecf20Sopenharmony_ci } 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci if (cqr->startdev->features & DASD_FEATURE_ERPLOG) { 14608c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_ERR, cqr->startdev, 14618c2ecf20Sopenharmony_ci "ERP on alias device for request %p," 14628c2ecf20Sopenharmony_ci " recover on base device %s", cqr, 14638c2ecf20Sopenharmony_ci dev_name(&cqr->block->base->cdev->dev)); 14648c2ecf20Sopenharmony_ci } 14658c2ecf20Sopenharmony_ci dasd_eckd_reset_ccw_to_base_io(cqr); 14668c2ecf20Sopenharmony_ci erp->startdev = cqr->block->base; 14678c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_inspect_alias; 14688c2ecf20Sopenharmony_ci return erp; 14698c2ecf20Sopenharmony_ci } else 14708c2ecf20Sopenharmony_ci return NULL; 14718c2ecf20Sopenharmony_ci} 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci/* 14758c2ecf20Sopenharmony_ci * DASD_3990_ERP_INSPECT_24 14768c2ecf20Sopenharmony_ci * 14778c2ecf20Sopenharmony_ci * DESCRIPTION 14788c2ecf20Sopenharmony_ci * Does a detailed inspection of the 24 byte sense data 14798c2ecf20Sopenharmony_ci * and sets up a related error recovery action. 14808c2ecf20Sopenharmony_ci * 14818c2ecf20Sopenharmony_ci * PARAMETER 14828c2ecf20Sopenharmony_ci * sense sense data of the actual error 14838c2ecf20Sopenharmony_ci * erp pointer to the currently created default ERP 14848c2ecf20Sopenharmony_ci * 14858c2ecf20Sopenharmony_ci * RETURN VALUES 14868c2ecf20Sopenharmony_ci * erp pointer to the (addtitional) ERP 14878c2ecf20Sopenharmony_ci */ 14888c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 14898c2ecf20Sopenharmony_cidasd_3990_erp_inspect_24(struct dasd_ccw_req * erp, char *sense) 14908c2ecf20Sopenharmony_ci{ 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci struct dasd_ccw_req *erp_filled = NULL; 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_ci /* Check sense for .... */ 14958c2ecf20Sopenharmony_ci /* 'Command Reject' */ 14968c2ecf20Sopenharmony_ci if ((erp_filled == NULL) && (sense[0] & SNS0_CMD_REJECT)) { 14978c2ecf20Sopenharmony_ci erp_filled = dasd_3990_erp_com_rej(erp, sense); 14988c2ecf20Sopenharmony_ci } 14998c2ecf20Sopenharmony_ci /* 'Intervention Required' */ 15008c2ecf20Sopenharmony_ci if ((erp_filled == NULL) && (sense[0] & SNS0_INTERVENTION_REQ)) { 15018c2ecf20Sopenharmony_ci erp_filled = dasd_3990_erp_int_req(erp); 15028c2ecf20Sopenharmony_ci } 15038c2ecf20Sopenharmony_ci /* 'Bus Out Parity Check' */ 15048c2ecf20Sopenharmony_ci if ((erp_filled == NULL) && (sense[0] & SNS0_BUS_OUT_CHECK)) { 15058c2ecf20Sopenharmony_ci erp_filled = dasd_3990_erp_bus_out(erp); 15068c2ecf20Sopenharmony_ci } 15078c2ecf20Sopenharmony_ci /* 'Equipment Check' */ 15088c2ecf20Sopenharmony_ci if ((erp_filled == NULL) && (sense[0] & SNS0_EQUIPMENT_CHECK)) { 15098c2ecf20Sopenharmony_ci erp_filled = dasd_3990_erp_equip_check(erp, sense); 15108c2ecf20Sopenharmony_ci } 15118c2ecf20Sopenharmony_ci /* 'Data Check' */ 15128c2ecf20Sopenharmony_ci if ((erp_filled == NULL) && (sense[0] & SNS0_DATA_CHECK)) { 15138c2ecf20Sopenharmony_ci erp_filled = dasd_3990_erp_data_check(erp, sense); 15148c2ecf20Sopenharmony_ci } 15158c2ecf20Sopenharmony_ci /* 'Overrun' */ 15168c2ecf20Sopenharmony_ci if ((erp_filled == NULL) && (sense[0] & SNS0_OVERRUN)) { 15178c2ecf20Sopenharmony_ci erp_filled = dasd_3990_erp_overrun(erp, sense); 15188c2ecf20Sopenharmony_ci } 15198c2ecf20Sopenharmony_ci /* 'Invalid Track Format' */ 15208c2ecf20Sopenharmony_ci if ((erp_filled == NULL) && (sense[1] & SNS1_INV_TRACK_FORMAT)) { 15218c2ecf20Sopenharmony_ci erp_filled = dasd_3990_erp_inv_format(erp, sense); 15228c2ecf20Sopenharmony_ci } 15238c2ecf20Sopenharmony_ci /* 'End-of-Cylinder' */ 15248c2ecf20Sopenharmony_ci if ((erp_filled == NULL) && (sense[1] & SNS1_EOC)) { 15258c2ecf20Sopenharmony_ci erp_filled = dasd_3990_erp_EOC(erp, sense); 15268c2ecf20Sopenharmony_ci } 15278c2ecf20Sopenharmony_ci /* 'Environmental Data' */ 15288c2ecf20Sopenharmony_ci if ((erp_filled == NULL) && (sense[2] & SNS2_ENV_DATA_PRESENT)) { 15298c2ecf20Sopenharmony_ci erp_filled = dasd_3990_erp_env_data(erp, sense); 15308c2ecf20Sopenharmony_ci } 15318c2ecf20Sopenharmony_ci /* 'No Record Found' */ 15328c2ecf20Sopenharmony_ci if ((erp_filled == NULL) && (sense[1] & SNS1_NO_REC_FOUND)) { 15338c2ecf20Sopenharmony_ci erp_filled = dasd_3990_erp_no_rec(erp, sense); 15348c2ecf20Sopenharmony_ci } 15358c2ecf20Sopenharmony_ci /* 'File Protected' */ 15368c2ecf20Sopenharmony_ci if ((erp_filled == NULL) && (sense[1] & SNS1_FILE_PROTECTED)) { 15378c2ecf20Sopenharmony_ci erp_filled = dasd_3990_erp_file_prot(erp); 15388c2ecf20Sopenharmony_ci } 15398c2ecf20Sopenharmony_ci /* other (unknown) error - do default ERP */ 15408c2ecf20Sopenharmony_ci if (erp_filled == NULL) { 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_ci erp_filled = erp; 15438c2ecf20Sopenharmony_ci } 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci return erp_filled; 15468c2ecf20Sopenharmony_ci 15478c2ecf20Sopenharmony_ci} /* END dasd_3990_erp_inspect_24 */ 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_ci/* 15508c2ecf20Sopenharmony_ci ***************************************************************************** 15518c2ecf20Sopenharmony_ci * 32 byte sense ERP functions (only) 15528c2ecf20Sopenharmony_ci ***************************************************************************** 15538c2ecf20Sopenharmony_ci */ 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci/* 15568c2ecf20Sopenharmony_ci * DASD_3990_ERPACTION_10_32 15578c2ecf20Sopenharmony_ci * 15588c2ecf20Sopenharmony_ci * DESCRIPTION 15598c2ecf20Sopenharmony_ci * Handles 32 byte 'Action 10' of Single Program Action Codes. 15608c2ecf20Sopenharmony_ci * Just retry and if retry doesn't work, return with error. 15618c2ecf20Sopenharmony_ci * 15628c2ecf20Sopenharmony_ci * PARAMETER 15638c2ecf20Sopenharmony_ci * erp current erp_head 15648c2ecf20Sopenharmony_ci * sense current sense data 15658c2ecf20Sopenharmony_ci * RETURN VALUES 15668c2ecf20Sopenharmony_ci * erp modified erp_head 15678c2ecf20Sopenharmony_ci */ 15688c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 15698c2ecf20Sopenharmony_cidasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense) 15708c2ecf20Sopenharmony_ci{ 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci erp->retries = 256; 15758c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_action_10_32; 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", "Perform logging requested"); 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci return erp; 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_action_10_32 */ 15828c2ecf20Sopenharmony_ci 15838c2ecf20Sopenharmony_ci/* 15848c2ecf20Sopenharmony_ci * DASD_3990_ERP_ACTION_1B_32 15858c2ecf20Sopenharmony_ci * 15868c2ecf20Sopenharmony_ci * DESCRIPTION 15878c2ecf20Sopenharmony_ci * Handles 32 byte 'Action 1B' of Single Program Action Codes. 15888c2ecf20Sopenharmony_ci * A write operation could not be finished because of an unexpected 15898c2ecf20Sopenharmony_ci * condition. 15908c2ecf20Sopenharmony_ci * The already created 'default erp' is used to get the link to 15918c2ecf20Sopenharmony_ci * the erp chain, but it can not be used for this recovery 15928c2ecf20Sopenharmony_ci * action because it contains no DE/LO data space. 15938c2ecf20Sopenharmony_ci * 15948c2ecf20Sopenharmony_ci * PARAMETER 15958c2ecf20Sopenharmony_ci * default_erp already added default erp. 15968c2ecf20Sopenharmony_ci * sense current sense data 15978c2ecf20Sopenharmony_ci * 15988c2ecf20Sopenharmony_ci * RETURN VALUES 15998c2ecf20Sopenharmony_ci * erp new erp or 16008c2ecf20Sopenharmony_ci * default_erp in case of imprecise ending or error 16018c2ecf20Sopenharmony_ci */ 16028c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 16038c2ecf20Sopenharmony_cidasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) 16048c2ecf20Sopenharmony_ci{ 16058c2ecf20Sopenharmony_ci 16068c2ecf20Sopenharmony_ci struct dasd_device *device = default_erp->startdev; 16078c2ecf20Sopenharmony_ci __u32 cpa = 0; 16088c2ecf20Sopenharmony_ci struct dasd_ccw_req *cqr; 16098c2ecf20Sopenharmony_ci struct dasd_ccw_req *erp; 16108c2ecf20Sopenharmony_ci struct DE_eckd_data *DE_data; 16118c2ecf20Sopenharmony_ci struct PFX_eckd_data *PFX_data; 16128c2ecf20Sopenharmony_ci char *LO_data; /* LO_eckd_data_t */ 16138c2ecf20Sopenharmony_ci struct ccw1 *ccw, *oldccw; 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 16168c2ecf20Sopenharmony_ci "Write not finished because of unexpected condition"); 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_ci default_erp->function = dasd_3990_erp_action_1B_32; 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci /* determine the original cqr */ 16218c2ecf20Sopenharmony_ci cqr = default_erp; 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ci while (cqr->refers != NULL) { 16248c2ecf20Sopenharmony_ci cqr = cqr->refers; 16258c2ecf20Sopenharmony_ci } 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_ci if (scsw_is_tm(&cqr->irb.scsw)) { 16288c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 16298c2ecf20Sopenharmony_ci "32 bit sense, action 1B is not defined" 16308c2ecf20Sopenharmony_ci " in transport mode - just retry"); 16318c2ecf20Sopenharmony_ci return default_erp; 16328c2ecf20Sopenharmony_ci } 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci /* for imprecise ending just do default erp */ 16358c2ecf20Sopenharmony_ci if (sense[1] & 0x01) { 16368c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 16378c2ecf20Sopenharmony_ci "Imprecise ending is set - just retry"); 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci return default_erp; 16408c2ecf20Sopenharmony_ci } 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci /* determine the address of the CCW to be restarted */ 16438c2ecf20Sopenharmony_ci /* Imprecise ending is not set -> addr from IRB-SCSW */ 16448c2ecf20Sopenharmony_ci cpa = default_erp->refers->irb.scsw.cmd.cpa; 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci if (cpa == 0) { 16478c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 16488c2ecf20Sopenharmony_ci "Unable to determine address of the CCW " 16498c2ecf20Sopenharmony_ci "to be restarted"); 16508c2ecf20Sopenharmony_ci 16518c2ecf20Sopenharmony_ci return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); 16528c2ecf20Sopenharmony_ci } 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci /* Build new ERP request including DE/LO */ 16558c2ecf20Sopenharmony_ci erp = dasd_alloc_erp_request((char *) &cqr->magic, 16568c2ecf20Sopenharmony_ci 2 + 1,/* DE/LO + TIC */ 16578c2ecf20Sopenharmony_ci sizeof(struct DE_eckd_data) + 16588c2ecf20Sopenharmony_ci sizeof(struct LO_eckd_data), device); 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_ci if (IS_ERR(erp)) { 16618c2ecf20Sopenharmony_ci /* internal error 01 - Unable to allocate ERP */ 16628c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, "An error occurred in the DASD " 16638c2ecf20Sopenharmony_ci "device driver, reason=%s\n", "01"); 16648c2ecf20Sopenharmony_ci return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); 16658c2ecf20Sopenharmony_ci } 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci /* use original DE */ 16688c2ecf20Sopenharmony_ci DE_data = erp->data; 16698c2ecf20Sopenharmony_ci oldccw = cqr->cpaddr; 16708c2ecf20Sopenharmony_ci if (oldccw->cmd_code == DASD_ECKD_CCW_PFX) { 16718c2ecf20Sopenharmony_ci PFX_data = cqr->data; 16728c2ecf20Sopenharmony_ci memcpy(DE_data, &PFX_data->define_extent, 16738c2ecf20Sopenharmony_ci sizeof(struct DE_eckd_data)); 16748c2ecf20Sopenharmony_ci } else 16758c2ecf20Sopenharmony_ci memcpy(DE_data, cqr->data, sizeof(struct DE_eckd_data)); 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ci /* create LO */ 16788c2ecf20Sopenharmony_ci LO_data = erp->data + sizeof(struct DE_eckd_data); 16798c2ecf20Sopenharmony_ci 16808c2ecf20Sopenharmony_ci if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { 16818c2ecf20Sopenharmony_ci /* should not */ 16828c2ecf20Sopenharmony_ci return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); 16838c2ecf20Sopenharmony_ci } 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci if ((sense[7] & 0x3F) == 0x01) { 16868c2ecf20Sopenharmony_ci /* operation code is WRITE DATA -> data area orientation */ 16878c2ecf20Sopenharmony_ci LO_data[0] = 0x81; 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci } else if ((sense[7] & 0x3F) == 0x03) { 16908c2ecf20Sopenharmony_ci /* operation code is FORMAT WRITE -> index orientation */ 16918c2ecf20Sopenharmony_ci LO_data[0] = 0xC3; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci } else { 16948c2ecf20Sopenharmony_ci LO_data[0] = sense[7]; /* operation */ 16958c2ecf20Sopenharmony_ci } 16968c2ecf20Sopenharmony_ci 16978c2ecf20Sopenharmony_ci LO_data[1] = sense[8]; /* auxiliary */ 16988c2ecf20Sopenharmony_ci LO_data[2] = sense[9]; 16998c2ecf20Sopenharmony_ci LO_data[3] = sense[3]; /* count */ 17008c2ecf20Sopenharmony_ci LO_data[4] = sense[29]; /* seek_addr.cyl */ 17018c2ecf20Sopenharmony_ci LO_data[5] = sense[30]; /* seek_addr.cyl 2nd byte */ 17028c2ecf20Sopenharmony_ci LO_data[7] = sense[31]; /* seek_addr.head 2nd byte */ 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci memcpy(&(LO_data[8]), &(sense[11]), 8); 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ci /* create DE ccw */ 17078c2ecf20Sopenharmony_ci ccw = erp->cpaddr; 17088c2ecf20Sopenharmony_ci memset(ccw, 0, sizeof(struct ccw1)); 17098c2ecf20Sopenharmony_ci ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT; 17108c2ecf20Sopenharmony_ci ccw->flags = CCW_FLAG_CC; 17118c2ecf20Sopenharmony_ci ccw->count = 16; 17128c2ecf20Sopenharmony_ci ccw->cda = (__u32)(addr_t) DE_data; 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci /* create LO ccw */ 17158c2ecf20Sopenharmony_ci ccw++; 17168c2ecf20Sopenharmony_ci memset(ccw, 0, sizeof(struct ccw1)); 17178c2ecf20Sopenharmony_ci ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD; 17188c2ecf20Sopenharmony_ci ccw->flags = CCW_FLAG_CC; 17198c2ecf20Sopenharmony_ci ccw->count = 16; 17208c2ecf20Sopenharmony_ci ccw->cda = (__u32)(addr_t) LO_data; 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci /* TIC to the failed ccw */ 17238c2ecf20Sopenharmony_ci ccw++; 17248c2ecf20Sopenharmony_ci ccw->cmd_code = CCW_CMD_TIC; 17258c2ecf20Sopenharmony_ci ccw->cda = cpa; 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci /* fill erp related fields */ 17288c2ecf20Sopenharmony_ci erp->flags = default_erp->flags; 17298c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_action_1B_32; 17308c2ecf20Sopenharmony_ci erp->refers = default_erp->refers; 17318c2ecf20Sopenharmony_ci erp->startdev = device; 17328c2ecf20Sopenharmony_ci erp->memdev = device; 17338c2ecf20Sopenharmony_ci erp->magic = default_erp->magic; 17348c2ecf20Sopenharmony_ci erp->expires = default_erp->expires; 17358c2ecf20Sopenharmony_ci erp->retries = 256; 17368c2ecf20Sopenharmony_ci erp->buildclk = get_tod_clock(); 17378c2ecf20Sopenharmony_ci erp->status = DASD_CQR_FILLED; 17388c2ecf20Sopenharmony_ci 17398c2ecf20Sopenharmony_ci /* remove the default erp */ 17408c2ecf20Sopenharmony_ci dasd_free_erp_request(default_erp, device); 17418c2ecf20Sopenharmony_ci 17428c2ecf20Sopenharmony_ci return erp; 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_action_1B_32 */ 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci/* 17478c2ecf20Sopenharmony_ci * DASD_3990_UPDATE_1B 17488c2ecf20Sopenharmony_ci * 17498c2ecf20Sopenharmony_ci * DESCRIPTION 17508c2ecf20Sopenharmony_ci * Handles the update to the 32 byte 'Action 1B' of Single Program 17518c2ecf20Sopenharmony_ci * Action Codes in case the first action was not successful. 17528c2ecf20Sopenharmony_ci * The already created 'previous_erp' is the currently not successful 17538c2ecf20Sopenharmony_ci * ERP. 17548c2ecf20Sopenharmony_ci * 17558c2ecf20Sopenharmony_ci * PARAMETER 17568c2ecf20Sopenharmony_ci * previous_erp already created previous erp. 17578c2ecf20Sopenharmony_ci * sense current sense data 17588c2ecf20Sopenharmony_ci * RETURN VALUES 17598c2ecf20Sopenharmony_ci * erp modified erp 17608c2ecf20Sopenharmony_ci */ 17618c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 17628c2ecf20Sopenharmony_cidasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) 17638c2ecf20Sopenharmony_ci{ 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci struct dasd_device *device = previous_erp->startdev; 17668c2ecf20Sopenharmony_ci __u32 cpa = 0; 17678c2ecf20Sopenharmony_ci struct dasd_ccw_req *cqr; 17688c2ecf20Sopenharmony_ci struct dasd_ccw_req *erp; 17698c2ecf20Sopenharmony_ci char *LO_data; /* struct LO_eckd_data */ 17708c2ecf20Sopenharmony_ci struct ccw1 *ccw; 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 17738c2ecf20Sopenharmony_ci "Write not finished because of unexpected condition" 17748c2ecf20Sopenharmony_ci " - follow on"); 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci /* determine the original cqr */ 17778c2ecf20Sopenharmony_ci cqr = previous_erp; 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ci while (cqr->refers != NULL) { 17808c2ecf20Sopenharmony_ci cqr = cqr->refers; 17818c2ecf20Sopenharmony_ci } 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_ci if (scsw_is_tm(&cqr->irb.scsw)) { 17848c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 17858c2ecf20Sopenharmony_ci "32 bit sense, action 1B, update," 17868c2ecf20Sopenharmony_ci " in transport mode - just retry"); 17878c2ecf20Sopenharmony_ci return previous_erp; 17888c2ecf20Sopenharmony_ci } 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_ci /* for imprecise ending just do default erp */ 17918c2ecf20Sopenharmony_ci if (sense[1] & 0x01) { 17928c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 17938c2ecf20Sopenharmony_ci "Imprecise ending is set - just retry"); 17948c2ecf20Sopenharmony_ci 17958c2ecf20Sopenharmony_ci previous_erp->status = DASD_CQR_FILLED; 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci return previous_erp; 17988c2ecf20Sopenharmony_ci } 17998c2ecf20Sopenharmony_ci 18008c2ecf20Sopenharmony_ci /* determine the address of the CCW to be restarted */ 18018c2ecf20Sopenharmony_ci /* Imprecise ending is not set -> addr from IRB-SCSW */ 18028c2ecf20Sopenharmony_ci cpa = previous_erp->irb.scsw.cmd.cpa; 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci if (cpa == 0) { 18058c2ecf20Sopenharmony_ci /* internal error 02 - 18068c2ecf20Sopenharmony_ci Unable to determine address of the CCW to be restarted */ 18078c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, "An error occurred in the DASD " 18088c2ecf20Sopenharmony_ci "device driver, reason=%s\n", "02"); 18098c2ecf20Sopenharmony_ci 18108c2ecf20Sopenharmony_ci previous_erp->status = DASD_CQR_FAILED; 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci return previous_erp; 18138c2ecf20Sopenharmony_ci } 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci erp = previous_erp; 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci /* update the LO with the new returned sense data */ 18188c2ecf20Sopenharmony_ci LO_data = erp->data + sizeof(struct DE_eckd_data); 18198c2ecf20Sopenharmony_ci 18208c2ecf20Sopenharmony_ci if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { 18218c2ecf20Sopenharmony_ci /* should not happen */ 18228c2ecf20Sopenharmony_ci previous_erp->status = DASD_CQR_FAILED; 18238c2ecf20Sopenharmony_ci 18248c2ecf20Sopenharmony_ci return previous_erp; 18258c2ecf20Sopenharmony_ci } 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_ci if ((sense[7] & 0x3F) == 0x01) { 18288c2ecf20Sopenharmony_ci /* operation code is WRITE DATA -> data area orientation */ 18298c2ecf20Sopenharmony_ci LO_data[0] = 0x81; 18308c2ecf20Sopenharmony_ci 18318c2ecf20Sopenharmony_ci } else if ((sense[7] & 0x3F) == 0x03) { 18328c2ecf20Sopenharmony_ci /* operation code is FORMAT WRITE -> index orientation */ 18338c2ecf20Sopenharmony_ci LO_data[0] = 0xC3; 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci } else { 18368c2ecf20Sopenharmony_ci LO_data[0] = sense[7]; /* operation */ 18378c2ecf20Sopenharmony_ci } 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci LO_data[1] = sense[8]; /* auxiliary */ 18408c2ecf20Sopenharmony_ci LO_data[2] = sense[9]; 18418c2ecf20Sopenharmony_ci LO_data[3] = sense[3]; /* count */ 18428c2ecf20Sopenharmony_ci LO_data[4] = sense[29]; /* seek_addr.cyl */ 18438c2ecf20Sopenharmony_ci LO_data[5] = sense[30]; /* seek_addr.cyl 2nd byte */ 18448c2ecf20Sopenharmony_ci LO_data[7] = sense[31]; /* seek_addr.head 2nd byte */ 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci memcpy(&(LO_data[8]), &(sense[11]), 8); 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ci /* TIC to the failed ccw */ 18498c2ecf20Sopenharmony_ci ccw = erp->cpaddr; /* addr of DE ccw */ 18508c2ecf20Sopenharmony_ci ccw++; /* addr of LE ccw */ 18518c2ecf20Sopenharmony_ci ccw++; /* addr of TIC ccw */ 18528c2ecf20Sopenharmony_ci ccw->cda = cpa; 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci erp->status = DASD_CQR_FILLED; 18558c2ecf20Sopenharmony_ci 18568c2ecf20Sopenharmony_ci return erp; 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci} /* end dasd_3990_update_1B */ 18598c2ecf20Sopenharmony_ci 18608c2ecf20Sopenharmony_ci/* 18618c2ecf20Sopenharmony_ci * DASD_3990_ERP_COMPOUND_RETRY 18628c2ecf20Sopenharmony_ci * 18638c2ecf20Sopenharmony_ci * DESCRIPTION 18648c2ecf20Sopenharmony_ci * Handles the compound ERP action retry code. 18658c2ecf20Sopenharmony_ci * NOTE: At least one retry is done even if zero is specified 18668c2ecf20Sopenharmony_ci * by the sense data. This makes enqueueing of the request 18678c2ecf20Sopenharmony_ci * easier. 18688c2ecf20Sopenharmony_ci * 18698c2ecf20Sopenharmony_ci * PARAMETER 18708c2ecf20Sopenharmony_ci * sense sense data of the actual error 18718c2ecf20Sopenharmony_ci * erp pointer to the currently created ERP 18728c2ecf20Sopenharmony_ci * 18738c2ecf20Sopenharmony_ci * RETURN VALUES 18748c2ecf20Sopenharmony_ci * erp modified ERP pointer 18758c2ecf20Sopenharmony_ci * 18768c2ecf20Sopenharmony_ci */ 18778c2ecf20Sopenharmony_cistatic void 18788c2ecf20Sopenharmony_cidasd_3990_erp_compound_retry(struct dasd_ccw_req * erp, char *sense) 18798c2ecf20Sopenharmony_ci{ 18808c2ecf20Sopenharmony_ci 18818c2ecf20Sopenharmony_ci switch (sense[25] & 0x03) { 18828c2ecf20Sopenharmony_ci case 0x00: /* no not retry */ 18838c2ecf20Sopenharmony_ci erp->retries = 1; 18848c2ecf20Sopenharmony_ci break; 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci case 0x01: /* retry 2 times */ 18878c2ecf20Sopenharmony_ci erp->retries = 2; 18888c2ecf20Sopenharmony_ci break; 18898c2ecf20Sopenharmony_ci 18908c2ecf20Sopenharmony_ci case 0x02: /* retry 10 times */ 18918c2ecf20Sopenharmony_ci erp->retries = 10; 18928c2ecf20Sopenharmony_ci break; 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ci case 0x03: /* retry 256 times */ 18958c2ecf20Sopenharmony_ci erp->retries = 256; 18968c2ecf20Sopenharmony_ci break; 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci default: 18998c2ecf20Sopenharmony_ci BUG(); 19008c2ecf20Sopenharmony_ci } 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_compound_retry; 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_compound_retry */ 19058c2ecf20Sopenharmony_ci 19068c2ecf20Sopenharmony_ci/* 19078c2ecf20Sopenharmony_ci * DASD_3990_ERP_COMPOUND_PATH 19088c2ecf20Sopenharmony_ci * 19098c2ecf20Sopenharmony_ci * DESCRIPTION 19108c2ecf20Sopenharmony_ci * Handles the compound ERP action for retry on alternate 19118c2ecf20Sopenharmony_ci * channel path. 19128c2ecf20Sopenharmony_ci * 19138c2ecf20Sopenharmony_ci * PARAMETER 19148c2ecf20Sopenharmony_ci * sense sense data of the actual error 19158c2ecf20Sopenharmony_ci * erp pointer to the currently created ERP 19168c2ecf20Sopenharmony_ci * 19178c2ecf20Sopenharmony_ci * RETURN VALUES 19188c2ecf20Sopenharmony_ci * erp modified ERP pointer 19198c2ecf20Sopenharmony_ci * 19208c2ecf20Sopenharmony_ci */ 19218c2ecf20Sopenharmony_cistatic void 19228c2ecf20Sopenharmony_cidasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense) 19238c2ecf20Sopenharmony_ci{ 19248c2ecf20Sopenharmony_ci if (sense[25] & DASD_SENSE_BIT_3) { 19258c2ecf20Sopenharmony_ci dasd_3990_erp_alternate_path(erp); 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci if (erp->status == DASD_CQR_FAILED && 19288c2ecf20Sopenharmony_ci !test_bit(DASD_CQR_VERIFY_PATH, &erp->flags)) { 19298c2ecf20Sopenharmony_ci /* reset the lpm and the status to be able to 19308c2ecf20Sopenharmony_ci * try further actions. */ 19318c2ecf20Sopenharmony_ci erp->lpm = dasd_path_get_opm(erp->startdev); 19328c2ecf20Sopenharmony_ci erp->status = DASD_CQR_NEED_ERP; 19338c2ecf20Sopenharmony_ci } 19348c2ecf20Sopenharmony_ci } 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_compound_path; 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_compound_path */ 19398c2ecf20Sopenharmony_ci 19408c2ecf20Sopenharmony_ci/* 19418c2ecf20Sopenharmony_ci * DASD_3990_ERP_COMPOUND_CODE 19428c2ecf20Sopenharmony_ci * 19438c2ecf20Sopenharmony_ci * DESCRIPTION 19448c2ecf20Sopenharmony_ci * Handles the compound ERP action for retry code. 19458c2ecf20Sopenharmony_ci * 19468c2ecf20Sopenharmony_ci * PARAMETER 19478c2ecf20Sopenharmony_ci * sense sense data of the actual error 19488c2ecf20Sopenharmony_ci * erp pointer to the currently created ERP 19498c2ecf20Sopenharmony_ci * 19508c2ecf20Sopenharmony_ci * RETURN VALUES 19518c2ecf20Sopenharmony_ci * erp NEW ERP pointer 19528c2ecf20Sopenharmony_ci * 19538c2ecf20Sopenharmony_ci */ 19548c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 19558c2ecf20Sopenharmony_cidasd_3990_erp_compound_code(struct dasd_ccw_req * erp, char *sense) 19568c2ecf20Sopenharmony_ci{ 19578c2ecf20Sopenharmony_ci 19588c2ecf20Sopenharmony_ci if (sense[25] & DASD_SENSE_BIT_2) { 19598c2ecf20Sopenharmony_ci 19608c2ecf20Sopenharmony_ci switch (sense[28]) { 19618c2ecf20Sopenharmony_ci case 0x17: 19628c2ecf20Sopenharmony_ci /* issue a Diagnostic Control command with an 19638c2ecf20Sopenharmony_ci * Inhibit Write subcommand and controller modifier */ 19648c2ecf20Sopenharmony_ci erp = dasd_3990_erp_DCTL(erp, 0x20); 19658c2ecf20Sopenharmony_ci break; 19668c2ecf20Sopenharmony_ci 19678c2ecf20Sopenharmony_ci case 0x25: 19688c2ecf20Sopenharmony_ci /* wait for 5 seconds and retry again */ 19698c2ecf20Sopenharmony_ci erp->retries = 1; 19708c2ecf20Sopenharmony_ci 19718c2ecf20Sopenharmony_ci dasd_3990_erp_block_queue (erp, 5*HZ); 19728c2ecf20Sopenharmony_ci break; 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci default: 19758c2ecf20Sopenharmony_ci /* should not happen - continue */ 19768c2ecf20Sopenharmony_ci break; 19778c2ecf20Sopenharmony_ci } 19788c2ecf20Sopenharmony_ci } 19798c2ecf20Sopenharmony_ci 19808c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_compound_code; 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci return erp; 19838c2ecf20Sopenharmony_ci 19848c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_compound_code */ 19858c2ecf20Sopenharmony_ci 19868c2ecf20Sopenharmony_ci/* 19878c2ecf20Sopenharmony_ci * DASD_3990_ERP_COMPOUND_CONFIG 19888c2ecf20Sopenharmony_ci * 19898c2ecf20Sopenharmony_ci * DESCRIPTION 19908c2ecf20Sopenharmony_ci * Handles the compound ERP action for configuration 19918c2ecf20Sopenharmony_ci * dependent error. 19928c2ecf20Sopenharmony_ci * Note: duplex handling is not implemented (yet). 19938c2ecf20Sopenharmony_ci * 19948c2ecf20Sopenharmony_ci * PARAMETER 19958c2ecf20Sopenharmony_ci * sense sense data of the actual error 19968c2ecf20Sopenharmony_ci * erp pointer to the currently created ERP 19978c2ecf20Sopenharmony_ci * 19988c2ecf20Sopenharmony_ci * RETURN VALUES 19998c2ecf20Sopenharmony_ci * erp modified ERP pointer 20008c2ecf20Sopenharmony_ci * 20018c2ecf20Sopenharmony_ci */ 20028c2ecf20Sopenharmony_cistatic void 20038c2ecf20Sopenharmony_cidasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense) 20048c2ecf20Sopenharmony_ci{ 20058c2ecf20Sopenharmony_ci 20068c2ecf20Sopenharmony_ci if ((sense[25] & DASD_SENSE_BIT_1) && (sense[26] & DASD_SENSE_BIT_2)) { 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci /* set to suspended duplex state then restart 20098c2ecf20Sopenharmony_ci internal error 05 - Set device to suspended duplex state 20108c2ecf20Sopenharmony_ci should be done */ 20118c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 20128c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 20138c2ecf20Sopenharmony_ci "An error occurred in the DASD device driver, " 20148c2ecf20Sopenharmony_ci "reason=%s\n", "05"); 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci } 20178c2ecf20Sopenharmony_ci 20188c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_compound_config; 20198c2ecf20Sopenharmony_ci 20208c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_compound_config */ 20218c2ecf20Sopenharmony_ci 20228c2ecf20Sopenharmony_ci/* 20238c2ecf20Sopenharmony_ci * DASD_3990_ERP_COMPOUND 20248c2ecf20Sopenharmony_ci * 20258c2ecf20Sopenharmony_ci * DESCRIPTION 20268c2ecf20Sopenharmony_ci * Does the further compound program action if 20278c2ecf20Sopenharmony_ci * compound retry was not successful. 20288c2ecf20Sopenharmony_ci * 20298c2ecf20Sopenharmony_ci * PARAMETER 20308c2ecf20Sopenharmony_ci * sense sense data of the actual error 20318c2ecf20Sopenharmony_ci * erp pointer to the current (failed) ERP 20328c2ecf20Sopenharmony_ci * 20338c2ecf20Sopenharmony_ci * RETURN VALUES 20348c2ecf20Sopenharmony_ci * erp (additional) ERP pointer 20358c2ecf20Sopenharmony_ci * 20368c2ecf20Sopenharmony_ci */ 20378c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 20388c2ecf20Sopenharmony_cidasd_3990_erp_compound(struct dasd_ccw_req * erp, char *sense) 20398c2ecf20Sopenharmony_ci{ 20408c2ecf20Sopenharmony_ci 20418c2ecf20Sopenharmony_ci if ((erp->function == dasd_3990_erp_compound_retry) && 20428c2ecf20Sopenharmony_ci (erp->status == DASD_CQR_NEED_ERP)) { 20438c2ecf20Sopenharmony_ci 20448c2ecf20Sopenharmony_ci dasd_3990_erp_compound_path(erp, sense); 20458c2ecf20Sopenharmony_ci } 20468c2ecf20Sopenharmony_ci 20478c2ecf20Sopenharmony_ci if ((erp->function == dasd_3990_erp_compound_path) && 20488c2ecf20Sopenharmony_ci (erp->status == DASD_CQR_NEED_ERP)) { 20498c2ecf20Sopenharmony_ci 20508c2ecf20Sopenharmony_ci erp = dasd_3990_erp_compound_code(erp, sense); 20518c2ecf20Sopenharmony_ci } 20528c2ecf20Sopenharmony_ci 20538c2ecf20Sopenharmony_ci if ((erp->function == dasd_3990_erp_compound_code) && 20548c2ecf20Sopenharmony_ci (erp->status == DASD_CQR_NEED_ERP)) { 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_ci dasd_3990_erp_compound_config(erp, sense); 20578c2ecf20Sopenharmony_ci } 20588c2ecf20Sopenharmony_ci 20598c2ecf20Sopenharmony_ci /* if no compound action ERP specified, the request failed */ 20608c2ecf20Sopenharmony_ci if (erp->status == DASD_CQR_NEED_ERP) 20618c2ecf20Sopenharmony_ci erp->status = DASD_CQR_FAILED; 20628c2ecf20Sopenharmony_ci 20638c2ecf20Sopenharmony_ci return erp; 20648c2ecf20Sopenharmony_ci 20658c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_compound */ 20668c2ecf20Sopenharmony_ci 20678c2ecf20Sopenharmony_ci/* 20688c2ecf20Sopenharmony_ci *DASD_3990_ERP_HANDLE_SIM 20698c2ecf20Sopenharmony_ci * 20708c2ecf20Sopenharmony_ci *DESCRIPTION 20718c2ecf20Sopenharmony_ci * inspects the SIM SENSE data and starts an appropriate action 20728c2ecf20Sopenharmony_ci * 20738c2ecf20Sopenharmony_ci * PARAMETER 20748c2ecf20Sopenharmony_ci * sense sense data of the actual error 20758c2ecf20Sopenharmony_ci * 20768c2ecf20Sopenharmony_ci * RETURN VALUES 20778c2ecf20Sopenharmony_ci * none 20788c2ecf20Sopenharmony_ci */ 20798c2ecf20Sopenharmony_civoid 20808c2ecf20Sopenharmony_cidasd_3990_erp_handle_sim(struct dasd_device *device, char *sense) 20818c2ecf20Sopenharmony_ci{ 20828c2ecf20Sopenharmony_ci /* print message according to log or message to operator mode */ 20838c2ecf20Sopenharmony_ci if ((sense[24] & DASD_SIM_MSG_TO_OP) || (sense[1] & 0x10)) { 20848c2ecf20Sopenharmony_ci /* print SIM SRC from RefCode */ 20858c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, "SIM - SRC: " 20868c2ecf20Sopenharmony_ci "%02x%02x%02x%02x\n", sense[22], 20878c2ecf20Sopenharmony_ci sense[23], sense[11], sense[12]); 20888c2ecf20Sopenharmony_ci } else if (sense[24] & DASD_SIM_LOG) { 20898c2ecf20Sopenharmony_ci /* print SIM SRC Refcode */ 20908c2ecf20Sopenharmony_ci dev_warn(&device->cdev->dev, "log SIM - SRC: " 20918c2ecf20Sopenharmony_ci "%02x%02x%02x%02x\n", sense[22], 20928c2ecf20Sopenharmony_ci sense[23], sense[11], sense[12]); 20938c2ecf20Sopenharmony_ci } 20948c2ecf20Sopenharmony_ci} 20958c2ecf20Sopenharmony_ci 20968c2ecf20Sopenharmony_ci/* 20978c2ecf20Sopenharmony_ci * DASD_3990_ERP_INSPECT_32 20988c2ecf20Sopenharmony_ci * 20998c2ecf20Sopenharmony_ci * DESCRIPTION 21008c2ecf20Sopenharmony_ci * Does a detailed inspection of the 32 byte sense data 21018c2ecf20Sopenharmony_ci * and sets up a related error recovery action. 21028c2ecf20Sopenharmony_ci * 21038c2ecf20Sopenharmony_ci * PARAMETER 21048c2ecf20Sopenharmony_ci * sense sense data of the actual error 21058c2ecf20Sopenharmony_ci * erp pointer to the currently created default ERP 21068c2ecf20Sopenharmony_ci * 21078c2ecf20Sopenharmony_ci * RETURN VALUES 21088c2ecf20Sopenharmony_ci * erp_filled pointer to the ERP 21098c2ecf20Sopenharmony_ci * 21108c2ecf20Sopenharmony_ci */ 21118c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 21128c2ecf20Sopenharmony_cidasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) 21138c2ecf20Sopenharmony_ci{ 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 21168c2ecf20Sopenharmony_ci 21178c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_inspect_32; 21188c2ecf20Sopenharmony_ci 21198c2ecf20Sopenharmony_ci /* check for SIM sense data */ 21208c2ecf20Sopenharmony_ci if ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE) 21218c2ecf20Sopenharmony_ci dasd_3990_erp_handle_sim(device, sense); 21228c2ecf20Sopenharmony_ci 21238c2ecf20Sopenharmony_ci if (sense[25] & DASD_SENSE_BIT_0) { 21248c2ecf20Sopenharmony_ci 21258c2ecf20Sopenharmony_ci /* compound program action codes (byte25 bit 0 == '1') */ 21268c2ecf20Sopenharmony_ci dasd_3990_erp_compound_retry(erp, sense); 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_ci } else { 21298c2ecf20Sopenharmony_ci 21308c2ecf20Sopenharmony_ci /* single program action codes (byte25 bit 0 == '0') */ 21318c2ecf20Sopenharmony_ci switch (sense[25]) { 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci case 0x00: /* success - use default ERP for retries */ 21348c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_DEBUG, device, "%s", 21358c2ecf20Sopenharmony_ci "ERP called for successful request" 21368c2ecf20Sopenharmony_ci " - just retry"); 21378c2ecf20Sopenharmony_ci break; 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci case 0x01: /* fatal error */ 21408c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 21418c2ecf20Sopenharmony_ci "ERP failed for the DASD\n"); 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_ci erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); 21448c2ecf20Sopenharmony_ci break; 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_ci case 0x02: /* intervention required */ 21478c2ecf20Sopenharmony_ci case 0x03: /* intervention required during dual copy */ 21488c2ecf20Sopenharmony_ci erp = dasd_3990_erp_int_req(erp); 21498c2ecf20Sopenharmony_ci break; 21508c2ecf20Sopenharmony_ci 21518c2ecf20Sopenharmony_ci case 0x0F: /* length mismatch during update write command 21528c2ecf20Sopenharmony_ci internal error 08 - update write command error*/ 21538c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, "An error occurred in the " 21548c2ecf20Sopenharmony_ci "DASD device driver, reason=%s\n", "08"); 21558c2ecf20Sopenharmony_ci 21568c2ecf20Sopenharmony_ci erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); 21578c2ecf20Sopenharmony_ci break; 21588c2ecf20Sopenharmony_ci 21598c2ecf20Sopenharmony_ci case 0x10: /* logging required for other channel program */ 21608c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_10_32(erp, sense); 21618c2ecf20Sopenharmony_ci break; 21628c2ecf20Sopenharmony_ci 21638c2ecf20Sopenharmony_ci case 0x15: /* next track outside defined extend 21648c2ecf20Sopenharmony_ci internal error 07 - The next track is not 21658c2ecf20Sopenharmony_ci within the defined storage extent */ 21668c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 21678c2ecf20Sopenharmony_ci "An error occurred in the DASD device driver, " 21688c2ecf20Sopenharmony_ci "reason=%s\n", "07"); 21698c2ecf20Sopenharmony_ci 21708c2ecf20Sopenharmony_ci erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); 21718c2ecf20Sopenharmony_ci break; 21728c2ecf20Sopenharmony_ci 21738c2ecf20Sopenharmony_ci case 0x1B: /* unexpected condition during write */ 21748c2ecf20Sopenharmony_ci 21758c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_1B_32(erp, sense); 21768c2ecf20Sopenharmony_ci break; 21778c2ecf20Sopenharmony_ci 21788c2ecf20Sopenharmony_ci case 0x1C: /* invalid data */ 21798c2ecf20Sopenharmony_ci dev_emerg(&device->cdev->dev, 21808c2ecf20Sopenharmony_ci "Data recovered during retry with PCI " 21818c2ecf20Sopenharmony_ci "fetch mode active\n"); 21828c2ecf20Sopenharmony_ci 21838c2ecf20Sopenharmony_ci /* not possible to handle this situation in Linux */ 21848c2ecf20Sopenharmony_ci panic 21858c2ecf20Sopenharmony_ci ("Invalid data - No way to inform application " 21868c2ecf20Sopenharmony_ci "about the possibly incorrect data"); 21878c2ecf20Sopenharmony_ci break; 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_ci case 0x1D: /* state-change pending */ 21908c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 21918c2ecf20Sopenharmony_ci "A State change pending condition exists " 21928c2ecf20Sopenharmony_ci "for the subsystem or device"); 21938c2ecf20Sopenharmony_ci 21948c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_4(erp, sense); 21958c2ecf20Sopenharmony_ci break; 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci case 0x1E: /* busy */ 21988c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 21998c2ecf20Sopenharmony_ci "Busy condition exists " 22008c2ecf20Sopenharmony_ci "for the subsystem or device"); 22018c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_4(erp, sense); 22028c2ecf20Sopenharmony_ci break; 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_ci default: /* all others errors - default erp */ 22058c2ecf20Sopenharmony_ci break; 22068c2ecf20Sopenharmony_ci } 22078c2ecf20Sopenharmony_ci } 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci return erp; 22108c2ecf20Sopenharmony_ci 22118c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_inspect_32 */ 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_cistatic void dasd_3990_erp_disable_path(struct dasd_device *device, __u8 lpum) 22148c2ecf20Sopenharmony_ci{ 22158c2ecf20Sopenharmony_ci int pos = pathmask_to_pos(lpum); 22168c2ecf20Sopenharmony_ci 22178c2ecf20Sopenharmony_ci if (!(device->features & DASD_FEATURE_PATH_AUTODISABLE)) { 22188c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 22198c2ecf20Sopenharmony_ci "Path %x.%02x (pathmask %02x) is operational despite excessive IFCCs\n", 22208c2ecf20Sopenharmony_ci device->path[pos].cssid, device->path[pos].chpid, lpum); 22218c2ecf20Sopenharmony_ci goto out; 22228c2ecf20Sopenharmony_ci } 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci /* no remaining path, cannot disable */ 22258c2ecf20Sopenharmony_ci if (!(dasd_path_get_opm(device) & ~lpum)) { 22268c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 22278c2ecf20Sopenharmony_ci "Last path %x.%02x (pathmask %02x) is operational despite excessive IFCCs\n", 22288c2ecf20Sopenharmony_ci device->path[pos].cssid, device->path[pos].chpid, lpum); 22298c2ecf20Sopenharmony_ci goto out; 22308c2ecf20Sopenharmony_ci } 22318c2ecf20Sopenharmony_ci 22328c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 22338c2ecf20Sopenharmony_ci "Path %x.%02x (pathmask %02x) is disabled - IFCC threshold exceeded\n", 22348c2ecf20Sopenharmony_ci device->path[pos].cssid, device->path[pos].chpid, lpum); 22358c2ecf20Sopenharmony_ci dasd_path_remove_opm(device, lpum); 22368c2ecf20Sopenharmony_ci dasd_path_add_ifccpm(device, lpum); 22378c2ecf20Sopenharmony_ci 22388c2ecf20Sopenharmony_ciout: 22398c2ecf20Sopenharmony_ci device->path[pos].errorclk = 0; 22408c2ecf20Sopenharmony_ci atomic_set(&device->path[pos].error_count, 0); 22418c2ecf20Sopenharmony_ci} 22428c2ecf20Sopenharmony_ci 22438c2ecf20Sopenharmony_cistatic void dasd_3990_erp_account_error(struct dasd_ccw_req *erp) 22448c2ecf20Sopenharmony_ci{ 22458c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 22468c2ecf20Sopenharmony_ci __u8 lpum = erp->refers->irb.esw.esw1.lpum; 22478c2ecf20Sopenharmony_ci int pos = pathmask_to_pos(lpum); 22488c2ecf20Sopenharmony_ci unsigned long clk; 22498c2ecf20Sopenharmony_ci 22508c2ecf20Sopenharmony_ci if (!device->path_thrhld) 22518c2ecf20Sopenharmony_ci return; 22528c2ecf20Sopenharmony_ci 22538c2ecf20Sopenharmony_ci clk = get_tod_clock(); 22548c2ecf20Sopenharmony_ci /* 22558c2ecf20Sopenharmony_ci * check if the last error is longer ago than the timeout, 22568c2ecf20Sopenharmony_ci * if so reset error state 22578c2ecf20Sopenharmony_ci */ 22588c2ecf20Sopenharmony_ci if ((tod_to_ns(clk - device->path[pos].errorclk) / NSEC_PER_SEC) 22598c2ecf20Sopenharmony_ci >= device->path_interval) { 22608c2ecf20Sopenharmony_ci atomic_set(&device->path[pos].error_count, 0); 22618c2ecf20Sopenharmony_ci device->path[pos].errorclk = 0; 22628c2ecf20Sopenharmony_ci } 22638c2ecf20Sopenharmony_ci atomic_inc(&device->path[pos].error_count); 22648c2ecf20Sopenharmony_ci device->path[pos].errorclk = clk; 22658c2ecf20Sopenharmony_ci /* threshold exceeded disable path if possible */ 22668c2ecf20Sopenharmony_ci if (atomic_read(&device->path[pos].error_count) >= 22678c2ecf20Sopenharmony_ci device->path_thrhld) 22688c2ecf20Sopenharmony_ci dasd_3990_erp_disable_path(device, lpum); 22698c2ecf20Sopenharmony_ci} 22708c2ecf20Sopenharmony_ci 22718c2ecf20Sopenharmony_ci/* 22728c2ecf20Sopenharmony_ci ***************************************************************************** 22738c2ecf20Sopenharmony_ci * main ERP control functions (24 and 32 byte sense) 22748c2ecf20Sopenharmony_ci ***************************************************************************** 22758c2ecf20Sopenharmony_ci */ 22768c2ecf20Sopenharmony_ci 22778c2ecf20Sopenharmony_ci/* 22788c2ecf20Sopenharmony_ci * DASD_3990_ERP_CONTROL_CHECK 22798c2ecf20Sopenharmony_ci * 22808c2ecf20Sopenharmony_ci * DESCRIPTION 22818c2ecf20Sopenharmony_ci * Does a generic inspection if a control check occurred and sets up 22828c2ecf20Sopenharmony_ci * the related error recovery procedure 22838c2ecf20Sopenharmony_ci * 22848c2ecf20Sopenharmony_ci * PARAMETER 22858c2ecf20Sopenharmony_ci * erp pointer to the currently created default ERP 22868c2ecf20Sopenharmony_ci * 22878c2ecf20Sopenharmony_ci * RETURN VALUES 22888c2ecf20Sopenharmony_ci * erp_filled pointer to the erp 22898c2ecf20Sopenharmony_ci */ 22908c2ecf20Sopenharmony_ci 22918c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 22928c2ecf20Sopenharmony_cidasd_3990_erp_control_check(struct dasd_ccw_req *erp) 22938c2ecf20Sopenharmony_ci{ 22948c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 22958c2ecf20Sopenharmony_ci 22968c2ecf20Sopenharmony_ci if (scsw_cstat(&erp->refers->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK 22978c2ecf20Sopenharmony_ci | SCHN_STAT_CHN_CTRL_CHK)) { 22988c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, "%s", 22998c2ecf20Sopenharmony_ci "channel or interface control check"); 23008c2ecf20Sopenharmony_ci dasd_3990_erp_account_error(erp); 23018c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_4(erp, NULL); 23028c2ecf20Sopenharmony_ci } 23038c2ecf20Sopenharmony_ci return erp; 23048c2ecf20Sopenharmony_ci} 23058c2ecf20Sopenharmony_ci 23068c2ecf20Sopenharmony_ci/* 23078c2ecf20Sopenharmony_ci * DASD_3990_ERP_INSPECT 23088c2ecf20Sopenharmony_ci * 23098c2ecf20Sopenharmony_ci * DESCRIPTION 23108c2ecf20Sopenharmony_ci * Does a detailed inspection for sense data by calling either 23118c2ecf20Sopenharmony_ci * the 24-byte or the 32-byte inspection routine. 23128c2ecf20Sopenharmony_ci * 23138c2ecf20Sopenharmony_ci * PARAMETER 23148c2ecf20Sopenharmony_ci * erp pointer to the currently created default ERP 23158c2ecf20Sopenharmony_ci * RETURN VALUES 23168c2ecf20Sopenharmony_ci * erp_new contens was possibly modified 23178c2ecf20Sopenharmony_ci */ 23188c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 23198c2ecf20Sopenharmony_cidasd_3990_erp_inspect(struct dasd_ccw_req *erp) 23208c2ecf20Sopenharmony_ci{ 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci struct dasd_ccw_req *erp_new = NULL; 23238c2ecf20Sopenharmony_ci char *sense; 23248c2ecf20Sopenharmony_ci 23258c2ecf20Sopenharmony_ci /* if this problem occurred on an alias retry on base */ 23268c2ecf20Sopenharmony_ci erp_new = dasd_3990_erp_inspect_alias(erp); 23278c2ecf20Sopenharmony_ci if (erp_new) 23288c2ecf20Sopenharmony_ci return erp_new; 23298c2ecf20Sopenharmony_ci 23308c2ecf20Sopenharmony_ci /* sense data are located in the refers record of the 23318c2ecf20Sopenharmony_ci * already set up new ERP ! 23328c2ecf20Sopenharmony_ci * check if concurrent sens is available 23338c2ecf20Sopenharmony_ci */ 23348c2ecf20Sopenharmony_ci sense = dasd_get_sense(&erp->refers->irb); 23358c2ecf20Sopenharmony_ci if (!sense) 23368c2ecf20Sopenharmony_ci erp_new = dasd_3990_erp_control_check(erp); 23378c2ecf20Sopenharmony_ci /* distinguish between 24 and 32 byte sense data */ 23388c2ecf20Sopenharmony_ci else if (sense[27] & DASD_SENSE_BIT_0) { 23398c2ecf20Sopenharmony_ci 23408c2ecf20Sopenharmony_ci /* inspect the 24 byte sense data */ 23418c2ecf20Sopenharmony_ci erp_new = dasd_3990_erp_inspect_24(erp, sense); 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_ci } else { 23448c2ecf20Sopenharmony_ci 23458c2ecf20Sopenharmony_ci /* inspect the 32 byte sense data */ 23468c2ecf20Sopenharmony_ci erp_new = dasd_3990_erp_inspect_32(erp, sense); 23478c2ecf20Sopenharmony_ci 23488c2ecf20Sopenharmony_ci } /* end distinguish between 24 and 32 byte sense data */ 23498c2ecf20Sopenharmony_ci 23508c2ecf20Sopenharmony_ci return erp_new; 23518c2ecf20Sopenharmony_ci} 23528c2ecf20Sopenharmony_ci 23538c2ecf20Sopenharmony_ci/* 23548c2ecf20Sopenharmony_ci * DASD_3990_ERP_ADD_ERP 23558c2ecf20Sopenharmony_ci * 23568c2ecf20Sopenharmony_ci * DESCRIPTION 23578c2ecf20Sopenharmony_ci * This function adds an additional request block (ERP) to the head of 23588c2ecf20Sopenharmony_ci * the given cqr (or erp). 23598c2ecf20Sopenharmony_ci * For a command mode cqr the erp is initialized as an default erp 23608c2ecf20Sopenharmony_ci * (retry TIC). 23618c2ecf20Sopenharmony_ci * For transport mode we make a copy of the original TCW (points to 23628c2ecf20Sopenharmony_ci * the original TCCB, TIDALs, etc.) but give it a fresh 23638c2ecf20Sopenharmony_ci * TSB so the original sense data will not be changed. 23648c2ecf20Sopenharmony_ci * 23658c2ecf20Sopenharmony_ci * PARAMETER 23668c2ecf20Sopenharmony_ci * cqr head of the current ERP-chain (or single cqr if 23678c2ecf20Sopenharmony_ci * first error) 23688c2ecf20Sopenharmony_ci * RETURN VALUES 23698c2ecf20Sopenharmony_ci * erp pointer to new ERP-chain head 23708c2ecf20Sopenharmony_ci */ 23718c2ecf20Sopenharmony_cistatic struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr) 23728c2ecf20Sopenharmony_ci{ 23738c2ecf20Sopenharmony_ci 23748c2ecf20Sopenharmony_ci struct dasd_device *device = cqr->startdev; 23758c2ecf20Sopenharmony_ci struct ccw1 *ccw; 23768c2ecf20Sopenharmony_ci struct dasd_ccw_req *erp; 23778c2ecf20Sopenharmony_ci int cplength, datasize; 23788c2ecf20Sopenharmony_ci struct tcw *tcw; 23798c2ecf20Sopenharmony_ci struct tsb *tsb; 23808c2ecf20Sopenharmony_ci 23818c2ecf20Sopenharmony_ci if (cqr->cpmode == 1) { 23828c2ecf20Sopenharmony_ci cplength = 0; 23838c2ecf20Sopenharmony_ci /* TCW needs to be 64 byte aligned, so leave enough room */ 23848c2ecf20Sopenharmony_ci datasize = 64 + sizeof(struct tcw) + sizeof(struct tsb); 23858c2ecf20Sopenharmony_ci } else { 23868c2ecf20Sopenharmony_ci cplength = 2; 23878c2ecf20Sopenharmony_ci datasize = 0; 23888c2ecf20Sopenharmony_ci } 23898c2ecf20Sopenharmony_ci 23908c2ecf20Sopenharmony_ci /* allocate additional request block */ 23918c2ecf20Sopenharmony_ci erp = dasd_alloc_erp_request((char *) &cqr->magic, 23928c2ecf20Sopenharmony_ci cplength, datasize, device); 23938c2ecf20Sopenharmony_ci if (IS_ERR(erp)) { 23948c2ecf20Sopenharmony_ci if (cqr->retries <= 0) { 23958c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_ERR, device, "%s", 23968c2ecf20Sopenharmony_ci "Unable to allocate ERP request"); 23978c2ecf20Sopenharmony_ci cqr->status = DASD_CQR_FAILED; 23988c2ecf20Sopenharmony_ci cqr->stopclk = get_tod_clock(); 23998c2ecf20Sopenharmony_ci } else { 24008c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_ERR, device, 24018c2ecf20Sopenharmony_ci "Unable to allocate ERP request " 24028c2ecf20Sopenharmony_ci "(%i retries left)", 24038c2ecf20Sopenharmony_ci cqr->retries); 24048c2ecf20Sopenharmony_ci dasd_block_set_timer(device->block, (HZ << 3)); 24058c2ecf20Sopenharmony_ci } 24068c2ecf20Sopenharmony_ci return erp; 24078c2ecf20Sopenharmony_ci } 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_ci ccw = cqr->cpaddr; 24108c2ecf20Sopenharmony_ci if (cqr->cpmode == 1) { 24118c2ecf20Sopenharmony_ci /* make a shallow copy of the original tcw but set new tsb */ 24128c2ecf20Sopenharmony_ci erp->cpmode = 1; 24138c2ecf20Sopenharmony_ci erp->cpaddr = PTR_ALIGN(erp->data, 64); 24148c2ecf20Sopenharmony_ci tcw = erp->cpaddr; 24158c2ecf20Sopenharmony_ci tsb = (struct tsb *) &tcw[1]; 24168c2ecf20Sopenharmony_ci *tcw = *((struct tcw *)cqr->cpaddr); 24178c2ecf20Sopenharmony_ci tcw->tsb = (long)tsb; 24188c2ecf20Sopenharmony_ci } else if (ccw->cmd_code == DASD_ECKD_CCW_PSF) { 24198c2ecf20Sopenharmony_ci /* PSF cannot be chained from NOOP/TIC */ 24208c2ecf20Sopenharmony_ci erp->cpaddr = cqr->cpaddr; 24218c2ecf20Sopenharmony_ci } else { 24228c2ecf20Sopenharmony_ci /* initialize request with default TIC to current ERP/CQR */ 24238c2ecf20Sopenharmony_ci ccw = erp->cpaddr; 24248c2ecf20Sopenharmony_ci ccw->cmd_code = CCW_CMD_NOOP; 24258c2ecf20Sopenharmony_ci ccw->flags = CCW_FLAG_CC; 24268c2ecf20Sopenharmony_ci ccw++; 24278c2ecf20Sopenharmony_ci ccw->cmd_code = CCW_CMD_TIC; 24288c2ecf20Sopenharmony_ci ccw->cda = (long)(cqr->cpaddr); 24298c2ecf20Sopenharmony_ci } 24308c2ecf20Sopenharmony_ci 24318c2ecf20Sopenharmony_ci erp->flags = cqr->flags; 24328c2ecf20Sopenharmony_ci erp->function = dasd_3990_erp_add_erp; 24338c2ecf20Sopenharmony_ci erp->refers = cqr; 24348c2ecf20Sopenharmony_ci erp->startdev = device; 24358c2ecf20Sopenharmony_ci erp->memdev = device; 24368c2ecf20Sopenharmony_ci erp->block = cqr->block; 24378c2ecf20Sopenharmony_ci erp->magic = cqr->magic; 24388c2ecf20Sopenharmony_ci erp->expires = cqr->expires; 24398c2ecf20Sopenharmony_ci erp->retries = device->default_retries; 24408c2ecf20Sopenharmony_ci erp->buildclk = get_tod_clock(); 24418c2ecf20Sopenharmony_ci erp->status = DASD_CQR_FILLED; 24428c2ecf20Sopenharmony_ci 24438c2ecf20Sopenharmony_ci return erp; 24448c2ecf20Sopenharmony_ci} 24458c2ecf20Sopenharmony_ci 24468c2ecf20Sopenharmony_ci/* 24478c2ecf20Sopenharmony_ci * DASD_3990_ERP_ADDITIONAL_ERP 24488c2ecf20Sopenharmony_ci * 24498c2ecf20Sopenharmony_ci * DESCRIPTION 24508c2ecf20Sopenharmony_ci * An additional ERP is needed to handle the current error. 24518c2ecf20Sopenharmony_ci * Add ERP to the head of the ERP-chain containing the ERP processing 24528c2ecf20Sopenharmony_ci * determined based on the sense data. 24538c2ecf20Sopenharmony_ci * 24548c2ecf20Sopenharmony_ci * PARAMETER 24558c2ecf20Sopenharmony_ci * cqr head of the current ERP-chain (or single cqr if 24568c2ecf20Sopenharmony_ci * first error) 24578c2ecf20Sopenharmony_ci * 24588c2ecf20Sopenharmony_ci * RETURN VALUES 24598c2ecf20Sopenharmony_ci * erp pointer to new ERP-chain head 24608c2ecf20Sopenharmony_ci */ 24618c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 24628c2ecf20Sopenharmony_cidasd_3990_erp_additional_erp(struct dasd_ccw_req * cqr) 24638c2ecf20Sopenharmony_ci{ 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_ci struct dasd_ccw_req *erp = NULL; 24668c2ecf20Sopenharmony_ci 24678c2ecf20Sopenharmony_ci /* add erp and initialize with default TIC */ 24688c2ecf20Sopenharmony_ci erp = dasd_3990_erp_add_erp(cqr); 24698c2ecf20Sopenharmony_ci 24708c2ecf20Sopenharmony_ci if (IS_ERR(erp)) 24718c2ecf20Sopenharmony_ci return erp; 24728c2ecf20Sopenharmony_ci 24738c2ecf20Sopenharmony_ci /* inspect sense, determine specific ERP if possible */ 24748c2ecf20Sopenharmony_ci if (erp != cqr) { 24758c2ecf20Sopenharmony_ci 24768c2ecf20Sopenharmony_ci erp = dasd_3990_erp_inspect(erp); 24778c2ecf20Sopenharmony_ci } 24788c2ecf20Sopenharmony_ci 24798c2ecf20Sopenharmony_ci return erp; 24808c2ecf20Sopenharmony_ci 24818c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_additional_erp */ 24828c2ecf20Sopenharmony_ci 24838c2ecf20Sopenharmony_ci/* 24848c2ecf20Sopenharmony_ci * DASD_3990_ERP_ERROR_MATCH 24858c2ecf20Sopenharmony_ci * 24868c2ecf20Sopenharmony_ci * DESCRIPTION 24878c2ecf20Sopenharmony_ci * Check if the device status of the given cqr is the same. 24888c2ecf20Sopenharmony_ci * This means that the failed CCW and the relevant sense data 24898c2ecf20Sopenharmony_ci * must match. 24908c2ecf20Sopenharmony_ci * I don't distinguish between 24 and 32 byte sense because in case of 24918c2ecf20Sopenharmony_ci * 24 byte sense byte 25 and 27 is set as well. 24928c2ecf20Sopenharmony_ci * 24938c2ecf20Sopenharmony_ci * PARAMETER 24948c2ecf20Sopenharmony_ci * cqr1 first cqr, which will be compared with the 24958c2ecf20Sopenharmony_ci * cqr2 second cqr. 24968c2ecf20Sopenharmony_ci * 24978c2ecf20Sopenharmony_ci * RETURN VALUES 24988c2ecf20Sopenharmony_ci * match 'boolean' for match found 24998c2ecf20Sopenharmony_ci * returns 1 if match found, otherwise 0. 25008c2ecf20Sopenharmony_ci */ 25018c2ecf20Sopenharmony_cistatic int dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, 25028c2ecf20Sopenharmony_ci struct dasd_ccw_req *cqr2) 25038c2ecf20Sopenharmony_ci{ 25048c2ecf20Sopenharmony_ci char *sense1, *sense2; 25058c2ecf20Sopenharmony_ci 25068c2ecf20Sopenharmony_ci if (cqr1->startdev != cqr2->startdev) 25078c2ecf20Sopenharmony_ci return 0; 25088c2ecf20Sopenharmony_ci 25098c2ecf20Sopenharmony_ci sense1 = dasd_get_sense(&cqr1->irb); 25108c2ecf20Sopenharmony_ci sense2 = dasd_get_sense(&cqr2->irb); 25118c2ecf20Sopenharmony_ci 25128c2ecf20Sopenharmony_ci /* one request has sense data, the other not -> no match, return 0 */ 25138c2ecf20Sopenharmony_ci if (!sense1 != !sense2) 25148c2ecf20Sopenharmony_ci return 0; 25158c2ecf20Sopenharmony_ci /* no sense data in both cases -> check cstat for IFCC */ 25168c2ecf20Sopenharmony_ci if (!sense1 && !sense2) { 25178c2ecf20Sopenharmony_ci if ((scsw_cstat(&cqr1->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK | 25188c2ecf20Sopenharmony_ci SCHN_STAT_CHN_CTRL_CHK)) == 25198c2ecf20Sopenharmony_ci (scsw_cstat(&cqr2->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK | 25208c2ecf20Sopenharmony_ci SCHN_STAT_CHN_CTRL_CHK))) 25218c2ecf20Sopenharmony_ci return 1; /* match with ifcc*/ 25228c2ecf20Sopenharmony_ci } 25238c2ecf20Sopenharmony_ci /* check sense data; byte 0-2,25,27 */ 25248c2ecf20Sopenharmony_ci if (!(sense1 && sense2 && 25258c2ecf20Sopenharmony_ci (memcmp(sense1, sense2, 3) == 0) && 25268c2ecf20Sopenharmony_ci (sense1[27] == sense2[27]) && 25278c2ecf20Sopenharmony_ci (sense1[25] == sense2[25]))) { 25288c2ecf20Sopenharmony_ci 25298c2ecf20Sopenharmony_ci return 0; /* sense doesn't match */ 25308c2ecf20Sopenharmony_ci } 25318c2ecf20Sopenharmony_ci 25328c2ecf20Sopenharmony_ci return 1; /* match */ 25338c2ecf20Sopenharmony_ci 25348c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_error_match */ 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci/* 25378c2ecf20Sopenharmony_ci * DASD_3990_ERP_IN_ERP 25388c2ecf20Sopenharmony_ci * 25398c2ecf20Sopenharmony_ci * DESCRIPTION 25408c2ecf20Sopenharmony_ci * check if the current error already happened before. 25418c2ecf20Sopenharmony_ci * quick exit if current cqr is not an ERP (cqr->refers=NULL) 25428c2ecf20Sopenharmony_ci * 25438c2ecf20Sopenharmony_ci * PARAMETER 25448c2ecf20Sopenharmony_ci * cqr failed cqr (either original cqr or already an erp) 25458c2ecf20Sopenharmony_ci * 25468c2ecf20Sopenharmony_ci * RETURN VALUES 25478c2ecf20Sopenharmony_ci * erp erp-pointer to the already defined error 25488c2ecf20Sopenharmony_ci * recovery procedure OR 25498c2ecf20Sopenharmony_ci * NULL if a 'new' error occurred. 25508c2ecf20Sopenharmony_ci */ 25518c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 25528c2ecf20Sopenharmony_cidasd_3990_erp_in_erp(struct dasd_ccw_req *cqr) 25538c2ecf20Sopenharmony_ci{ 25548c2ecf20Sopenharmony_ci 25558c2ecf20Sopenharmony_ci struct dasd_ccw_req *erp_head = cqr, /* save erp chain head */ 25568c2ecf20Sopenharmony_ci *erp_match = NULL; /* save erp chain head */ 25578c2ecf20Sopenharmony_ci int match = 0; /* 'boolean' for matching error found */ 25588c2ecf20Sopenharmony_ci 25598c2ecf20Sopenharmony_ci if (cqr->refers == NULL) { /* return if not in erp */ 25608c2ecf20Sopenharmony_ci return NULL; 25618c2ecf20Sopenharmony_ci } 25628c2ecf20Sopenharmony_ci 25638c2ecf20Sopenharmony_ci /* check the erp/cqr chain for current error */ 25648c2ecf20Sopenharmony_ci do { 25658c2ecf20Sopenharmony_ci match = dasd_3990_erp_error_match(erp_head, cqr->refers); 25668c2ecf20Sopenharmony_ci erp_match = cqr; /* save possible matching erp */ 25678c2ecf20Sopenharmony_ci cqr = cqr->refers; /* check next erp/cqr in queue */ 25688c2ecf20Sopenharmony_ci 25698c2ecf20Sopenharmony_ci } while ((cqr->refers != NULL) && (!match)); 25708c2ecf20Sopenharmony_ci 25718c2ecf20Sopenharmony_ci if (!match) { 25728c2ecf20Sopenharmony_ci return NULL; /* no match was found */ 25738c2ecf20Sopenharmony_ci } 25748c2ecf20Sopenharmony_ci 25758c2ecf20Sopenharmony_ci return erp_match; /* return address of matching erp */ 25768c2ecf20Sopenharmony_ci 25778c2ecf20Sopenharmony_ci} /* END dasd_3990_erp_in_erp */ 25788c2ecf20Sopenharmony_ci 25798c2ecf20Sopenharmony_ci/* 25808c2ecf20Sopenharmony_ci * DASD_3990_ERP_FURTHER_ERP (24 & 32 byte sense) 25818c2ecf20Sopenharmony_ci * 25828c2ecf20Sopenharmony_ci * DESCRIPTION 25838c2ecf20Sopenharmony_ci * No retry is left for the current ERP. Check what has to be done 25848c2ecf20Sopenharmony_ci * with the ERP. 25858c2ecf20Sopenharmony_ci * - do further defined ERP action or 25868c2ecf20Sopenharmony_ci * - wait for interrupt or 25878c2ecf20Sopenharmony_ci * - exit with permanent error 25888c2ecf20Sopenharmony_ci * 25898c2ecf20Sopenharmony_ci * PARAMETER 25908c2ecf20Sopenharmony_ci * erp ERP which is in progress with no retry left 25918c2ecf20Sopenharmony_ci * 25928c2ecf20Sopenharmony_ci * RETURN VALUES 25938c2ecf20Sopenharmony_ci * erp modified/additional ERP 25948c2ecf20Sopenharmony_ci */ 25958c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 25968c2ecf20Sopenharmony_cidasd_3990_erp_further_erp(struct dasd_ccw_req *erp) 25978c2ecf20Sopenharmony_ci{ 25988c2ecf20Sopenharmony_ci 25998c2ecf20Sopenharmony_ci struct dasd_device *device = erp->startdev; 26008c2ecf20Sopenharmony_ci char *sense = dasd_get_sense(&erp->irb); 26018c2ecf20Sopenharmony_ci 26028c2ecf20Sopenharmony_ci /* check for 24 byte sense ERP */ 26038c2ecf20Sopenharmony_ci if ((erp->function == dasd_3990_erp_bus_out) || 26048c2ecf20Sopenharmony_ci (erp->function == dasd_3990_erp_action_1) || 26058c2ecf20Sopenharmony_ci (erp->function == dasd_3990_erp_action_4)) { 26068c2ecf20Sopenharmony_ci 26078c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_1(erp); 26088c2ecf20Sopenharmony_ci 26098c2ecf20Sopenharmony_ci } else if (erp->function == dasd_3990_erp_action_1_sec) { 26108c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_1_sec(erp); 26118c2ecf20Sopenharmony_ci } else if (erp->function == dasd_3990_erp_action_5) { 26128c2ecf20Sopenharmony_ci 26138c2ecf20Sopenharmony_ci /* retries have not been successful */ 26148c2ecf20Sopenharmony_ci /* prepare erp for retry on different channel path */ 26158c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_1(erp); 26168c2ecf20Sopenharmony_ci 26178c2ecf20Sopenharmony_ci if (sense && !(sense[2] & DASD_SENSE_BIT_0)) { 26188c2ecf20Sopenharmony_ci 26198c2ecf20Sopenharmony_ci /* issue a Diagnostic Control command with an 26208c2ecf20Sopenharmony_ci * Inhibit Write subcommand */ 26218c2ecf20Sopenharmony_ci 26228c2ecf20Sopenharmony_ci switch (sense[25]) { 26238c2ecf20Sopenharmony_ci case 0x17: 26248c2ecf20Sopenharmony_ci case 0x57:{ /* controller */ 26258c2ecf20Sopenharmony_ci erp = dasd_3990_erp_DCTL(erp, 0x20); 26268c2ecf20Sopenharmony_ci break; 26278c2ecf20Sopenharmony_ci } 26288c2ecf20Sopenharmony_ci case 0x18: 26298c2ecf20Sopenharmony_ci case 0x58:{ /* channel path */ 26308c2ecf20Sopenharmony_ci erp = dasd_3990_erp_DCTL(erp, 0x40); 26318c2ecf20Sopenharmony_ci break; 26328c2ecf20Sopenharmony_ci } 26338c2ecf20Sopenharmony_ci case 0x19: 26348c2ecf20Sopenharmony_ci case 0x59:{ /* storage director */ 26358c2ecf20Sopenharmony_ci erp = dasd_3990_erp_DCTL(erp, 0x80); 26368c2ecf20Sopenharmony_ci break; 26378c2ecf20Sopenharmony_ci } 26388c2ecf20Sopenharmony_ci default: 26398c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_WARNING, device, 26408c2ecf20Sopenharmony_ci "invalid subcommand modifier 0x%x " 26418c2ecf20Sopenharmony_ci "for Diagnostic Control Command", 26428c2ecf20Sopenharmony_ci sense[25]); 26438c2ecf20Sopenharmony_ci } 26448c2ecf20Sopenharmony_ci } 26458c2ecf20Sopenharmony_ci 26468c2ecf20Sopenharmony_ci /* check for 32 byte sense ERP */ 26478c2ecf20Sopenharmony_ci } else if (sense && 26488c2ecf20Sopenharmony_ci ((erp->function == dasd_3990_erp_compound_retry) || 26498c2ecf20Sopenharmony_ci (erp->function == dasd_3990_erp_compound_path) || 26508c2ecf20Sopenharmony_ci (erp->function == dasd_3990_erp_compound_code) || 26518c2ecf20Sopenharmony_ci (erp->function == dasd_3990_erp_compound_config))) { 26528c2ecf20Sopenharmony_ci 26538c2ecf20Sopenharmony_ci erp = dasd_3990_erp_compound(erp, sense); 26548c2ecf20Sopenharmony_ci 26558c2ecf20Sopenharmony_ci } else { 26568c2ecf20Sopenharmony_ci /* 26578c2ecf20Sopenharmony_ci * No retry left and no additional special handling 26588c2ecf20Sopenharmony_ci * necessary 26598c2ecf20Sopenharmony_ci */ 26608c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 26618c2ecf20Sopenharmony_ci "ERP %p has run out of retries and failed\n", erp); 26628c2ecf20Sopenharmony_ci 26638c2ecf20Sopenharmony_ci erp->status = DASD_CQR_FAILED; 26648c2ecf20Sopenharmony_ci } 26658c2ecf20Sopenharmony_ci 26668c2ecf20Sopenharmony_ci return erp; 26678c2ecf20Sopenharmony_ci 26688c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_further_erp */ 26698c2ecf20Sopenharmony_ci 26708c2ecf20Sopenharmony_ci/* 26718c2ecf20Sopenharmony_ci * DASD_3990_ERP_HANDLE_MATCH_ERP 26728c2ecf20Sopenharmony_ci * 26738c2ecf20Sopenharmony_ci * DESCRIPTION 26748c2ecf20Sopenharmony_ci * An error occurred again and an ERP has been detected which is already 26758c2ecf20Sopenharmony_ci * used to handle this error (e.g. retries). 26768c2ecf20Sopenharmony_ci * All prior ERP's are asumed to be successful and therefore removed 26778c2ecf20Sopenharmony_ci * from queue. 26788c2ecf20Sopenharmony_ci * If retry counter of matching erp is already 0, it is checked if further 26798c2ecf20Sopenharmony_ci * action is needed (besides retry) or if the ERP has failed. 26808c2ecf20Sopenharmony_ci * 26818c2ecf20Sopenharmony_ci * PARAMETER 26828c2ecf20Sopenharmony_ci * erp_head first ERP in ERP-chain 26838c2ecf20Sopenharmony_ci * erp ERP that handles the actual error. 26848c2ecf20Sopenharmony_ci * (matching erp) 26858c2ecf20Sopenharmony_ci * 26868c2ecf20Sopenharmony_ci * RETURN VALUES 26878c2ecf20Sopenharmony_ci * erp modified/additional ERP 26888c2ecf20Sopenharmony_ci */ 26898c2ecf20Sopenharmony_cistatic struct dasd_ccw_req * 26908c2ecf20Sopenharmony_cidasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head, 26918c2ecf20Sopenharmony_ci struct dasd_ccw_req *erp) 26928c2ecf20Sopenharmony_ci{ 26938c2ecf20Sopenharmony_ci 26948c2ecf20Sopenharmony_ci struct dasd_device *device = erp_head->startdev; 26958c2ecf20Sopenharmony_ci struct dasd_ccw_req *erp_done = erp_head; /* finished req */ 26968c2ecf20Sopenharmony_ci struct dasd_ccw_req *erp_free = NULL; /* req to be freed */ 26978c2ecf20Sopenharmony_ci 26988c2ecf20Sopenharmony_ci /* loop over successful ERPs and remove them from chanq */ 26998c2ecf20Sopenharmony_ci while (erp_done != erp) { 27008c2ecf20Sopenharmony_ci 27018c2ecf20Sopenharmony_ci if (erp_done == NULL) /* end of chain reached */ 27028c2ecf20Sopenharmony_ci panic(PRINTK_HEADER "Programming error in ERP! The " 27038c2ecf20Sopenharmony_ci "original request was lost\n"); 27048c2ecf20Sopenharmony_ci 27058c2ecf20Sopenharmony_ci /* remove the request from the device queue */ 27068c2ecf20Sopenharmony_ci list_del(&erp_done->blocklist); 27078c2ecf20Sopenharmony_ci 27088c2ecf20Sopenharmony_ci erp_free = erp_done; 27098c2ecf20Sopenharmony_ci erp_done = erp_done->refers; 27108c2ecf20Sopenharmony_ci 27118c2ecf20Sopenharmony_ci /* free the finished erp request */ 27128c2ecf20Sopenharmony_ci dasd_free_erp_request(erp_free, erp_free->memdev); 27138c2ecf20Sopenharmony_ci 27148c2ecf20Sopenharmony_ci } /* end while */ 27158c2ecf20Sopenharmony_ci 27168c2ecf20Sopenharmony_ci if (erp->retries > 0) { 27178c2ecf20Sopenharmony_ci 27188c2ecf20Sopenharmony_ci char *sense = dasd_get_sense(&erp->refers->irb); 27198c2ecf20Sopenharmony_ci 27208c2ecf20Sopenharmony_ci /* check for special retries */ 27218c2ecf20Sopenharmony_ci if (sense && erp->function == dasd_3990_erp_action_4) { 27228c2ecf20Sopenharmony_ci 27238c2ecf20Sopenharmony_ci erp = dasd_3990_erp_action_4(erp, sense); 27248c2ecf20Sopenharmony_ci 27258c2ecf20Sopenharmony_ci } else if (sense && 27268c2ecf20Sopenharmony_ci erp->function == dasd_3990_erp_action_1B_32) { 27278c2ecf20Sopenharmony_ci 27288c2ecf20Sopenharmony_ci erp = dasd_3990_update_1B(erp, sense); 27298c2ecf20Sopenharmony_ci 27308c2ecf20Sopenharmony_ci } else if (sense && erp->function == dasd_3990_erp_int_req) { 27318c2ecf20Sopenharmony_ci 27328c2ecf20Sopenharmony_ci erp = dasd_3990_erp_int_req(erp); 27338c2ecf20Sopenharmony_ci 27348c2ecf20Sopenharmony_ci } else { 27358c2ecf20Sopenharmony_ci /* simple retry */ 27368c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_DEBUG, device, 27378c2ecf20Sopenharmony_ci "%i retries left for erp %p", 27388c2ecf20Sopenharmony_ci erp->retries, erp); 27398c2ecf20Sopenharmony_ci 27408c2ecf20Sopenharmony_ci /* handle the request again... */ 27418c2ecf20Sopenharmony_ci erp->status = DASD_CQR_FILLED; 27428c2ecf20Sopenharmony_ci } 27438c2ecf20Sopenharmony_ci 27448c2ecf20Sopenharmony_ci } else { 27458c2ecf20Sopenharmony_ci /* no retry left - check for further necessary action */ 27468c2ecf20Sopenharmony_ci /* if no further actions, handle rest as permanent error */ 27478c2ecf20Sopenharmony_ci erp = dasd_3990_erp_further_erp(erp); 27488c2ecf20Sopenharmony_ci } 27498c2ecf20Sopenharmony_ci 27508c2ecf20Sopenharmony_ci return erp; 27518c2ecf20Sopenharmony_ci 27528c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_handle_match_erp */ 27538c2ecf20Sopenharmony_ci 27548c2ecf20Sopenharmony_ci/* 27558c2ecf20Sopenharmony_ci * DASD_3990_ERP_ACTION 27568c2ecf20Sopenharmony_ci * 27578c2ecf20Sopenharmony_ci * DESCRIPTION 27588c2ecf20Sopenharmony_ci * control routine for 3990 erp actions. 27598c2ecf20Sopenharmony_ci * Has to be called with the queue lock (namely the s390_irq_lock) acquired. 27608c2ecf20Sopenharmony_ci * 27618c2ecf20Sopenharmony_ci * PARAMETER 27628c2ecf20Sopenharmony_ci * cqr failed cqr (either original cqr or already an erp) 27638c2ecf20Sopenharmony_ci * 27648c2ecf20Sopenharmony_ci * RETURN VALUES 27658c2ecf20Sopenharmony_ci * erp erp-pointer to the head of the ERP action chain. 27668c2ecf20Sopenharmony_ci * This means: 27678c2ecf20Sopenharmony_ci * - either a ptr to an additional ERP cqr or 27688c2ecf20Sopenharmony_ci * - the original given cqr (which's status might 27698c2ecf20Sopenharmony_ci * be modified) 27708c2ecf20Sopenharmony_ci */ 27718c2ecf20Sopenharmony_cistruct dasd_ccw_req * 27728c2ecf20Sopenharmony_cidasd_3990_erp_action(struct dasd_ccw_req * cqr) 27738c2ecf20Sopenharmony_ci{ 27748c2ecf20Sopenharmony_ci struct dasd_ccw_req *erp = NULL; 27758c2ecf20Sopenharmony_ci struct dasd_device *device = cqr->startdev; 27768c2ecf20Sopenharmony_ci struct dasd_ccw_req *temp_erp = NULL; 27778c2ecf20Sopenharmony_ci 27788c2ecf20Sopenharmony_ci if (device->features & DASD_FEATURE_ERPLOG) { 27798c2ecf20Sopenharmony_ci /* print current erp_chain */ 27808c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 27818c2ecf20Sopenharmony_ci "ERP chain at BEGINNING of ERP-ACTION\n"); 27828c2ecf20Sopenharmony_ci for (temp_erp = cqr; 27838c2ecf20Sopenharmony_ci temp_erp != NULL; temp_erp = temp_erp->refers) { 27848c2ecf20Sopenharmony_ci 27858c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 27868c2ecf20Sopenharmony_ci "ERP %p (%02x) refers to %p\n", 27878c2ecf20Sopenharmony_ci temp_erp, temp_erp->status, 27888c2ecf20Sopenharmony_ci temp_erp->refers); 27898c2ecf20Sopenharmony_ci } 27908c2ecf20Sopenharmony_ci } 27918c2ecf20Sopenharmony_ci 27928c2ecf20Sopenharmony_ci /* double-check if current erp/cqr was successful */ 27938c2ecf20Sopenharmony_ci if ((scsw_cstat(&cqr->irb.scsw) == 0x00) && 27948c2ecf20Sopenharmony_ci (scsw_dstat(&cqr->irb.scsw) == 27958c2ecf20Sopenharmony_ci (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) { 27968c2ecf20Sopenharmony_ci 27978c2ecf20Sopenharmony_ci DBF_DEV_EVENT(DBF_DEBUG, device, 27988c2ecf20Sopenharmony_ci "ERP called for successful request %p" 27998c2ecf20Sopenharmony_ci " - NO ERP necessary", cqr); 28008c2ecf20Sopenharmony_ci 28018c2ecf20Sopenharmony_ci cqr->status = DASD_CQR_DONE; 28028c2ecf20Sopenharmony_ci 28038c2ecf20Sopenharmony_ci return cqr; 28048c2ecf20Sopenharmony_ci } 28058c2ecf20Sopenharmony_ci 28068c2ecf20Sopenharmony_ci /* check if error happened before */ 28078c2ecf20Sopenharmony_ci erp = dasd_3990_erp_in_erp(cqr); 28088c2ecf20Sopenharmony_ci 28098c2ecf20Sopenharmony_ci if (erp == NULL) { 28108c2ecf20Sopenharmony_ci /* no matching erp found - set up erp */ 28118c2ecf20Sopenharmony_ci erp = dasd_3990_erp_additional_erp(cqr); 28128c2ecf20Sopenharmony_ci if (IS_ERR(erp)) 28138c2ecf20Sopenharmony_ci return erp; 28148c2ecf20Sopenharmony_ci } else { 28158c2ecf20Sopenharmony_ci /* matching erp found - set all leading erp's to DONE */ 28168c2ecf20Sopenharmony_ci erp = dasd_3990_erp_handle_match_erp(cqr, erp); 28178c2ecf20Sopenharmony_ci } 28188c2ecf20Sopenharmony_ci 28198c2ecf20Sopenharmony_ci 28208c2ecf20Sopenharmony_ci /* 28218c2ecf20Sopenharmony_ci * For path verification work we need to stick with the path that was 28228c2ecf20Sopenharmony_ci * originally chosen so that the per path configuration data is 28238c2ecf20Sopenharmony_ci * assigned correctly. 28248c2ecf20Sopenharmony_ci */ 28258c2ecf20Sopenharmony_ci if (test_bit(DASD_CQR_VERIFY_PATH, &erp->flags) && cqr->lpm) { 28268c2ecf20Sopenharmony_ci erp->lpm = cqr->lpm; 28278c2ecf20Sopenharmony_ci } 28288c2ecf20Sopenharmony_ci 28298c2ecf20Sopenharmony_ci if (device->features & DASD_FEATURE_ERPLOG) { 28308c2ecf20Sopenharmony_ci /* print current erp_chain */ 28318c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 28328c2ecf20Sopenharmony_ci "ERP chain at END of ERP-ACTION\n"); 28338c2ecf20Sopenharmony_ci for (temp_erp = erp; 28348c2ecf20Sopenharmony_ci temp_erp != NULL; temp_erp = temp_erp->refers) { 28358c2ecf20Sopenharmony_ci 28368c2ecf20Sopenharmony_ci dev_err(&device->cdev->dev, 28378c2ecf20Sopenharmony_ci "ERP %p (%02x) refers to %p\n", 28388c2ecf20Sopenharmony_ci temp_erp, temp_erp->status, 28398c2ecf20Sopenharmony_ci temp_erp->refers); 28408c2ecf20Sopenharmony_ci } 28418c2ecf20Sopenharmony_ci } 28428c2ecf20Sopenharmony_ci 28438c2ecf20Sopenharmony_ci /* enqueue ERP request if it's a new one */ 28448c2ecf20Sopenharmony_ci if (list_empty(&erp->blocklist)) { 28458c2ecf20Sopenharmony_ci cqr->status = DASD_CQR_IN_ERP; 28468c2ecf20Sopenharmony_ci /* add erp request before the cqr */ 28478c2ecf20Sopenharmony_ci list_add_tail(&erp->blocklist, &cqr->blocklist); 28488c2ecf20Sopenharmony_ci } 28498c2ecf20Sopenharmony_ci 28508c2ecf20Sopenharmony_ci 28518c2ecf20Sopenharmony_ci 28528c2ecf20Sopenharmony_ci return erp; 28538c2ecf20Sopenharmony_ci 28548c2ecf20Sopenharmony_ci} /* end dasd_3990_erp_action */ 2855