📄 dasd_3990_erp.c
字号:
* RETURN VALUES * void */voiddasd_3990_erp_block_queue (ccw_req_t *erp, unsigned long expires){ dasd_device_t *device = erp->device; DASD_MESSAGE (KERN_INFO, device, "blocking request queue for %is", (int) expires); check_then_set (&erp->status, CQR_STATUS_ERROR, CQR_STATUS_PENDING); /* restart queue after some time */ device->timer.function = dasd_3990_erp_restart_queue; device->timer.data = (unsigned long) erp; device->timer.expires = jiffies + (expires * HZ); add_timer(&device->timer); } /* end dasd_3990_erp_block_queue */ /* * DASD_3990_ERP_RESTART_QUEUE * * DESCRIPTION * Restarts request currently in status PENDING. * This has to be done if either an related interrupt has received, or * a timer has expired. * * * PARAMETER * erp pointer to the PENDING ERP * * RETURN VALUES * void * */voiddasd_3990_erp_restart_queue (unsigned long erp){ ccw_req_t *cqr = (void *) erp; dasd_device_t *device = cqr->device; unsigned long flags; /* get the needed locks to modify the request queue */ s390irq_spin_lock_irqsave (device->devinfo.irq, flags); /* 'restart' the device queue */ if (cqr->status == CQR_STATUS_PENDING) { DASD_MESSAGE (KERN_INFO, device, "%s", "request queue restarted by MIH"); check_then_set (&cqr->status, CQR_STATUS_PENDING, CQR_STATUS_QUEUED); } /* release the lock */ s390irq_spin_unlock_irqrestore (device->devinfo.irq, flags); dasd_schedule_bh (device);} /* end dasd_3990_erp_restart_queue *//* * DASD_3990_ERP_INT_REQ * * DESCRIPTION * Handles 'Intervention Required' error. * This means either device offline or not installed. * * PARAMETER * erp current erp * RETURN VALUES * erp modified erp */ccw_req_t *dasd_3990_erp_int_req (ccw_req_t *erp){ dasd_device_t *device = erp->device; /* first time set initial retry counter and erp_function */ /* and retry once without blocking queue */ /* (this enables easier enqueing of the cqr) */ if (erp->function != dasd_3990_erp_int_req) { erp->retries = 256; erp->function = dasd_3990_erp_int_req; } else { /* issue a message and wait for 'device ready' interrupt */ DASD_MESSAGE (KERN_ERR, device, "%s", "is offline or not installed - " "INTERVENTION REQUIRED!!"); dasd_3990_erp_block_queue (erp, 60); } return erp;} /* end dasd_3990_erp_int_req *//* * DASD_3990_ERP_ALTERNATE_PATH * * DESCRIPTION * Repeat the operation on a different channel path. * If all alternate paths have been tried, the request is posted with a * permanent error. * * PARAMETER * erp pointer to the current ERP * * RETURN VALUES * erp modified pointer to the ERP * */voiddasd_3990_erp_alternate_path (ccw_req_t *erp){ dasd_device_t *device = erp->device; int irq = device->devinfo.irq; /* try alternate valid path */ erp->lpm &= ~(erp->dstat->lpum); erp->options |= DOIO_VALID_LPM; /* use LPM for DO_IO */ if ((erp->lpm & ioinfo[irq]->opm) != 0x00) { DASD_MESSAGE (KERN_DEBUG, device, "try alternate lpm=%x (lpum=%x / opm=%x)", erp->lpm, erp->dstat->lpum, ioinfo[irq]->opm); /* reset status to queued to handle the request again... */ check_then_set (&erp->status, CQR_STATUS_ERROR, CQR_STATUS_QUEUED); erp->retries = 1; } else { DASD_MESSAGE (KERN_ERR, device, "No alternate channel path left (lpum=%x / " "opm=%x) -> permanent error", erp->dstat->lpum, ioinfo[irq]->opm); /* post request with permanent error */ check_then_set (&erp->status, CQR_STATUS_ERROR, CQR_STATUS_FAILED); } } /* end dasd_3990_erp_alternate_path *//* * DASD_3990_ERP_DCTL * * DESCRIPTION * Setup cqr to do the Diagnostic Control (DCTL) command with an * Inhibit Write subcommand (0x20) and the given modifier. * * PARAMETER * erp pointer to the current (failed) ERP * modifier subcommand modifier * * RETURN VALUES * dctl_cqr pointer to NEW dctl_cqr * */ccw_req_t *dasd_3990_erp_DCTL (ccw_req_t *erp, char modifier){ dasd_device_t *device = erp->device; DCTL_data_t *DCTL_data; ccw1_t *ccw; ccw_req_t *dctl_cqr = dasd_alloc_request ((char *) &erp->magic, 1, sizeof(DCTL_data_t), erp->device); if (!dctl_cqr) { DASD_MESSAGE (KERN_ERR, device, "%s", "Unable to allocate DCTL-CQR"); check_then_set (&erp->status, CQR_STATUS_ERROR, CQR_STATUS_FAILED); return erp; } DCTL_data = dctl_cqr->data; DCTL_data->subcommand = 0x02; /* Inhibit Write */ DCTL_data->modifier = modifier; ccw = dctl_cqr->cpaddr; memset (ccw, 0, sizeof (ccw1_t)); ccw->cmd_code = CCW_CMD_DCTL; ccw->count = 4; if (dasd_set_normalized_cda(ccw, __pa (DCTL_data), dctl_cqr, erp->device)) { dasd_free_request (dctl_cqr, erp->device); DASD_MESSAGE (KERN_ERR, device, "%s", "Unable to allocate DCTL-CQR"); check_then_set (&erp->status, CQR_STATUS_ERROR, CQR_STATUS_FAILED); return erp; } dctl_cqr->function = dasd_3990_erp_DCTL; dctl_cqr->refers = erp; dctl_cqr->device = erp->device; dctl_cqr->magic = erp->magic; dctl_cqr->lpm = LPM_ANYPATH; dctl_cqr->expires = 5 * TOD_MIN; dctl_cqr->retries = 2; asm volatile ("STCK %0":"=m" (dctl_cqr->buildclk)); dctl_cqr->status = CQR_STATUS_FILLED; return dctl_cqr;} /* end dasd_3990_erp_DCTL *//* * DASD_3990_ERP_ACTION_1 * * DESCRIPTION * Setup ERP to do the ERP action 1 (see Reference manual). * Repeat the operation on a different channel path. * If all alternate paths have been tried, the request is posted with a * permanent error. * Note: duplex handling is not implemented (yet). * * PARAMETER * erp pointer to the current ERP * * RETURN VALUES * erp pointer to the ERP * */ccw_req_t *dasd_3990_erp_action_1 (ccw_req_t *erp){ erp->function = dasd_3990_erp_action_1; dasd_3990_erp_alternate_path (erp); return erp;} /* end dasd_3990_erp_action_1 *//* * DASD_3990_ERP_ACTION_4 * * DESCRIPTION * Setup ERP to do the ERP action 4 (see Reference manual). * Set the current request to PENDING to block the CQR queue for that device * until the state change interrupt appears. * Use a timer (20 seconds) to retry the cqr if the interrupt is still missing. * * PARAMETER * sense sense data of the actual error * erp pointer to the current ERP * * RETURN VALUES * erp pointer to the ERP * */ccw_req_t *dasd_3990_erp_action_4 (ccw_req_t *erp, char *sense){ dasd_device_t *device = erp->device; /* first time set initial retry counter and erp_function */ /* and retry once without waiting for state change pending */ /* interrupt (this enables easier enqueing of the cqr) */ if (erp->function != dasd_3990_erp_action_4) { erp->retries = 256; erp->function = dasd_3990_erp_action_4; } else { if (sense[25] & 0x1D) { /* state change pending */ DASD_MESSAGE (KERN_INFO, device, "%s", "waiting for state change pending " "int"); dasd_3990_erp_block_queue (erp, 30); } else { /* no state change pending - retry */ check_then_set (&erp->status, CQR_STATUS_ERROR, CQR_STATUS_QUEUED); } } return erp;} /* end dasd_3990_erp_action_4 *//* ***************************************************************************** * 24 byte sense ERP functions (only) ***************************************************************************** *//* * DASD_3990_ERP_ACTION_5 * * DESCRIPTION * Setup ERP to do the ERP action 5 (see Reference manual). * NOTE: Further handling is done in xxx_further_erp after the retries. * * PARAMETER * erp pointer to the current ERP * * RETURN VALUES * erp pointer to the ERP * */ccw_req_t *dasd_3990_erp_action_5 (ccw_req_t *erp){ /* first of all retry */ erp->retries = 10; erp->function = dasd_3990_erp_action_5; return erp;} /* end dasd_3990_erp_action_5 *//* * DASD_3990_HANDLE_ENV_DATA * * DESCRIPTION * Handles 24 byte 'Environmental data present'. * Does a analysis of the sense data (message Format) * and prints the error messages. * * PARAMETER * sense current sense data * * RETURN VALUES * void */voiddasd_3990_handle_env_data (ccw_req_t *erp, char *sense){ dasd_device_t *device = erp->device; char msg_format = (sense[7] & 0xF0); char msg_no = (sense[7] & 0x0F); switch (msg_format) { case 0x00: /* Format 0 - Program or System Checks */ if (sense[1] & 0x10) { /* check message to operator bit */ switch (msg_no) { case 0x00: /* No Message */ break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -