2005-04-17 02:20:36 +04:00
/*
* Author ( s ) . . . . . . : Holger Smolinski < Holger . Smolinski @ de . ibm . com >
* Horst Hummel < Horst . Hummel @ de . ibm . com >
* Carsten Otte < Cotte @ de . ibm . com >
* Martin Schwidefsky < schwidefsky @ de . ibm . com >
* Bugreports . to . . : < Linux390 @ de . ibm . com >
2012-07-20 13:15:04 +04:00
* Copyright IBM Corp . 1999 , 2001
2005-04-17 02:20:36 +04:00
*
*/
2009-03-26 17:23:49 +03:00
# define KMSG_COMPONENT "dasd"
2005-04-17 02:20:36 +04:00
# include <linux/ctype.h>
# include <linux/init.h>
# include <asm/debug.h>
# include <asm/ebcdic.h>
# include <asm/uaccess.h>
/* This is ugly... */
# define PRINTK_HEADER "dasd_erp:"
# include "dasd_int.h"
struct dasd_ccw_req *
dasd_alloc_erp_request ( char * magic , int cplength , int datasize ,
struct dasd_device * device )
{
unsigned long flags ;
struct dasd_ccw_req * cqr ;
char * data ;
int size ;
/* Sanity checks */
2006-04-01 03:27:08 +04:00
BUG_ON ( magic = = NULL | | datasize > PAGE_SIZE | |
( cplength * sizeof ( struct ccw1 ) ) > PAGE_SIZE ) ;
2005-04-17 02:20:36 +04:00
size = ( sizeof ( struct dasd_ccw_req ) + 7L ) & - 8L ;
if ( cplength > 0 )
size + = cplength * sizeof ( struct ccw1 ) ;
if ( datasize > 0 )
size + = datasize ;
spin_lock_irqsave ( & device - > mem_lock , flags ) ;
cqr = ( struct dasd_ccw_req * )
dasd_alloc_chunk ( & device - > erp_chunks , size ) ;
spin_unlock_irqrestore ( & device - > mem_lock , flags ) ;
if ( cqr = = NULL )
return ERR_PTR ( - ENOMEM ) ;
memset ( cqr , 0 , sizeof ( struct dasd_ccw_req ) ) ;
2008-01-26 16:11:23 +03:00
INIT_LIST_HEAD ( & cqr - > devlist ) ;
INIT_LIST_HEAD ( & cqr - > blocklist ) ;
2005-04-17 02:20:36 +04:00
data = ( char * ) cqr + ( ( sizeof ( struct dasd_ccw_req ) + 7L ) & - 8L ) ;
cqr - > cpaddr = NULL ;
if ( cplength > 0 ) {
cqr - > cpaddr = ( struct ccw1 * ) data ;
data + = cplength * sizeof ( struct ccw1 ) ;
memset ( cqr - > cpaddr , 0 , cplength * sizeof ( struct ccw1 ) ) ;
}
cqr - > data = NULL ;
if ( datasize > 0 ) {
cqr - > data = data ;
memset ( cqr - > data , 0 , datasize ) ;
}
strncpy ( ( char * ) & cqr - > magic , magic , 4 ) ;
ASCEBC ( ( char * ) & cqr - > magic , 4 ) ;
set_bit ( DASD_CQR_FLAGS_USE_ERP , & cqr - > flags ) ;
dasd_get_device ( device ) ;
return cqr ;
}
void
2008-01-26 16:11:23 +03:00
dasd_free_erp_request ( struct dasd_ccw_req * cqr , struct dasd_device * device )
2005-04-17 02:20:36 +04:00
{
unsigned long flags ;
spin_lock_irqsave ( & device - > mem_lock , flags ) ;
dasd_free_chunk ( & device - > erp_chunks , cqr ) ;
spin_unlock_irqrestore ( & device - > mem_lock , flags ) ;
atomic_dec ( & device - > ref_count ) ;
}
/*
* dasd_default_erp_action just retries the current cqr
*/
struct dasd_ccw_req *
2008-01-26 16:11:23 +03:00
dasd_default_erp_action ( struct dasd_ccw_req * cqr )
2005-04-17 02:20:36 +04:00
{
struct dasd_device * device ;
2008-01-26 16:11:23 +03:00
device = cqr - > startdev ;
2005-04-17 02:20:36 +04:00
/* just retry - there is nothing to save ... I got no sense data.... */
if ( cqr - > retries > 0 ) {
2009-03-26 17:23:49 +03:00
DBF_DEV_EVENT ( DBF_DEBUG , device ,
2005-04-17 02:20:36 +04:00
" default ERP called (%i retries left) " ,
cqr - > retries ) ;
2011-01-05 14:48:03 +03:00
if ( ! test_bit ( DASD_CQR_VERIFY_PATH , & cqr - > flags ) )
cqr - > lpm = device - > path_data . opm ;
2008-01-26 16:11:23 +03:00
cqr - > status = DASD_CQR_FILLED ;
2005-04-17 02:20:36 +04:00
} else {
2009-09-11 12:28:30 +04:00
pr_err ( " %s: default ERP has run out of retries and failed \n " ,
dev_name ( & device - > cdev - > dev ) ) ;
2005-04-17 02:20:36 +04:00
cqr - > status = DASD_CQR_FAILED ;
2013-01-30 12:49:40 +04:00
cqr - > stopclk = get_tod_clock ( ) ;
2005-04-17 02:20:36 +04:00
}
return cqr ;
} /* end dasd_default_erp_action */
/*
* DESCRIPTION
* Frees all ERPs of the current ERP Chain and set the status
* of the original CQR either to DASD_CQR_DONE if ERP was successful
* or to DASD_CQR_FAILED if ERP was NOT successful .
* NOTE : This function is only called if no discipline postaction
* is available
*
* PARAMETER
* erp current erp_head
*
* RETURN VALUES
* cqr pointer to the original CQR
*/
2008-01-26 16:11:23 +03:00
struct dasd_ccw_req * dasd_default_erp_postaction ( struct dasd_ccw_req * cqr )
2005-04-17 02:20:36 +04:00
{
int success ;
2006-04-01 03:27:08 +04:00
BUG_ON ( cqr - > refers = = NULL | | cqr - > function = = NULL ) ;
2005-04-17 02:20:36 +04:00
success = cqr - > status = = DASD_CQR_DONE ;
/* free all ERPs - but NOT the original cqr */
while ( cqr - > refers ! = NULL ) {
struct dasd_ccw_req * refers ;
refers = cqr - > refers ;
2008-01-26 16:11:23 +03:00
/* remove the request from the block queue */
list_del ( & cqr - > blocklist ) ;
2005-04-17 02:20:36 +04:00
/* free the finished erp request */
2008-01-26 16:11:23 +03:00
dasd_free_erp_request ( cqr , cqr - > memdev ) ;
2005-04-17 02:20:36 +04:00
cqr = refers ;
}
/* set corresponding status to original cqr */
if ( success )
cqr - > status = DASD_CQR_DONE ;
else {
cqr - > status = DASD_CQR_FAILED ;
2013-01-30 12:49:40 +04:00
cqr - > stopclk = get_tod_clock ( ) ;
2005-04-17 02:20:36 +04:00
}
return cqr ;
} /* end default_erp_postaction */
void
dasd_log_sense ( struct dasd_ccw_req * cqr , struct irb * irb )
{
struct dasd_device * device ;
2008-01-26 16:11:23 +03:00
device = cqr - > startdev ;
2005-04-17 02:20:36 +04:00
/* dump sense data */
if ( device - > discipline & & device - > discipline - > dump_sense )
device - > discipline - > dump_sense ( device , cqr , irb ) ;
}
2009-03-26 17:23:49 +03:00
void
dasd_log_sense_dbf ( struct dasd_ccw_req * cqr , struct irb * irb )
{
struct dasd_device * device ;
device = cqr - > startdev ;
/* dump sense data to s390 debugfeature*/
if ( device - > discipline & & device - > discipline - > dump_sense_dbf )
2009-07-07 18:37:06 +04:00
device - > discipline - > dump_sense_dbf ( device , irb , " log " ) ;
2009-03-26 17:23:49 +03:00
}
EXPORT_SYMBOL ( dasd_log_sense_dbf ) ;
2005-04-17 02:20:36 +04:00
EXPORT_SYMBOL ( dasd_default_erp_action ) ;
EXPORT_SYMBOL ( dasd_default_erp_postaction ) ;
EXPORT_SYMBOL ( dasd_alloc_erp_request ) ;
EXPORT_SYMBOL ( dasd_free_erp_request ) ;
EXPORT_SYMBOL ( dasd_log_sense ) ;
2009-03-26 17:23:49 +03:00