⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dasd_3990_erp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  * File...........: linux/drivers/s390/block/dasd_3990_erp.c * Author(s)......: Horst  Hummel    <Horst.Hummel@de.ibm.com>  *		    Holger Smolinski <Holger.Smolinski@de.ibm.com> * Bugreports.to..: <Linux390@de.ibm.com> * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001 * * $Revision: 1.36 $ */#include <linux/timer.h>#include <linux/slab.h>#include <asm/idals.h>#include <asm/todclk.h>#define PRINTK_HEADER "dasd_erp(3990): "#include "dasd_int.h"#include "dasd_eckd.h"struct DCTL_data {	unsigned char subcommand;  /* e.g Inhibit Write, Enable Write,... */	unsigned char modifier;	   /* Subcommand modifier */	unsigned short res;	   /* reserved */} __attribute__ ((packed));/* *****************************************************************************  * SECTION ERP EXAMINATION *****************************************************************************  *//* * DASD_3990_ERP_EXAMINE_24  * * DESCRIPTION *   Checks only for fatal (unrecoverable) error.  *   A detailed examination of the sense data is done later outside *   the interrupt handler. * *   Each bit configuration leading to an action code 2 (Exit with *   programming error or unusual condition indication) *   are handled as fatal error磗. *  *   All other configurations are handled as recoverable errors. * * RETURN VALUES *   dasd_era_fatal	for all fatal (unrecoverable errors) *   dasd_era_recover	for all others. */static dasd_era_tdasd_3990_erp_examine_24(struct dasd_ccw_req * cqr, char *sense){	struct dasd_device *device = cqr->device;	/* check for 'Command Reject' */	if ((sense[0] & SNS0_CMD_REJECT) &&	    (!(sense[2] & SNS2_ENV_DATA_PRESENT))) {		DEV_MESSAGE(KERN_ERR, device, "%s",			    "EXAMINE 24: Command Reject detected - "			    "fatal error");		return dasd_era_fatal;	}	/* check for 'Invalid Track Format' */	if ((sense[1] & SNS1_INV_TRACK_FORMAT) &&	    (!(sense[2] & SNS2_ENV_DATA_PRESENT))) {		DEV_MESSAGE(KERN_ERR, device, "%s",			    "EXAMINE 24: Invalid Track Format detected "			    "- fatal error");		return dasd_era_fatal;	}	/* check for 'No Record Found' */	if (sense[1] & SNS1_NO_REC_FOUND) {                /* FIXME: fatal error ?!? */		DEV_MESSAGE(KERN_ERR, device,			    "EXAMINE 24: No Record Found detected %s",                            device->state <= DASD_STATE_BASIC ?			    " " : "- fatal error");		return dasd_era_fatal;	}	/* return recoverable for all others */	return dasd_era_recover;}				/* END dasd_3990_erp_examine_24 *//* * DASD_3990_ERP_EXAMINE_32  * * DESCRIPTION *   Checks only for fatal/no/recoverable error.  *   A detailed examination of the sense data is done later outside *   the interrupt handler. * * RETURN VALUES *   dasd_era_none	no error  *   dasd_era_fatal	for all fatal (unrecoverable errors) *   dasd_era_recover	for recoverable others. */static dasd_era_tdasd_3990_erp_examine_32(struct dasd_ccw_req * cqr, char *sense){	struct dasd_device *device = cqr->device;	switch (sense[25]) {	case 0x00:		return dasd_era_none;	case 0x01:		DEV_MESSAGE(KERN_ERR, device, "%s", "EXAMINE 32: fatal error");		return dasd_era_fatal;	default:		return dasd_era_recover;	}}				/* end dasd_3990_erp_examine_32 *//* * DASD_3990_ERP_EXAMINE  * * DESCRIPTION *   Checks only for fatal/no/recover error.  *   A detailed examination of the sense data is done later outside *   the interrupt handler. * *   The logic is based on the 'IBM 3990 Storage Control  Reference' manual *   'Chapter 7. Error Recovery Procedures'. * * RETURN VALUES *   dasd_era_none	no error  *   dasd_era_fatal	for all fatal (unrecoverable errors) *   dasd_era_recover	for all others. */dasd_era_tdasd_3990_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb){	char *sense = irb->ecw;	dasd_era_t era = dasd_era_recover;	struct dasd_device *device = cqr->device;	/* check for successful execution first */	if (irb->scsw.cstat == 0x00 &&	    irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))		return dasd_era_none;	/* distinguish between 24 and 32 byte sense data */	if (sense[27] & DASD_SENSE_BIT_0) {		era = dasd_3990_erp_examine_24(cqr, sense);	} else {		era = dasd_3990_erp_examine_32(cqr, sense);	}	/* log the erp chain if fatal error occurred */	if ((era == dasd_era_fatal) && (device->state >= DASD_STATE_READY)) {		dasd_log_sense(cqr, irb);		dasd_log_ccw(cqr, 0, irb->scsw.cpa);	}	return era;}				/* END dasd_3990_erp_examine *//* *****************************************************************************  * SECTION ERP HANDLING *****************************************************************************  *//* *****************************************************************************  * 24 and 32 byte sense ERP functions *****************************************************************************  *//* * DASD_3990_ERP_CLEANUP  * * DESCRIPTION *   Removes the already build but not necessary ERP request and sets *   the status of the original cqr / erp to the given (final) status * *  PARAMETER *   erp		request to be blocked *   final_status	either DASD_CQR_DONE or DASD_CQR_FAILED  * * RETURN VALUES *   cqr		original cqr		    */static struct dasd_ccw_req *dasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status){	struct dasd_ccw_req *cqr = erp->refers;	dasd_free_erp_request(erp, erp->device);	cqr->status = final_status;	return cqr;}				/* end dasd_3990_erp_cleanup *//* * DASD_3990_ERP_BLOCK_QUEUE  * * DESCRIPTION *   Block the given device request queue to prevent from further *   processing until the started timer has expired or an related *   interrupt was received. */static voiddasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires){	struct dasd_device *device = erp->device;	DEV_MESSAGE(KERN_INFO, device,		    "blocking request queue for %is", expires/HZ);	device->stopped |= DASD_STOPPED_PENDING;	erp->status = DASD_CQR_QUEUED;	dasd_set_timer(device, expires);}/* * 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 */static struct dasd_ccw_req *dasd_3990_erp_int_req(struct dasd_ccw_req * erp){	struct dasd_device *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 */		DEV_MESSAGE(KERN_ERR, device, "%s",			    "is offline or not installed - "			    "INTERVENTION REQUIRED!!");		dasd_3990_erp_block_queue(erp, 60*HZ);	}	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 */static voiddasd_3990_erp_alternate_path(struct dasd_ccw_req * erp){	struct dasd_device *device = erp->device;	__u8 opm;	/* try alternate valid path */	opm = ccw_device_get_path_mask(device->cdev);	//FIXME: start with get_opm ?	if (erp->lpm == 0)		erp->lpm = LPM_ANYPATH & ~(erp->irb.esw.esw0.sublog.lpum);	else		erp->lpm &= ~(erp->irb.esw.esw0.sublog.lpum);	if ((erp->lpm & opm) != 0x00) {		DEV_MESSAGE(KERN_DEBUG, device,			    "try alternate lpm=%x (lpum=%x / opm=%x)",			    erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm);		/* reset status to queued to handle the request again... */		if (erp->status > DASD_CQR_QUEUED)			erp->status = DASD_CQR_QUEUED;		erp->retries = 1;	} else {		DEV_MESSAGE(KERN_ERR, device,			    "No alternate channel path left (lpum=%x / "			    "opm=%x) -> permanent error",			    erp->irb.esw.esw0.sublog.lpum, opm);		/* post request with permanent error */		if (erp->status > DASD_CQR_QUEUED)			erp->status = DASD_CQR_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  * */static struct dasd_ccw_req *dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier){	struct dasd_device *device = erp->device;	struct DCTL_data *DCTL_data;	struct ccw1 *ccw;	struct dasd_ccw_req *dctl_cqr;	dctl_cqr = dasd_alloc_erp_request((char *) &erp->magic, 1,					  sizeof (struct DCTL_data),					  erp->device);	if (IS_ERR(dctl_cqr)) {		DEV_MESSAGE(KERN_ERR, device, "%s",			    "Unable to allocate DCTL-CQR");		erp->status = DASD_CQR_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 (struct ccw1));	ccw->cmd_code = CCW_CMD_DCTL;	ccw->count = 4;	ccw->cda = (__u32)(addr_t) DCTL_data;	dctl_cqr->function = dasd_3990_erp_DCTL;	dctl_cqr->refers = erp;	dctl_cqr->device = erp->device;	dctl_cqr->magic = erp->magic;	dctl_cqr->expires = 5 * 60 * HZ;	dctl_cqr->retries = 2;	dctl_cqr->buildclk = get_clock();	dctl_cqr->status = DASD_CQR_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 * */static struct dasd_ccw_req *dasd_3990_erp_action_1(struct dasd_ccw_req * 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 * */static struct dasd_ccw_req *dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense){	struct dasd_device *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) {		DEV_MESSAGE(KERN_INFO, device, "%s",			    "dasd_3990_erp_action_4: first time retry");		erp->retries = 256;		erp->function = dasd_3990_erp_action_4;	} else {		if (sense[25] == 0x1D) {	/* state change pending */			DEV_MESSAGE(KERN_INFO, device, 				    "waiting for state change pending "				    "interrupt, %d retries left",				    erp->retries);						dasd_3990_erp_block_queue(erp, 30*HZ);                } else if (sense[25] == 0x1E) {	/* busy */			DEV_MESSAGE(KERN_INFO, device,				    "busy - redriving request later, "				    "%d retries left",				    erp->retries);                        dasd_3990_erp_block_queue(erp, HZ);		} else {			/* no state change pending - retry */			DEV_MESSAGE (KERN_INFO, device, 				     "redriving request immediately, "				     "%d retries left", 				     erp->retries);			erp->status = DASD_CQR_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 * */static struct dasd_ccw_req *dasd_3990_erp_action_5(struct dasd_ccw_req * 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'.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -