📄 dasd_3990_erp.c
字号:
/* * 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 * * History of changes: * 05/14/01 fixed PL030160GTO (BUG() in erp_action_5) */#include <asm/ccwcache.h>#include <asm/idals.h>#include <asm/s390io.h>#include <linux/timer.h>#include "dasd_int.h"#include "dasd_eckd.h"#include "dasd_3990_erp.h"#ifdef PRINTK_HEADER#undef PRINTK_HEADER#endif /* PRINTK_HEADER */#define PRINTK_HEADER "dasd_erp(3990): "/* ***************************************************************************** * SECTION DEBUG ROUTINES ***************************************************************************** */voidlog_erp_chain (ccw_req_t *cqr, int caller, __u32 cpa){ ccw_req_t *loop_cqr = cqr; dasd_device_t *device = cqr->device; int i; char *nl, *end_cqr, *begin, *end; /* dump sense data */ if (device->discipline && device->discipline->dump_sense ) { device->discipline->dump_sense (device, cqr); } /* log the channel program */ while (loop_cqr != NULL) { DASD_MESSAGE (KERN_ERR, device, "(%s) ERP chain report for req: %p", caller == 0 ? "EXAMINE" : "ACTION", loop_cqr); nl = (char *) loop_cqr; end_cqr = nl + sizeof (ccw_req_t); while (nl < end_cqr) { DASD_MESSAGE (KERN_ERR, device, "%p: %02x%02x%02x%02x %02x%02x%02x%02x " "%02x%02x%02x%02x %02x%02x%02x%02x", nl, nl[0], nl[1], nl[2], nl[3], nl[4], nl[5], nl[6], nl[7], nl[8], nl[9], nl[10], nl[11], nl[12], nl[13], nl[14], nl[15]); nl +=16; } nl = (char *) loop_cqr->cpaddr; if (loop_cqr->cplength > 40) { /* log only parts of the CP */ DASD_MESSAGE (KERN_ERR, device, "%s", "Start of channel program:"); for (i = 0; i < 20; i += 2) { DASD_MESSAGE (KERN_ERR, device, "%p: %02x%02x%02x%02x %02x%02x%02x%02x " "%02x%02x%02x%02x %02x%02x%02x%02x", nl, nl[0], nl[1], nl[2], nl[3], nl[4], nl[5], nl[6], nl[7], nl[8], nl[9], nl[10], nl[11], nl[12], nl[13], nl[14], nl[15]); nl += 16; } DASD_MESSAGE (KERN_ERR, device, "%s", "End of channel program:"); nl = (char *) loop_cqr->cpaddr; nl += ((loop_cqr->cplength - 10) * 8); for (i = 0; i < 20; i += 2) { DASD_MESSAGE (KERN_ERR, device, "%p: %02x%02x%02x%02x %02x%02x%02x%02x " "%02x%02x%02x%02x %02x%02x%02x%02x", nl, nl[0], nl[1], nl[2], nl[3], nl[4], nl[5], nl[6], nl[7], nl[8], nl[9], nl[10], nl[11], nl[12], nl[13], nl[14], nl[15]); nl += 16; } } else { /* log the whole CP */ DASD_MESSAGE (KERN_ERR, device, "%s", "Channel program (complete):"); for (i = 0; i < (loop_cqr->cplength + 4); i += 2) { DASD_MESSAGE (KERN_ERR, device, "%p: %02x%02x%02x%02x %02x%02x%02x%02x " "%02x%02x%02x%02x %02x%02x%02x%02x", nl, nl[0], nl[1], nl[2], nl[3], nl[4], nl[5], nl[6], nl[7], nl[8], nl[9], nl[10], nl[11], nl[12], nl[13], nl[14], nl[15]); nl += 16; } } /* log bytes arround failed CCW if not already done */ begin = (char *) loop_cqr->cpaddr; end = begin + ((loop_cqr->cplength+4) * 8); nl = (void *)(long)cpa; if (loop_cqr == cqr) { /* log only once */ /* if not whole CP logged OR CCW outside logged CP */ if ((loop_cqr->cplength > 40) || ((nl < begin ) && (nl > end ) ) ) { nl -= 10*8; /* start some bytes before */ DASD_MESSAGE (KERN_ERR, device, "Failed CCW (%p) (area):", (void *)(long)cpa); for (i = 0; i < 20; i += 2) { DASD_MESSAGE (KERN_ERR, device, "%p: %02x%02x%02x%02x %02x%02x%02x%02x " "%02x%02x%02x%02x %02x%02x%02x%02x", nl, nl[0], nl[1], nl[2], nl[3], nl[4], nl[5], nl[6], nl[7], nl[8], nl[9], nl[10], nl[11], nl[12], nl[13], nl[14], nl[15]); nl += 16; } } else { DASD_MESSAGE (KERN_ERR, device, "Failed CCW (%p) already logged", (void *)(long)cpa); } } loop_cqr = loop_cqr->refers; } } /* end log_erp_chain *//* ***************************************************************************** * 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. */dasd_era_tdasd_3990_erp_examine_24 (ccw_req_t *cqr, char *sense){ dasd_device_t *device = cqr->device; /* check for 'Command Reject' */ if (( sense[0] & SNS0_CMD_REJECT ) && (!(sense[2] & SNS2_ENV_DATA_PRESENT)) ) { DASD_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)) ) { DASD_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) { DASD_MESSAGE (KERN_ERR, device, "EXAMINE 24: No Record Found detected %s", cqr == device->init_cqr ? " " : "- 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. */dasd_era_tdasd_3990_erp_examine_32 (ccw_req_t *cqr, char *sense){ dasd_device_t *device = cqr->device; switch (sense[25]) { case 0x00: return dasd_era_none; case 0x01: DASD_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 (ccw_req_t *cqr, devstat_t *stat){ char *sense = stat->ii.sense.data; dasd_era_t era = dasd_era_recover; dasd_device_t *device = cqr->device; /* check for successful execution first */ if (stat->cstat == 0x00 && stat->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 ) && (cqr != device->init_cqr) ){ log_erp_chain (cqr, 0, stat->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 neccessary 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 CQR_STATUS_DONE or CQR_STATUS_FAILED * * RETURN VALUES * cqr original cqr */ccw_req_t *dasd_3990_erp_cleanup (ccw_req_t *erp, char final_status){ ccw_req_t *cqr = erp->refers; dasd_free_request (erp, erp->device); check_then_set (&cqr->status, CQR_STATUS_ERROR, 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. * * PARAMETER * erp request to be blocked * expires time to wait until restart (in seconds) *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -