2007-09-07 09:15:31 +02:00
/*
2008-06-10 18:20:58 +02:00
* zfcp device driver
2005-04-16 15:20:36 -07:00
*
2008-06-10 18:20:58 +02:00
* Error Recovery Procedures ( ERP ) .
2007-09-07 09:15:31 +02:00
*
2010-02-17 11:18:56 +01:00
* Copyright IBM Corporation 2002 , 2010
2005-04-16 15:20:36 -07:00
*/
2008-12-25 13:39:53 +01:00
# define KMSG_COMPONENT "zfcp"
# define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
2009-08-18 15:43:25 +02:00
# include <linux/kthread.h>
2005-04-16 15:20:36 -07:00
# include "zfcp_ext.h"
2010-02-17 11:18:50 +01:00
# include "zfcp_reqlist.h"
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
# define ZFCP_MAX_ERPS 3
enum zfcp_erp_act_flags {
ZFCP_STATUS_ERP_TIMEDOUT = 0x10000000 ,
ZFCP_STATUS_ERP_CLOSE_ONLY = 0x01000000 ,
ZFCP_STATUS_ERP_DISMISSING = 0x00100000 ,
ZFCP_STATUS_ERP_DISMISSED = 0x00200000 ,
ZFCP_STATUS_ERP_LOWMEM = 0x00400000 ,
2010-09-08 14:39:54 +02:00
ZFCP_STATUS_ERP_NO_REF = 0x00800000 ,
2008-07-02 10:56:40 +02:00
} ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
enum zfcp_erp_steps {
ZFCP_ERP_STEP_UNINITIALIZED = 0x0000 ,
ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001 ,
ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010 ,
ZFCP_ERP_STEP_PORT_CLOSING = 0x0100 ,
ZFCP_ERP_STEP_PORT_OPENING = 0x0800 ,
2010-09-08 14:39:55 +02:00
ZFCP_ERP_STEP_LUN_CLOSING = 0x1000 ,
ZFCP_ERP_STEP_LUN_OPENING = 0x2000 ,
2008-07-02 10:56:40 +02:00
} ;
enum zfcp_erp_act_type {
2010-09-08 14:39:55 +02:00
ZFCP_ERP_ACTION_REOPEN_LUN = 1 ,
2008-07-02 10:56:40 +02:00
ZFCP_ERP_ACTION_REOPEN_PORT = 2 ,
ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3 ,
ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4 ,
} ;
enum zfcp_erp_act_state {
ZFCP_ERP_ACTION_RUNNING = 1 ,
ZFCP_ERP_ACTION_READY = 2 ,
} ;
enum zfcp_erp_act_result {
ZFCP_ERP_SUCCEEDED = 0 ,
ZFCP_ERP_FAILED = 1 ,
ZFCP_ERP_CONTINUES = 2 ,
ZFCP_ERP_EXIT = 3 ,
ZFCP_ERP_DISMISSED = 4 ,
ZFCP_ERP_NOMEM = 5 ,
} ;
static void zfcp_erp_adapter_block ( struct zfcp_adapter * adapter , int mask )
2005-04-16 15:20:36 -07:00
{
2010-09-08 14:40:01 +02:00
zfcp_erp_clear_adapter_status ( adapter ,
ZFCP_STATUS_COMMON_UNBLOCKED | mask ) ;
2006-09-18 22:29:56 +02:00
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
static int zfcp_erp_action_exists ( struct zfcp_erp_action * act )
2006-09-18 22:29:56 +02:00
{
2008-07-02 10:56:40 +02:00
struct zfcp_erp_action * curr_act ;
list_for_each_entry ( curr_act , & act - > adapter - > erp_running_head , list )
if ( act = = curr_act )
return ZFCP_ERP_ACTION_RUNNING ;
return 0 ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static void zfcp_erp_action_ready ( struct zfcp_erp_action * act )
2006-09-18 22:29:56 +02:00
{
2008-07-02 10:56:40 +02:00
struct zfcp_adapter * adapter = act - > adapter ;
list_move ( & act - > list , & act - > adapter - > erp_ready_head ) ;
2010-12-02 15:16:12 +01:00
zfcp_dbf_rec_run ( " erardy1 " , act ) ;
2009-08-18 15:43:25 +02:00
wake_up ( & adapter - > erp_ready_wq ) ;
2010-12-02 15:16:12 +01:00
zfcp_dbf_rec_run ( " erardy2 " , act ) ;
2006-09-18 22:29:56 +02:00
}
2008-07-02 10:56:40 +02:00
static void zfcp_erp_action_dismiss ( struct zfcp_erp_action * act )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
act - > status | = ZFCP_STATUS_ERP_DISMISSED ;
if ( zfcp_erp_action_exists ( act ) = = ZFCP_ERP_ACTION_RUNNING )
zfcp_erp_action_ready ( act ) ;
}
2005-04-16 15:20:36 -07:00
2010-09-08 14:39:55 +02:00
static void zfcp_erp_action_dismiss_lun ( struct scsi_device * sdev )
2008-07-02 10:56:40 +02:00
{
2010-09-08 14:39:55 +02:00
struct zfcp_scsi_dev * zfcp_sdev = sdev_to_zfcp ( sdev ) ;
if ( atomic_read ( & zfcp_sdev - > status ) & ZFCP_STATUS_COMMON_ERP_INUSE )
zfcp_erp_action_dismiss ( & zfcp_sdev - > erp_action ) ;
2008-07-02 10:56:40 +02:00
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
static void zfcp_erp_action_dismiss_port ( struct zfcp_port * port )
{
2010-09-08 14:39:55 +02:00
struct scsi_device * sdev ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
if ( atomic_read ( & port - > status ) & ZFCP_STATUS_COMMON_ERP_INUSE )
zfcp_erp_action_dismiss ( & port - > erp_action ) ;
2010-09-08 14:39:55 +02:00
else
shost_for_each_device ( sdev , port - > adapter - > scsi_host )
if ( sdev_to_zfcp ( sdev ) - > port = = port )
zfcp_erp_action_dismiss_lun ( sdev ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static void zfcp_erp_action_dismiss_adapter ( struct zfcp_adapter * adapter )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
struct zfcp_port * port ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
if ( atomic_read ( & adapter - > status ) & ZFCP_STATUS_COMMON_ERP_INUSE )
zfcp_erp_action_dismiss ( & adapter - > erp_action ) ;
2009-11-24 16:53:58 +01:00
else {
read_lock ( & adapter - > port_list_lock ) ;
list_for_each_entry ( port , & adapter - > port_list , list )
2008-07-02 10:56:40 +02:00
zfcp_erp_action_dismiss_port ( port ) ;
2009-11-24 16:53:58 +01:00
read_unlock ( & adapter - > port_list_lock ) ;
}
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_required_act ( int want , struct zfcp_adapter * adapter ,
struct zfcp_port * port ,
2010-09-08 14:39:55 +02:00
struct scsi_device * sdev )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
int need = want ;
2010-09-08 14:39:55 +02:00
int l_status , p_status , a_status ;
struct zfcp_scsi_dev * zfcp_sdev ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
switch ( want ) {
2010-09-08 14:39:55 +02:00
case ZFCP_ERP_ACTION_REOPEN_LUN :
zfcp_sdev = sdev_to_zfcp ( sdev ) ;
l_status = atomic_read ( & zfcp_sdev - > status ) ;
if ( l_status & ZFCP_STATUS_COMMON_ERP_INUSE )
2008-07-02 10:56:40 +02:00
return 0 ;
p_status = atomic_read ( & port - > status ) ;
if ( ! ( p_status & ZFCP_STATUS_COMMON_RUNNING ) | |
p_status & ZFCP_STATUS_COMMON_ERP_FAILED )
return 0 ;
if ( ! ( p_status & ZFCP_STATUS_COMMON_UNBLOCKED ) )
need = ZFCP_ERP_ACTION_REOPEN_PORT ;
/* fall through */
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED :
2010-07-08 09:53:06 +02:00
p_status = atomic_read ( & port - > status ) ;
if ( ! ( p_status & ZFCP_STATUS_COMMON_OPEN ) )
need = ZFCP_ERP_ACTION_REOPEN_PORT ;
/* fall through */
case ZFCP_ERP_ACTION_REOPEN_PORT :
2008-07-02 10:56:40 +02:00
p_status = atomic_read ( & port - > status ) ;
if ( p_status & ZFCP_STATUS_COMMON_ERP_INUSE )
return 0 ;
a_status = atomic_read ( & adapter - > status ) ;
if ( ! ( a_status & ZFCP_STATUS_COMMON_RUNNING ) | |
a_status & ZFCP_STATUS_COMMON_ERP_FAILED )
return 0 ;
2010-11-17 14:23:42 +01:00
if ( p_status & ZFCP_STATUS_COMMON_NOESC )
return need ;
2008-07-02 10:56:40 +02:00
if ( ! ( a_status & ZFCP_STATUS_COMMON_UNBLOCKED ) )
need = ZFCP_ERP_ACTION_REOPEN_ADAPTER ;
/* fall through */
case ZFCP_ERP_ACTION_REOPEN_ADAPTER :
a_status = atomic_read ( & adapter - > status ) ;
if ( a_status & ZFCP_STATUS_COMMON_ERP_INUSE )
return 0 ;
2009-08-18 15:43:27 +02:00
if ( ! ( a_status & ZFCP_STATUS_COMMON_RUNNING ) & &
! ( a_status & ZFCP_STATUS_COMMON_OPEN ) )
return 0 ; /* shutdown requested for closed adapter */
2008-07-02 10:56:40 +02:00
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
return need ;
2005-04-16 15:20:36 -07:00
}
2010-09-08 14:39:54 +02:00
static struct zfcp_erp_action * zfcp_erp_setup_act ( int need , u32 act_status ,
2008-07-02 10:56:40 +02:00
struct zfcp_adapter * adapter ,
struct zfcp_port * port ,
2010-09-08 14:39:55 +02:00
struct scsi_device * sdev )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
struct zfcp_erp_action * erp_action ;
2010-09-08 14:39:55 +02:00
struct zfcp_scsi_dev * zfcp_sdev ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
switch ( need ) {
2010-09-08 14:39:55 +02:00
case ZFCP_ERP_ACTION_REOPEN_LUN :
zfcp_sdev = sdev_to_zfcp ( sdev ) ;
2010-09-08 14:39:54 +02:00
if ( ! ( act_status & ZFCP_STATUS_ERP_NO_REF ) )
2010-09-08 14:39:55 +02:00
if ( scsi_device_get ( sdev ) )
2010-09-08 14:39:54 +02:00
return NULL ;
2010-09-08 14:39:55 +02:00
atomic_set_mask ( ZFCP_STATUS_COMMON_ERP_INUSE ,
& zfcp_sdev - > status ) ;
erp_action = & zfcp_sdev - > erp_action ;
2010-11-17 14:23:43 +01:00
memset ( erp_action , 0 , sizeof ( struct zfcp_erp_action ) ) ;
erp_action - > port = port ;
erp_action - > sdev = sdev ;
2010-09-08 14:39:55 +02:00
if ( ! ( atomic_read ( & zfcp_sdev - > status ) &
ZFCP_STATUS_COMMON_RUNNING ) )
2010-09-08 14:39:54 +02:00
act_status | = ZFCP_STATUS_ERP_CLOSE_ONLY ;
2008-07-02 10:56:40 +02:00
break ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
case ZFCP_ERP_ACTION_REOPEN_PORT :
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED :
2010-02-17 11:18:56 +01:00
if ( ! get_device ( & port - > dev ) )
2009-11-24 16:54:05 +01:00
return NULL ;
2008-07-02 10:56:40 +02:00
zfcp_erp_action_dismiss_port ( port ) ;
atomic_set_mask ( ZFCP_STATUS_COMMON_ERP_INUSE , & port - > status ) ;
erp_action = & port - > erp_action ;
2010-11-17 14:23:43 +01:00
memset ( erp_action , 0 , sizeof ( struct zfcp_erp_action ) ) ;
erp_action - > port = port ;
2008-07-02 10:56:40 +02:00
if ( ! ( atomic_read ( & port - > status ) & ZFCP_STATUS_COMMON_RUNNING ) )
2010-09-08 14:39:54 +02:00
act_status | = ZFCP_STATUS_ERP_CLOSE_ONLY ;
2008-07-02 10:56:40 +02:00
break ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
case ZFCP_ERP_ACTION_REOPEN_ADAPTER :
2009-11-24 16:53:59 +01:00
kref_get ( & adapter - > ref ) ;
2008-07-02 10:56:40 +02:00
zfcp_erp_action_dismiss_adapter ( adapter ) ;
atomic_set_mask ( ZFCP_STATUS_COMMON_ERP_INUSE , & adapter - > status ) ;
erp_action = & adapter - > erp_action ;
2010-11-17 14:23:43 +01:00
memset ( erp_action , 0 , sizeof ( struct zfcp_erp_action ) ) ;
2008-07-02 10:56:40 +02:00
if ( ! ( atomic_read ( & adapter - > status ) &
ZFCP_STATUS_COMMON_RUNNING ) )
2010-09-08 14:39:54 +02:00
act_status | = ZFCP_STATUS_ERP_CLOSE_ONLY ;
2008-07-02 10:56:40 +02:00
break ;
default :
return NULL ;
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
erp_action - > adapter = adapter ;
erp_action - > action = need ;
2010-09-08 14:39:54 +02:00
erp_action - > status = act_status ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
return erp_action ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_action_enqueue ( int want , struct zfcp_adapter * adapter ,
struct zfcp_port * port ,
2010-09-08 14:39:55 +02:00
struct scsi_device * sdev ,
2010-12-02 15:16:16 +01:00
char * id , u32 act_status )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
int retval = 1 , need ;
2010-12-02 15:16:12 +01:00
struct zfcp_erp_action * act ;
2005-04-16 15:20:36 -07:00
2009-08-18 15:43:25 +02:00
if ( ! adapter - > erp_thread )
2008-07-02 10:56:40 +02:00
return - EIO ;
2005-04-16 15:20:36 -07:00
2010-09-08 14:39:55 +02:00
need = zfcp_erp_required_act ( want , adapter , port , sdev ) ;
2008-07-02 10:56:40 +02:00
if ( ! need )
2005-04-16 15:20:36 -07:00
goto out ;
2010-09-08 14:39:55 +02:00
act = zfcp_erp_setup_act ( need , act_status , adapter , port , sdev ) ;
2008-07-02 10:56:40 +02:00
if ( ! act )
goto out ;
2010-09-08 14:39:54 +02:00
atomic_set_mask ( ZFCP_STATUS_ADAPTER_ERP_PENDING , & adapter - > status ) ;
2008-07-02 10:56:40 +02:00
+ + adapter - > erp_total_count ;
list_add_tail ( & act - > list , & adapter - > erp_ready_head ) ;
2009-08-18 15:43:25 +02:00
wake_up ( & adapter - > erp_ready_wq ) ;
2008-07-02 10:56:40 +02:00
retval = 0 ;
2005-04-16 15:20:36 -07:00
out :
2010-12-02 15:16:12 +01:00
zfcp_dbf_rec_trig ( id , adapter , port , sdev , want , need ) ;
2005-04-16 15:20:36 -07:00
return retval ;
}
2008-07-02 10:56:40 +02:00
static int _zfcp_erp_adapter_reopen ( struct zfcp_adapter * adapter ,
2010-12-02 15:16:16 +01:00
int clear_mask , char * id )
2008-07-02 10:56:40 +02:00
{
zfcp_erp_adapter_block ( adapter , clear_mask ) ;
2009-03-02 13:09:08 +01:00
zfcp_scsi_schedule_rports_block ( adapter ) ;
2008-07-02 10:56:40 +02:00
/* ensure propagation of failed status to new devices */
if ( atomic_read ( & adapter - > status ) & ZFCP_STATUS_COMMON_ERP_FAILED ) {
2010-09-08 14:40:01 +02:00
zfcp_erp_set_adapter_status ( adapter ,
ZFCP_STATUS_COMMON_ERP_FAILED ) ;
2008-07-02 10:56:40 +02:00
return - EIO ;
}
return zfcp_erp_action_enqueue ( ZFCP_ERP_ACTION_REOPEN_ADAPTER ,
2010-12-02 15:16:16 +01:00
adapter , NULL , NULL , id , 0 ) ;
2008-07-02 10:56:40 +02:00
}
/**
* zfcp_erp_adapter_reopen - Reopen adapter .
* @ adapter : Adapter to reopen .
* @ clear : Status flags to clear .
* @ id : Id for debug trace event .
2005-04-16 15:20:36 -07:00
*/
2010-12-02 15:16:16 +01:00
void zfcp_erp_adapter_reopen ( struct zfcp_adapter * adapter , int clear , char * id )
2005-04-16 15:20:36 -07:00
{
unsigned long flags ;
2009-11-24 16:53:58 +01:00
zfcp_erp_adapter_block ( adapter , clear ) ;
zfcp_scsi_schedule_rports_block ( adapter ) ;
write_lock_irqsave ( & adapter - > erp_lock , flags ) ;
if ( atomic_read ( & adapter - > status ) & ZFCP_STATUS_COMMON_ERP_FAILED )
2010-09-08 14:40:01 +02:00
zfcp_erp_set_adapter_status ( adapter ,
ZFCP_STATUS_COMMON_ERP_FAILED ) ;
2009-11-24 16:53:58 +01:00
else
zfcp_erp_action_enqueue ( ZFCP_ERP_ACTION_REOPEN_ADAPTER , adapter ,
2010-12-02 15:16:16 +01:00
NULL , NULL , id , 0 ) ;
2009-11-24 16:53:58 +01:00
write_unlock_irqrestore ( & adapter - > erp_lock , flags ) ;
2008-07-02 10:56:40 +02:00
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
/**
* zfcp_erp_adapter_shutdown - Shutdown adapter .
* @ adapter : Adapter to shut down .
* @ clear : Status flags to clear .
* @ id : Id for debug trace event .
*/
void zfcp_erp_adapter_shutdown ( struct zfcp_adapter * adapter , int clear ,
2010-12-02 15:16:16 +01:00
char * id )
2008-07-02 10:56:40 +02:00
{
int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED ;
2010-12-02 15:16:16 +01:00
zfcp_erp_adapter_reopen ( adapter , clear | flags , id ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
/**
* zfcp_erp_port_shutdown - Shutdown port
* @ port : Port to shut down .
* @ clear : Status flags to clear .
* @ id : Id for debug trace event .
2005-04-16 15:20:36 -07:00
*/
2010-12-02 15:16:16 +01:00
void zfcp_erp_port_shutdown ( struct zfcp_port * port , int clear , char * id )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED ;
2010-12-02 15:16:16 +01:00
zfcp_erp_port_reopen ( port , clear | flags , id ) ;
2008-07-02 10:56:40 +02:00
}
static void zfcp_erp_port_block ( struct zfcp_port * port , int clear )
{
2010-09-08 14:40:01 +02:00
zfcp_erp_clear_port_status ( port ,
ZFCP_STATUS_COMMON_UNBLOCKED | clear ) ;
2008-07-02 10:56:40 +02:00
}
2010-12-02 15:16:16 +01:00
static void _zfcp_erp_port_forced_reopen ( struct zfcp_port * port , int clear ,
char * id )
2008-07-02 10:56:40 +02:00
{
zfcp_erp_port_block ( port , clear ) ;
2009-03-02 13:09:08 +01:00
zfcp_scsi_schedule_rport_block ( port ) ;
2008-07-02 10:56:40 +02:00
if ( atomic_read ( & port - > status ) & ZFCP_STATUS_COMMON_ERP_FAILED )
return ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
zfcp_erp_action_enqueue ( ZFCP_ERP_ACTION_REOPEN_PORT_FORCED ,
2010-12-02 15:16:16 +01:00
port - > adapter , port , NULL , id , 0 ) ;
2008-07-02 10:56:40 +02:00
}
/**
* zfcp_erp_port_forced_reopen - Forced close of port and open again
* @ port : Port to force close and to reopen .
2010-12-02 15:16:16 +01:00
* @ clear : Status flags to clear .
2008-07-02 10:56:40 +02:00
* @ id : Id for debug trace event .
*/
2010-12-02 15:16:16 +01:00
void zfcp_erp_port_forced_reopen ( struct zfcp_port * port , int clear , char * id )
2008-07-02 10:56:40 +02:00
{
unsigned long flags ;
struct zfcp_adapter * adapter = port - > adapter ;
2009-11-24 16:53:58 +01:00
write_lock_irqsave ( & adapter - > erp_lock , flags ) ;
2010-12-02 15:16:16 +01:00
_zfcp_erp_port_forced_reopen ( port , clear , id ) ;
2009-11-24 16:53:58 +01:00
write_unlock_irqrestore ( & adapter - > erp_lock , flags ) ;
2008-07-02 10:56:40 +02:00
}
2010-12-02 15:16:16 +01:00
static int _zfcp_erp_port_reopen ( struct zfcp_port * port , int clear , char * id )
2008-07-02 10:56:40 +02:00
{
zfcp_erp_port_block ( port , clear ) ;
2009-03-02 13:09:08 +01:00
zfcp_scsi_schedule_rport_block ( port ) ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
if ( atomic_read ( & port - > status ) & ZFCP_STATUS_COMMON_ERP_FAILED ) {
2005-04-16 15:20:36 -07:00
/* ensure propagation of failed status to new devices */
2010-09-08 14:40:01 +02:00
zfcp_erp_set_port_status ( port , ZFCP_STATUS_COMMON_ERP_FAILED ) ;
2008-07-02 10:56:40 +02:00
return - EIO ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
return zfcp_erp_action_enqueue ( ZFCP_ERP_ACTION_REOPEN_PORT ,
2010-12-02 15:16:16 +01:00
port - > adapter , port , NULL , id , 0 ) ;
2005-04-16 15:20:36 -07:00
}
/**
2008-07-02 10:56:40 +02:00
* zfcp_erp_port_reopen - trigger remote port recovery
* @ port : port to recover
* @ clear_mask : flags in port status to be cleared
2010-12-02 15:16:16 +01:00
* @ id : Id for debug trace event .
2005-04-16 15:20:36 -07:00
*
2008-07-02 10:56:40 +02:00
* Returns 0 if recovery has been triggered , < 0 if not .
2005-04-16 15:20:36 -07:00
*/
2010-12-02 15:16:16 +01:00
int zfcp_erp_port_reopen ( struct zfcp_port * port , int clear , char * id )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
int retval ;
2009-11-24 16:53:58 +01:00
unsigned long flags ;
2005-04-16 15:20:36 -07:00
struct zfcp_adapter * adapter = port - > adapter ;
2009-11-24 16:53:58 +01:00
write_lock_irqsave ( & adapter - > erp_lock , flags ) ;
2010-12-02 15:16:16 +01:00
retval = _zfcp_erp_port_reopen ( port , clear , id ) ;
2009-11-24 16:53:58 +01:00
write_unlock_irqrestore ( & adapter - > erp_lock , flags ) ;
2005-04-16 15:20:36 -07:00
return retval ;
}
2010-09-08 14:39:55 +02:00
static void zfcp_erp_lun_block ( struct scsi_device * sdev , int clear_mask )
2008-07-02 10:56:40 +02:00
{
2010-09-08 14:40:01 +02:00
zfcp_erp_clear_lun_status ( sdev ,
ZFCP_STATUS_COMMON_UNBLOCKED | clear_mask ) ;
2008-07-02 10:56:40 +02:00
}
2010-09-08 14:39:55 +02:00
static void _zfcp_erp_lun_reopen ( struct scsi_device * sdev , int clear , char * id ,
2010-12-02 15:16:16 +01:00
u32 act_status )
2005-04-16 15:20:36 -07:00
{
2010-09-08 14:39:55 +02:00
struct zfcp_scsi_dev * zfcp_sdev = sdev_to_zfcp ( sdev ) ;
struct zfcp_adapter * adapter = zfcp_sdev - > port - > adapter ;
2005-04-16 15:20:36 -07:00
2010-09-08 14:39:55 +02:00
zfcp_erp_lun_block ( sdev , clear ) ;
2005-04-16 15:20:36 -07:00
2010-09-08 14:39:55 +02:00
if ( atomic_read ( & zfcp_sdev - > status ) & ZFCP_STATUS_COMMON_ERP_FAILED )
2008-07-02 10:56:40 +02:00
return ;
2005-04-16 15:20:36 -07:00
2010-09-08 14:39:55 +02:00
zfcp_erp_action_enqueue ( ZFCP_ERP_ACTION_REOPEN_LUN , adapter ,
2010-12-02 15:16:16 +01:00
zfcp_sdev - > port , sdev , id , act_status ) ;
2005-04-16 15:20:36 -07:00
}
/**
2010-09-08 14:39:55 +02:00
* zfcp_erp_lun_reopen - initiate reopen of a LUN
* @ sdev : SCSI device / LUN to be reopened
* @ clear_mask : specifies flags in LUN status to be cleared
2010-12-02 15:16:16 +01:00
* @ id : Id for debug trace event .
*
2005-04-16 15:20:36 -07:00
* Return : 0 on success , < 0 on error
*/
2010-12-02 15:16:16 +01:00
void zfcp_erp_lun_reopen ( struct scsi_device * sdev , int clear , char * id )
2005-04-16 15:20:36 -07:00
{
unsigned long flags ;
2010-09-08 14:39:55 +02:00
struct zfcp_scsi_dev * zfcp_sdev = sdev_to_zfcp ( sdev ) ;
struct zfcp_port * port = zfcp_sdev - > port ;
2008-07-02 10:56:40 +02:00
struct zfcp_adapter * adapter = port - > adapter ;
2005-04-16 15:20:36 -07:00
2009-11-24 16:53:58 +01:00
write_lock_irqsave ( & adapter - > erp_lock , flags ) ;
2010-12-02 15:16:16 +01:00
_zfcp_erp_lun_reopen ( sdev , clear , id , 0 ) ;
2010-09-08 14:39:54 +02:00
write_unlock_irqrestore ( & adapter - > erp_lock , flags ) ;
}
/**
2010-09-08 14:39:55 +02:00
* zfcp_erp_lun_shutdown - Shutdown LUN
* @ sdev : SCSI device / LUN to shut down .
2010-09-08 14:39:54 +02:00
* @ clear : Status flags to clear .
* @ id : Id for debug trace event .
*/
2010-12-02 15:16:16 +01:00
void zfcp_erp_lun_shutdown ( struct scsi_device * sdev , int clear , char * id )
2010-09-08 14:39:54 +02:00
{
int flags = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED ;
2010-12-02 15:16:16 +01:00
zfcp_erp_lun_reopen ( sdev , clear | flags , id ) ;
2010-09-08 14:39:54 +02:00
}
/**
2010-09-08 14:39:55 +02:00
* zfcp_erp_lun_shutdown_wait - Shutdown LUN and wait for erp completion
* @ sdev : SCSI device / LUN to shut down .
2010-09-08 14:39:54 +02:00
* @ id : Id for debug trace event .
*
2010-09-08 14:39:55 +02:00
* Do not acquire a reference for the LUN when creating the ERP
2010-09-08 14:39:54 +02:00
* action . It is safe , because this function waits for the ERP to
2010-09-08 14:39:55 +02:00
* complete first . This allows to shutdown the LUN , even when the SCSI
* device is in the state SDEV_DEL when scsi_device_get will fail .
2010-09-08 14:39:54 +02:00
*/
2010-09-08 14:39:55 +02:00
void zfcp_erp_lun_shutdown_wait ( struct scsi_device * sdev , char * id )
2010-09-08 14:39:54 +02:00
{
unsigned long flags ;
2010-09-08 14:39:55 +02:00
struct zfcp_scsi_dev * zfcp_sdev = sdev_to_zfcp ( sdev ) ;
struct zfcp_port * port = zfcp_sdev - > port ;
2010-09-08 14:39:54 +02:00
struct zfcp_adapter * adapter = port - > adapter ;
int clear = ZFCP_STATUS_COMMON_RUNNING | ZFCP_STATUS_COMMON_ERP_FAILED ;
write_lock_irqsave ( & adapter - > erp_lock , flags ) ;
2010-12-02 15:16:16 +01:00
_zfcp_erp_lun_reopen ( sdev , clear , id , ZFCP_STATUS_ERP_NO_REF ) ;
2009-11-24 16:53:58 +01:00
write_unlock_irqrestore ( & adapter - > erp_lock , flags ) ;
2010-09-08 14:39:54 +02:00
zfcp_erp_wait ( adapter ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static int status_change_set ( unsigned long mask , atomic_t * status )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
return ( atomic_read ( status ) ^ mask ) & mask ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static void zfcp_erp_adapter_unblock ( struct zfcp_adapter * adapter )
2008-03-27 14:22:02 +01:00
{
2008-07-02 10:56:40 +02:00
if ( status_change_set ( ZFCP_STATUS_COMMON_UNBLOCKED , & adapter - > status ) )
2010-12-02 15:16:12 +01:00
zfcp_dbf_rec_run ( " eraubl1 " , & adapter - > erp_action ) ;
2008-07-02 10:56:40 +02:00
atomic_set_mask ( ZFCP_STATUS_COMMON_UNBLOCKED , & adapter - > status ) ;
2008-03-27 14:22:02 +01:00
}
2008-07-02 10:56:40 +02:00
static void zfcp_erp_port_unblock ( struct zfcp_port * port )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
if ( status_change_set ( ZFCP_STATUS_COMMON_UNBLOCKED , & port - > status ) )
2010-12-02 15:16:12 +01:00
zfcp_dbf_rec_run ( " erpubl1 " , & port - > erp_action ) ;
2008-07-02 10:56:40 +02:00
atomic_set_mask ( ZFCP_STATUS_COMMON_UNBLOCKED , & port - > status ) ;
2005-04-16 15:20:36 -07:00
}
2010-09-08 14:39:55 +02:00
static void zfcp_erp_lun_unblock ( struct scsi_device * sdev )
2005-04-16 15:20:36 -07:00
{
2010-09-08 14:39:55 +02:00
struct zfcp_scsi_dev * zfcp_sdev = sdev_to_zfcp ( sdev ) ;
if ( status_change_set ( ZFCP_STATUS_COMMON_UNBLOCKED , & zfcp_sdev - > status ) )
2010-12-02 15:16:12 +01:00
zfcp_dbf_rec_run ( " erlubl1 " , & sdev_to_zfcp ( sdev ) - > erp_action ) ;
2010-09-08 14:39:55 +02:00
atomic_set_mask ( ZFCP_STATUS_COMMON_UNBLOCKED , & zfcp_sdev - > status ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static void zfcp_erp_action_to_running ( struct zfcp_erp_action * erp_action )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
list_move ( & erp_action - > list , & erp_action - > adapter - > erp_running_head ) ;
2010-12-02 15:16:12 +01:00
zfcp_dbf_rec_run ( " erator1 " , erp_action ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static void zfcp_erp_strategy_check_fsfreq ( struct zfcp_erp_action * act )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
struct zfcp_adapter * adapter = act - > adapter ;
2010-02-17 11:18:49 +01:00
struct zfcp_fsf_req * req ;
2005-04-16 15:20:36 -07:00
2010-02-17 11:18:49 +01:00
if ( ! act - > fsf_req_id )
2008-07-02 10:56:40 +02:00
return ;
2005-04-16 15:20:36 -07:00
2010-02-17 11:18:50 +01:00
spin_lock ( & adapter - > req_list - > lock ) ;
req = _zfcp_reqlist_find ( adapter - > req_list , act - > fsf_req_id ) ;
2010-02-17 11:18:49 +01:00
if ( req & & req - > erp_action = = act ) {
2008-07-02 10:56:40 +02:00
if ( act - > status & ( ZFCP_STATUS_ERP_DISMISSED |
ZFCP_STATUS_ERP_TIMEDOUT ) ) {
2010-02-17 11:18:49 +01:00
req - > status | = ZFCP_STATUS_FSFREQ_DISMISSED ;
2010-12-02 15:16:12 +01:00
zfcp_dbf_rec_run ( " erscf_1 " , act ) ;
2010-02-17 11:18:49 +01:00
req - > erp_action = NULL ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
if ( act - > status & ZFCP_STATUS_ERP_TIMEDOUT )
2010-12-02 15:16:12 +01:00
zfcp_dbf_rec_run ( " erscf_2 " , act ) ;
2010-02-17 11:18:49 +01:00
if ( req - > status & ZFCP_STATUS_FSFREQ_DISMISSED )
act - > fsf_req_id = 0 ;
2008-07-02 10:56:40 +02:00
} else
2010-02-17 11:18:49 +01:00
act - > fsf_req_id = 0 ;
2010-02-17 11:18:50 +01:00
spin_unlock ( & adapter - > req_list - > lock ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
/**
* zfcp_erp_notify - Trigger ERP action .
* @ erp_action : ERP action to continue .
* @ set_mask : ERP action status flags to set .
2005-04-16 15:20:36 -07:00
*/
2008-07-02 10:56:40 +02:00
void zfcp_erp_notify ( struct zfcp_erp_action * erp_action , unsigned long set_mask )
2005-04-16 15:20:36 -07:00
{
struct zfcp_adapter * adapter = erp_action - > adapter ;
2008-07-02 10:56:40 +02:00
unsigned long flags ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
write_lock_irqsave ( & adapter - > erp_lock , flags ) ;
2005-04-16 15:20:36 -07:00
if ( zfcp_erp_action_exists ( erp_action ) = = ZFCP_ERP_ACTION_RUNNING ) {
erp_action - > status | = set_mask ;
zfcp_erp_action_ready ( erp_action ) ;
}
write_unlock_irqrestore ( & adapter - > erp_lock , flags ) ;
}
2008-07-02 10:56:40 +02:00
/**
* zfcp_erp_timeout_handler - Trigger ERP action from timed out ERP request
* @ data : ERP action ( from timer data )
2005-04-16 15:20:36 -07:00
*/
2008-07-02 10:56:40 +02:00
void zfcp_erp_timeout_handler ( unsigned long data )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
struct zfcp_erp_action * act = ( struct zfcp_erp_action * ) data ;
zfcp_erp_notify ( act , ZFCP_STATUS_ERP_TIMEDOUT ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static void zfcp_erp_memwait_handler ( unsigned long data )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
zfcp_erp_notify ( ( struct zfcp_erp_action * ) data , 0 ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static void zfcp_erp_strategy_memwait ( struct zfcp_erp_action * erp_action )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
init_timer ( & erp_action - > timer ) ;
erp_action - > timer . function = zfcp_erp_memwait_handler ;
erp_action - > timer . data = ( unsigned long ) erp_action ;
erp_action - > timer . expires = jiffies + HZ ;
add_timer ( & erp_action - > timer ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static void _zfcp_erp_port_reopen_all ( struct zfcp_adapter * adapter ,
2010-12-02 15:16:16 +01:00
int clear , char * id )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
struct zfcp_port * port ;
2005-04-16 15:20:36 -07:00
2009-11-24 16:53:58 +01:00
read_lock ( & adapter - > port_list_lock ) ;
list_for_each_entry ( port , & adapter - > port_list , list )
2010-12-02 15:16:16 +01:00
_zfcp_erp_port_reopen ( port , clear , id ) ;
2009-11-24 16:53:58 +01:00
read_unlock ( & adapter - > port_list_lock ) ;
2005-04-16 15:20:36 -07:00
}
2010-09-08 14:39:55 +02:00
static void _zfcp_erp_lun_reopen_all ( struct zfcp_port * port , int clear ,
2010-12-02 15:16:16 +01:00
char * id )
2005-04-16 15:20:36 -07:00
{
2010-09-08 14:39:55 +02:00
struct scsi_device * sdev ;
2005-04-16 15:20:36 -07:00
2010-09-08 14:39:55 +02:00
shost_for_each_device ( sdev , port - > adapter - > scsi_host )
if ( sdev_to_zfcp ( sdev ) - > port = = port )
2010-12-02 15:16:16 +01:00
_zfcp_erp_lun_reopen ( sdev , clear , id , 0 ) ;
2005-04-16 15:20:36 -07:00
}
2009-07-13 15:06:09 +02:00
static void zfcp_erp_strategy_followup_failed ( struct zfcp_erp_action * act )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
switch ( act - > action ) {
case ZFCP_ERP_ACTION_REOPEN_ADAPTER :
2010-12-02 15:16:16 +01:00
_zfcp_erp_adapter_reopen ( act - > adapter , 0 , " ersff_1 " ) ;
2008-07-02 10:56:40 +02:00
break ;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED :
2010-12-02 15:16:16 +01:00
_zfcp_erp_port_forced_reopen ( act - > port , 0 , " ersff_2 " ) ;
2008-07-02 10:56:40 +02:00
break ;
case ZFCP_ERP_ACTION_REOPEN_PORT :
2010-12-02 15:16:16 +01:00
_zfcp_erp_port_reopen ( act - > port , 0 , " ersff_3 " ) ;
2008-07-02 10:56:40 +02:00
break ;
2010-09-08 14:39:55 +02:00
case ZFCP_ERP_ACTION_REOPEN_LUN :
2010-12-02 15:16:16 +01:00
_zfcp_erp_lun_reopen ( act - > sdev , 0 , " ersff_4 " , 0 ) ;
2009-07-13 15:06:09 +02:00
break ;
}
}
static void zfcp_erp_strategy_followup_success ( struct zfcp_erp_action * act )
{
switch ( act - > action ) {
case ZFCP_ERP_ACTION_REOPEN_ADAPTER :
2010-12-02 15:16:16 +01:00
_zfcp_erp_port_reopen_all ( act - > adapter , 0 , " ersfs_1 " ) ;
2009-07-13 15:06:09 +02:00
break ;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED :
2010-12-02 15:16:16 +01:00
_zfcp_erp_port_reopen ( act - > port , 0 , " ersfs_2 " ) ;
2009-07-13 15:06:09 +02:00
break ;
case ZFCP_ERP_ACTION_REOPEN_PORT :
2010-12-02 15:16:16 +01:00
_zfcp_erp_lun_reopen_all ( act - > port , 0 , " ersfs_3 " ) ;
2008-07-02 10:56:40 +02:00
break ;
2005-04-16 15:20:36 -07:00
}
}
2008-07-02 10:56:40 +02:00
static void zfcp_erp_wakeup ( struct zfcp_adapter * adapter )
2005-04-16 15:20:36 -07:00
{
unsigned long flags ;
2009-11-24 16:53:58 +01:00
read_lock_irqsave ( & adapter - > erp_lock , flags ) ;
2008-07-02 10:56:40 +02:00
if ( list_empty ( & adapter - > erp_ready_head ) & &
list_empty ( & adapter - > erp_running_head ) ) {
atomic_clear_mask ( ZFCP_STATUS_ADAPTER_ERP_PENDING ,
& adapter - > status ) ;
wake_up ( & adapter - > erp_done_wqh ) ;
2005-04-16 15:20:36 -07:00
}
2009-11-24 16:53:58 +01:00
read_unlock_irqrestore ( & adapter - > erp_lock , flags ) ;
2008-07-02 10:56:40 +02:00
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
static void zfcp_erp_enqueue_ptp_port ( struct zfcp_adapter * adapter )
{
struct zfcp_port * port ;
port = zfcp_port_enqueue ( adapter , adapter - > peer_wwpn , 0 ,
adapter - > peer_d_id ) ;
if ( IS_ERR ( port ) ) /* error or port already attached */
return ;
2010-12-02 15:16:16 +01:00
_zfcp_erp_port_reopen ( port , 0 , " ereptp1 " ) ;
2008-07-02 10:56:40 +02:00
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
static int zfcp_erp_adapter_strat_fsf_xconf ( struct zfcp_erp_action * erp_action )
{
int retries ;
int sleep = 1 ;
struct zfcp_adapter * adapter = erp_action - > adapter ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
atomic_clear_mask ( ZFCP_STATUS_ADAPTER_XCONFIG_OK , & adapter - > status ) ;
for ( retries = 7 ; retries ; retries - - ) {
atomic_clear_mask ( ZFCP_STATUS_ADAPTER_HOST_CON_INIT ,
& adapter - > status ) ;
write_lock_irq ( & adapter - > erp_lock ) ;
zfcp_erp_action_to_running ( erp_action ) ;
write_unlock_irq ( & adapter - > erp_lock ) ;
if ( zfcp_fsf_exchange_config_data ( erp_action ) ) {
atomic_clear_mask ( ZFCP_STATUS_ADAPTER_HOST_CON_INIT ,
& adapter - > status ) ;
return ZFCP_ERP_FAILED ;
2005-04-16 15:20:36 -07:00
}
2009-08-18 15:43:25 +02:00
wait_event ( adapter - > erp_ready_wq ,
! list_empty ( & adapter - > erp_ready_head ) ) ;
2008-07-02 10:56:40 +02:00
if ( erp_action - > status & ZFCP_STATUS_ERP_TIMEDOUT )
break ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
if ( ! ( atomic_read ( & adapter - > status ) &
ZFCP_STATUS_ADAPTER_HOST_CON_INIT ) )
break ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
ssleep ( sleep ) ;
sleep * = 2 ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
atomic_clear_mask ( ZFCP_STATUS_ADAPTER_HOST_CON_INIT ,
& adapter - > status ) ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
if ( ! ( atomic_read ( & adapter - > status ) & ZFCP_STATUS_ADAPTER_XCONFIG_OK ) )
return ZFCP_ERP_FAILED ;
2007-09-07 09:15:31 +02:00
2008-07-02 10:56:40 +02:00
if ( fc_host_port_type ( adapter - > scsi_host ) = = FC_PORTTYPE_PTP )
zfcp_erp_enqueue_ptp_port ( adapter ) ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
return ZFCP_ERP_SUCCEEDED ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_adapter_strategy_open_fsf_xport ( struct zfcp_erp_action * act )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
int ret ;
struct zfcp_adapter * adapter = act - > adapter ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
write_lock_irq ( & adapter - > erp_lock ) ;
zfcp_erp_action_to_running ( act ) ;
write_unlock_irq ( & adapter - > erp_lock ) ;
ret = zfcp_fsf_exchange_port_data ( act ) ;
if ( ret = = - EOPNOTSUPP )
return ZFCP_ERP_SUCCEEDED ;
if ( ret )
return ZFCP_ERP_FAILED ;
2010-12-02 15:16:12 +01:00
zfcp_dbf_rec_run ( " erasox1 " , act ) ;
2009-08-18 15:43:25 +02:00
wait_event ( adapter - > erp_ready_wq ,
! list_empty ( & adapter - > erp_ready_head ) ) ;
2010-12-02 15:16:12 +01:00
zfcp_dbf_rec_run ( " erasox2 " , act ) ;
2008-07-02 10:56:40 +02:00
if ( act - > status & ZFCP_STATUS_ERP_TIMEDOUT )
return ZFCP_ERP_FAILED ;
return ZFCP_ERP_SUCCEEDED ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_adapter_strategy_open_fsf ( struct zfcp_erp_action * act )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
if ( zfcp_erp_adapter_strat_fsf_xconf ( act ) = = ZFCP_ERP_FAILED )
return ZFCP_ERP_FAILED ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
if ( zfcp_erp_adapter_strategy_open_fsf_xport ( act ) = = ZFCP_ERP_FAILED )
return ZFCP_ERP_FAILED ;
2005-04-16 15:20:36 -07:00
2011-02-22 19:54:40 +01:00
if ( mempool_resize ( act - > adapter - > pool . sr_data ,
2010-06-21 10:11:33 +02:00
act - > adapter - > stat_read_buf_num , GFP_KERNEL ) )
return ZFCP_ERP_FAILED ;
if ( mempool_resize ( act - > adapter - > pool . status_read_req ,
act - > adapter - > stat_read_buf_num , GFP_KERNEL ) )
return ZFCP_ERP_FAILED ;
2010-04-30 18:09:36 +02:00
atomic_set ( & act - > adapter - > stat_miss , act - > adapter - > stat_read_buf_num ) ;
2008-07-02 10:56:40 +02:00
if ( zfcp_status_read_refill ( act - > adapter ) )
return ZFCP_ERP_FAILED ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
return ZFCP_ERP_SUCCEEDED ;
}
2005-04-16 15:20:36 -07:00
2009-03-02 13:09:03 +01:00
static void zfcp_erp_adapter_strategy_close ( struct zfcp_erp_action * act )
2008-07-02 10:56:40 +02:00
{
struct zfcp_adapter * adapter = act - > adapter ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
/* close queues to ensure that buffers are not accessed by adapter */
2009-08-18 15:43:19 +02:00
zfcp_qdio_close ( adapter - > qdio ) ;
2008-07-02 10:56:40 +02:00
zfcp_fsf_req_dismiss_all ( adapter ) ;
adapter - > fsf_req_seq_no = 0 ;
2009-08-18 15:43:12 +02:00
zfcp_fc_wka_ports_force_offline ( adapter - > gs ) ;
2010-09-08 14:39:55 +02:00
/* all ports and LUNs are closed */
2010-09-08 14:40:01 +02:00
zfcp_erp_clear_adapter_status ( adapter , ZFCP_STATUS_COMMON_OPEN ) ;
2009-03-02 13:09:03 +01:00
2008-07-02 10:56:40 +02:00
atomic_clear_mask ( ZFCP_STATUS_ADAPTER_XCONFIG_OK |
2009-03-02 13:09:03 +01:00
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED , & adapter - > status ) ;
2005-04-16 15:20:36 -07:00
}
2009-03-02 13:09:03 +01:00
static int zfcp_erp_adapter_strategy_open ( struct zfcp_erp_action * act )
2005-04-16 15:20:36 -07:00
{
2009-03-02 13:09:03 +01:00
struct zfcp_adapter * adapter = act - > adapter ;
2005-04-16 15:20:36 -07:00
2010-12-02 15:16:17 +01:00
if ( zfcp_qdio_open ( adapter - > qdio ) ) {
2009-03-02 13:09:03 +01:00
atomic_clear_mask ( ZFCP_STATUS_ADAPTER_XCONFIG_OK |
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED ,
& adapter - > status ) ;
return ZFCP_ERP_FAILED ;
}
2008-07-02 10:56:40 +02:00
2009-03-02 13:09:03 +01:00
if ( zfcp_erp_adapter_strategy_open_fsf ( act ) ) {
zfcp_erp_adapter_strategy_close ( act ) ;
return ZFCP_ERP_FAILED ;
}
atomic_set_mask ( ZFCP_STATUS_COMMON_OPEN , & adapter - > status ) ;
return ZFCP_ERP_SUCCEEDED ;
}
2008-07-02 10:56:40 +02:00
2009-03-02 13:09:03 +01:00
static int zfcp_erp_adapter_strategy ( struct zfcp_erp_action * act )
{
struct zfcp_adapter * adapter = act - > adapter ;
if ( atomic_read ( & adapter - > status ) & ZFCP_STATUS_COMMON_OPEN ) {
zfcp_erp_adapter_strategy_close ( act ) ;
if ( act - > status & ZFCP_STATUS_ERP_CLOSE_ONLY )
return ZFCP_ERP_EXIT ;
}
if ( zfcp_erp_adapter_strategy_open ( act ) ) {
2008-07-02 10:56:40 +02:00
ssleep ( 8 ) ;
2009-03-02 13:09:03 +01:00
return ZFCP_ERP_FAILED ;
}
2005-04-16 15:20:36 -07:00
2009-03-02 13:09:03 +01:00
return ZFCP_ERP_SUCCEEDED ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_port_forced_strategy_close ( struct zfcp_erp_action * act )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
int retval ;
retval = zfcp_fsf_close_physical_port ( act ) ;
if ( retval = = - ENOMEM )
return ZFCP_ERP_NOMEM ;
act - > step = ZFCP_ERP_STEP_PHYS_PORT_CLOSING ;
if ( retval )
return ZFCP_ERP_FAILED ;
return ZFCP_ERP_CONTINUES ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static void zfcp_erp_port_strategy_clearstati ( struct zfcp_port * port )
2005-04-16 15:20:36 -07:00
{
2009-03-02 13:08:54 +01:00
atomic_clear_mask ( ZFCP_STATUS_COMMON_ACCESS_DENIED , & port - > status ) ;
2008-07-02 10:56:40 +02:00
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
static int zfcp_erp_port_forced_strategy ( struct zfcp_erp_action * erp_action )
{
struct zfcp_port * port = erp_action - > port ;
int status = atomic_read ( & port - > status ) ;
switch ( erp_action - > step ) {
case ZFCP_ERP_STEP_UNINITIALIZED :
zfcp_erp_port_strategy_clearstati ( port ) ;
if ( ( status & ZFCP_STATUS_PORT_PHYS_OPEN ) & &
( status & ZFCP_STATUS_COMMON_OPEN ) )
return zfcp_erp_port_forced_strategy_close ( erp_action ) ;
else
return ZFCP_ERP_FAILED ;
case ZFCP_ERP_STEP_PHYS_PORT_CLOSING :
2009-07-13 15:06:08 +02:00
if ( ! ( status & ZFCP_STATUS_PORT_PHYS_OPEN ) )
2008-07-02 10:56:40 +02:00
return ZFCP_ERP_SUCCEEDED ;
}
return ZFCP_ERP_FAILED ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_port_strategy_close ( struct zfcp_erp_action * erp_action )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
int retval ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
retval = zfcp_fsf_close_port ( erp_action ) ;
if ( retval = = - ENOMEM )
return ZFCP_ERP_NOMEM ;
erp_action - > step = ZFCP_ERP_STEP_PORT_CLOSING ;
if ( retval )
return ZFCP_ERP_FAILED ;
return ZFCP_ERP_CONTINUES ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_port_strategy_open_port ( struct zfcp_erp_action * erp_action )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
int retval ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
retval = zfcp_fsf_open_port ( erp_action ) ;
if ( retval = = - ENOMEM )
return ZFCP_ERP_NOMEM ;
erp_action - > step = ZFCP_ERP_STEP_PORT_OPENING ;
if ( retval )
return ZFCP_ERP_FAILED ;
return ZFCP_ERP_CONTINUES ;
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
static int zfcp_erp_open_ptp_port ( struct zfcp_erp_action * act )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
struct zfcp_adapter * adapter = act - > adapter ;
struct zfcp_port * port = act - > port ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
if ( port - > wwpn ! = adapter - > peer_wwpn ) {
2010-09-08 14:40:01 +02:00
zfcp_erp_set_port_status ( port , ZFCP_STATUS_COMMON_ERP_FAILED ) ;
2008-07-02 10:56:40 +02:00
return ZFCP_ERP_FAILED ;
}
port - > d_id = adapter - > peer_d_id ;
return zfcp_erp_port_strategy_open_port ( act ) ;
}
static int zfcp_erp_port_strategy_open_common ( struct zfcp_erp_action * act )
{
struct zfcp_adapter * adapter = act - > adapter ;
struct zfcp_port * port = act - > port ;
int p_status = atomic_read ( & port - > status ) ;
switch ( act - > step ) {
case ZFCP_ERP_STEP_UNINITIALIZED :
case ZFCP_ERP_STEP_PHYS_PORT_CLOSING :
case ZFCP_ERP_STEP_PORT_CLOSING :
if ( fc_host_port_type ( adapter - > scsi_host ) = = FC_PORTTYPE_PTP )
return zfcp_erp_open_ptp_port ( act ) ;
2008-12-19 16:56:59 +01:00
if ( ! port - > d_id ) {
2009-10-14 11:00:43 +02:00
zfcp_fc_trigger_did_lookup ( port ) ;
2009-08-18 15:43:20 +02:00
return ZFCP_ERP_EXIT ;
2008-07-02 10:56:40 +02:00
}
return zfcp_erp_port_strategy_open_port ( act ) ;
case ZFCP_ERP_STEP_PORT_OPENING :
/* D_ID might have changed during open */
2008-10-01 12:42:17 +02:00
if ( p_status & ZFCP_STATUS_COMMON_OPEN ) {
2009-10-14 11:00:43 +02:00
if ( ! port - > d_id ) {
zfcp_fc_trigger_did_lookup ( port ) ;
return ZFCP_ERP_EXIT ;
2008-10-01 12:42:17 +02:00
}
2009-10-14 11:00:43 +02:00
return ZFCP_ERP_SUCCEEDED ;
2008-10-01 12:42:17 +02:00
}
2009-05-15 13:18:20 +02:00
if ( port - > d_id & & ! ( p_status & ZFCP_STATUS_COMMON_NOESC ) ) {
port - > d_id = 0 ;
2010-07-08 09:53:10 +02:00
return ZFCP_ERP_FAILED ;
2009-05-15 13:18:20 +02:00
}
/* fall through otherwise */
2008-07-02 10:56:40 +02:00
}
return ZFCP_ERP_FAILED ;
}
static int zfcp_erp_port_strategy ( struct zfcp_erp_action * erp_action )
{
struct zfcp_port * port = erp_action - > port ;
2009-10-14 11:00:43 +02:00
int p_status = atomic_read ( & port - > status ) ;
2008-07-02 10:56:40 +02:00
2009-10-14 11:00:43 +02:00
if ( ( p_status & ZFCP_STATUS_COMMON_NOESC ) & &
! ( p_status & ZFCP_STATUS_COMMON_OPEN ) )
2008-10-01 12:42:17 +02:00
goto close_init_done ;
2008-07-02 10:56:40 +02:00
switch ( erp_action - > step ) {
case ZFCP_ERP_STEP_UNINITIALIZED :
zfcp_erp_port_strategy_clearstati ( port ) ;
2009-10-14 11:00:43 +02:00
if ( p_status & ZFCP_STATUS_COMMON_OPEN )
2008-07-02 10:56:40 +02:00
return zfcp_erp_port_strategy_close ( erp_action ) ;
2005-04-16 15:20:36 -07:00
break ;
2008-07-02 10:56:40 +02:00
case ZFCP_ERP_STEP_PORT_CLOSING :
2009-10-14 11:00:43 +02:00
if ( p_status & ZFCP_STATUS_COMMON_OPEN )
2008-07-02 10:56:40 +02:00
return ZFCP_ERP_FAILED ;
2005-04-16 15:20:36 -07:00
break ;
}
2008-10-01 12:42:17 +02:00
close_init_done :
2008-07-02 10:56:40 +02:00
if ( erp_action - > status & ZFCP_STATUS_ERP_CLOSE_ONLY )
return ZFCP_ERP_EXIT ;
2005-04-16 15:20:36 -07:00
2008-10-01 12:42:17 +02:00
return zfcp_erp_port_strategy_open_common ( erp_action ) ;
2008-07-02 10:56:40 +02:00
}
2010-09-08 14:39:55 +02:00
static void zfcp_erp_lun_strategy_clearstati ( struct scsi_device * sdev )
2008-07-02 10:56:40 +02:00
{
2010-09-08 14:39:55 +02:00
struct zfcp_scsi_dev * zfcp_sdev = sdev_to_zfcp ( sdev ) ;
2008-10-01 12:42:16 +02:00
atomic_clear_mask ( ZFCP_STATUS_COMMON_ACCESS_DENIED |
2010-09-08 14:39:55 +02:00
ZFCP_STATUS_LUN_SHARED | ZFCP_STATUS_LUN_READONLY ,
& zfcp_sdev - > status ) ;
2008-07-02 10:56:40 +02:00
}
2010-09-08 14:39:55 +02:00
static int zfcp_erp_lun_strategy_close ( struct zfcp_erp_action * erp_action )
2008-07-02 10:56:40 +02:00
{
2010-09-08 14:39:55 +02:00
int retval = zfcp_fsf_close_lun ( erp_action ) ;
2008-07-02 10:56:40 +02:00
if ( retval = = - ENOMEM )
return ZFCP_ERP_NOMEM ;
2010-09-08 14:39:55 +02:00
erp_action - > step = ZFCP_ERP_STEP_LUN_CLOSING ;
2008-07-02 10:56:40 +02:00
if ( retval )
return ZFCP_ERP_FAILED ;
return ZFCP_ERP_CONTINUES ;
}
2010-09-08 14:39:55 +02:00
static int zfcp_erp_lun_strategy_open ( struct zfcp_erp_action * erp_action )
2008-07-02 10:56:40 +02:00
{
2010-09-08 14:39:55 +02:00
int retval = zfcp_fsf_open_lun ( erp_action ) ;
2008-07-02 10:56:40 +02:00
if ( retval = = - ENOMEM )
return ZFCP_ERP_NOMEM ;
2010-09-08 14:39:55 +02:00
erp_action - > step = ZFCP_ERP_STEP_LUN_OPENING ;
2008-07-02 10:56:40 +02:00
if ( retval )
return ZFCP_ERP_FAILED ;
return ZFCP_ERP_CONTINUES ;
2005-04-16 15:20:36 -07:00
}
2010-09-08 14:39:55 +02:00
static int zfcp_erp_lun_strategy ( struct zfcp_erp_action * erp_action )
2005-04-16 15:20:36 -07:00
{
2010-09-08 14:39:55 +02:00
struct scsi_device * sdev = erp_action - > sdev ;
struct zfcp_scsi_dev * zfcp_sdev = sdev_to_zfcp ( sdev ) ;
2008-07-02 10:56:40 +02:00
switch ( erp_action - > step ) {
case ZFCP_ERP_STEP_UNINITIALIZED :
2010-09-08 14:39:55 +02:00
zfcp_erp_lun_strategy_clearstati ( sdev ) ;
if ( atomic_read ( & zfcp_sdev - > status ) & ZFCP_STATUS_COMMON_OPEN )
return zfcp_erp_lun_strategy_close ( erp_action ) ;
2008-07-02 10:56:40 +02:00
/* already closed, fall through */
2010-09-08 14:39:55 +02:00
case ZFCP_ERP_STEP_LUN_CLOSING :
if ( atomic_read ( & zfcp_sdev - > status ) & ZFCP_STATUS_COMMON_OPEN )
2008-07-02 10:56:40 +02:00
return ZFCP_ERP_FAILED ;
if ( erp_action - > status & ZFCP_STATUS_ERP_CLOSE_ONLY )
return ZFCP_ERP_EXIT ;
2010-09-08 14:39:55 +02:00
return zfcp_erp_lun_strategy_open ( erp_action ) ;
2008-07-02 10:56:40 +02:00
2010-09-08 14:39:55 +02:00
case ZFCP_ERP_STEP_LUN_OPENING :
if ( atomic_read ( & zfcp_sdev - > status ) & ZFCP_STATUS_COMMON_OPEN )
2008-07-02 10:56:40 +02:00
return ZFCP_ERP_SUCCEEDED ;
}
return ZFCP_ERP_FAILED ;
2005-04-16 15:20:36 -07:00
}
2010-09-08 14:39:55 +02:00
static int zfcp_erp_strategy_check_lun ( struct scsi_device * sdev , int result )
2005-04-16 15:20:36 -07:00
{
2010-09-08 14:39:55 +02:00
struct zfcp_scsi_dev * zfcp_sdev = sdev_to_zfcp ( sdev ) ;
2005-04-16 15:20:36 -07:00
switch ( result ) {
case ZFCP_ERP_SUCCEEDED :
2010-09-08 14:39:55 +02:00
atomic_set ( & zfcp_sdev - > erp_counter , 0 ) ;
zfcp_erp_lun_unblock ( sdev ) ;
2005-04-16 15:20:36 -07:00
break ;
case ZFCP_ERP_FAILED :
2010-09-08 14:39:55 +02:00
atomic_inc ( & zfcp_sdev - > erp_counter ) ;
if ( atomic_read ( & zfcp_sdev - > erp_counter ) > ZFCP_MAX_ERPS ) {
dev_err ( & zfcp_sdev - > port - > adapter - > ccw_device - > dev ,
" ERP failed for LUN 0x%016Lx on "
2008-10-01 12:42:15 +02:00
" port 0x%016Lx \n " ,
2010-09-08 14:39:55 +02:00
( unsigned long long ) zfcp_scsi_dev_lun ( sdev ) ,
( unsigned long long ) zfcp_sdev - > port - > wwpn ) ;
2010-09-08 14:40:01 +02:00
zfcp_erp_set_lun_status ( sdev ,
ZFCP_STATUS_COMMON_ERP_FAILED ) ;
2008-10-01 12:42:15 +02:00
}
2005-04-16 15:20:36 -07:00
break ;
}
2010-09-08 14:39:55 +02:00
if ( atomic_read ( & zfcp_sdev - > status ) & ZFCP_STATUS_COMMON_ERP_FAILED ) {
zfcp_erp_lun_block ( sdev , 0 ) ;
2005-04-16 15:20:36 -07:00
result = ZFCP_ERP_EXIT ;
}
return result ;
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_strategy_check_port ( struct zfcp_port * port , int result )
2005-04-16 15:20:36 -07:00
{
switch ( result ) {
case ZFCP_ERP_SUCCEEDED :
atomic_set ( & port - > erp_counter , 0 ) ;
zfcp_erp_port_unblock ( port ) ;
break ;
2008-07-02 10:56:40 +02:00
2005-04-16 15:20:36 -07:00
case ZFCP_ERP_FAILED :
2008-07-02 10:56:40 +02:00
if ( atomic_read ( & port - > status ) & ZFCP_STATUS_COMMON_NOESC ) {
2008-06-10 18:21:00 +02:00
zfcp_erp_port_block ( port , 0 ) ;
result = ZFCP_ERP_EXIT ;
}
2005-04-16 15:20:36 -07:00
atomic_inc ( & port - > erp_counter ) ;
2008-10-01 12:42:15 +02:00
if ( atomic_read ( & port - > erp_counter ) > ZFCP_MAX_ERPS ) {
dev_err ( & port - > adapter - > ccw_device - > dev ,
" ERP failed for remote port 0x%016Lx \n " ,
2008-10-01 12:42:18 +02:00
( unsigned long long ) port - > wwpn ) ;
2010-09-08 14:40:01 +02:00
zfcp_erp_set_port_status ( port ,
ZFCP_STATUS_COMMON_ERP_FAILED ) ;
2008-10-01 12:42:15 +02:00
}
2005-04-16 15:20:36 -07:00
break ;
}
2008-07-02 10:56:40 +02:00
if ( atomic_read ( & port - > status ) & ZFCP_STATUS_COMMON_ERP_FAILED ) {
zfcp_erp_port_block ( port , 0 ) ;
2005-04-16 15:20:36 -07:00
result = ZFCP_ERP_EXIT ;
}
return result ;
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_strategy_check_adapter ( struct zfcp_adapter * adapter ,
int result )
2005-04-16 15:20:36 -07:00
{
switch ( result ) {
case ZFCP_ERP_SUCCEEDED :
atomic_set ( & adapter - > erp_counter , 0 ) ;
zfcp_erp_adapter_unblock ( adapter ) ;
break ;
2008-07-02 10:56:40 +02:00
2005-04-16 15:20:36 -07:00
case ZFCP_ERP_FAILED :
atomic_inc ( & adapter - > erp_counter ) ;
2008-10-01 12:42:15 +02:00
if ( atomic_read ( & adapter - > erp_counter ) > ZFCP_MAX_ERPS ) {
dev_err ( & adapter - > ccw_device - > dev ,
" ERP cannot recover an error "
" on the FCP device \n " ) ;
2010-09-08 14:40:01 +02:00
zfcp_erp_set_adapter_status ( adapter ,
ZFCP_STATUS_COMMON_ERP_FAILED ) ;
2008-10-01 12:42:15 +02:00
}
2005-04-16 15:20:36 -07:00
break ;
}
2008-07-02 10:56:40 +02:00
if ( atomic_read ( & adapter - > status ) & ZFCP_STATUS_COMMON_ERP_FAILED ) {
zfcp_erp_adapter_block ( adapter , 0 ) ;
2005-04-16 15:20:36 -07:00
result = ZFCP_ERP_EXIT ;
}
return result ;
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_strategy_check_target ( struct zfcp_erp_action * erp_action ,
int result )
2007-05-08 11:16:52 +02:00
{
2008-07-02 10:56:40 +02:00
struct zfcp_adapter * adapter = erp_action - > adapter ;
struct zfcp_port * port = erp_action - > port ;
2010-09-08 14:39:55 +02:00
struct scsi_device * sdev = erp_action - > sdev ;
2008-07-02 10:56:40 +02:00
switch ( erp_action - > action ) {
2010-09-08 14:39:55 +02:00
case ZFCP_ERP_ACTION_REOPEN_LUN :
result = zfcp_erp_strategy_check_lun ( sdev , result ) ;
2008-07-02 10:56:40 +02:00
break ;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED :
case ZFCP_ERP_ACTION_REOPEN_PORT :
result = zfcp_erp_strategy_check_port ( port , result ) ;
break ;
case ZFCP_ERP_ACTION_REOPEN_ADAPTER :
result = zfcp_erp_strategy_check_adapter ( adapter , result ) ;
break ;
}
return result ;
2007-05-08 11:16:52 +02:00
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_strat_change_det ( atomic_t * target_status , u32 erp_status )
2007-05-08 11:16:52 +02:00
{
2008-07-02 10:56:40 +02:00
int status = atomic_read ( target_status ) ;
2007-05-08 11:16:52 +02:00
2008-07-02 10:56:40 +02:00
if ( ( status & ZFCP_STATUS_COMMON_RUNNING ) & &
( erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY ) )
return 1 ; /* take it online */
2007-05-08 11:16:52 +02:00
2008-07-02 10:56:40 +02:00
if ( ! ( status & ZFCP_STATUS_COMMON_RUNNING ) & &
! ( erp_status & ZFCP_STATUS_ERP_CLOSE_ONLY ) )
return 1 ; /* take it offline */
return 0 ;
2007-05-08 11:16:52 +02:00
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_strategy_statechange ( struct zfcp_erp_action * act , int ret )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
int action = act - > action ;
struct zfcp_adapter * adapter = act - > adapter ;
struct zfcp_port * port = act - > port ;
2010-09-08 14:39:55 +02:00
struct scsi_device * sdev = act - > sdev ;
struct zfcp_scsi_dev * zfcp_sdev ;
2008-07-02 10:56:40 +02:00
u32 erp_status = act - > status ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
switch ( action ) {
2005-04-16 15:20:36 -07:00
case ZFCP_ERP_ACTION_REOPEN_ADAPTER :
2008-07-02 10:56:40 +02:00
if ( zfcp_erp_strat_change_det ( & adapter - > status , erp_status ) ) {
_zfcp_erp_adapter_reopen ( adapter ,
ZFCP_STATUS_COMMON_ERP_FAILED ,
2010-12-02 15:16:16 +01:00
" ersscg1 " ) ;
2008-07-02 10:56:40 +02:00
return ZFCP_ERP_EXIT ;
}
2005-04-16 15:20:36 -07:00
break ;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED :
case ZFCP_ERP_ACTION_REOPEN_PORT :
2008-07-02 10:56:40 +02:00
if ( zfcp_erp_strat_change_det ( & port - > status , erp_status ) ) {
_zfcp_erp_port_reopen ( port ,
ZFCP_STATUS_COMMON_ERP_FAILED ,
2010-12-02 15:16:16 +01:00
" ersscg2 " ) ;
2008-07-02 10:56:40 +02:00
return ZFCP_ERP_EXIT ;
}
2005-04-16 15:20:36 -07:00
break ;
2010-09-08 14:39:55 +02:00
case ZFCP_ERP_ACTION_REOPEN_LUN :
zfcp_sdev = sdev_to_zfcp ( sdev ) ;
if ( zfcp_erp_strat_change_det ( & zfcp_sdev - > status , erp_status ) ) {
_zfcp_erp_lun_reopen ( sdev ,
ZFCP_STATUS_COMMON_ERP_FAILED ,
2010-12-02 15:16:16 +01:00
" ersscg3 " , 0 ) ;
2008-07-02 10:56:40 +02:00
return ZFCP_ERP_EXIT ;
}
2005-04-16 15:20:36 -07:00
break ;
}
2008-07-02 10:56:40 +02:00
return ret ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static void zfcp_erp_action_dequeue ( struct zfcp_erp_action * erp_action )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
struct zfcp_adapter * adapter = erp_action - > adapter ;
2010-09-08 14:39:55 +02:00
struct zfcp_scsi_dev * zfcp_sdev ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
adapter - > erp_total_count - - ;
if ( erp_action - > status & ZFCP_STATUS_ERP_LOWMEM ) {
adapter - > erp_low_mem_count - - ;
erp_action - > status & = ~ ZFCP_STATUS_ERP_LOWMEM ;
2008-03-27 14:22:05 +01:00
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
list_del ( & erp_action - > list ) ;
2010-12-02 15:16:12 +01:00
zfcp_dbf_rec_run ( " eractd1 " , erp_action ) ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
switch ( erp_action - > action ) {
2010-09-08 14:39:55 +02:00
case ZFCP_ERP_ACTION_REOPEN_LUN :
zfcp_sdev = sdev_to_zfcp ( erp_action - > sdev ) ;
2008-07-02 10:56:40 +02:00
atomic_clear_mask ( ZFCP_STATUS_COMMON_ERP_INUSE ,
2010-09-08 14:39:55 +02:00
& zfcp_sdev - > status ) ;
2008-07-02 10:56:40 +02:00
break ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED :
case ZFCP_ERP_ACTION_REOPEN_PORT :
atomic_clear_mask ( ZFCP_STATUS_COMMON_ERP_INUSE ,
& erp_action - > port - > status ) ;
break ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
case ZFCP_ERP_ACTION_REOPEN_ADAPTER :
atomic_clear_mask ( ZFCP_STATUS_COMMON_ERP_INUSE ,
& erp_action - > adapter - > status ) ;
break ;
}
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static void zfcp_erp_action_cleanup ( struct zfcp_erp_action * act , int result )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
struct zfcp_adapter * adapter = act - > adapter ;
struct zfcp_port * port = act - > port ;
2010-09-08 14:39:55 +02:00
struct scsi_device * sdev = act - > sdev ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
switch ( act - > action ) {
2010-09-08 14:39:55 +02:00
case ZFCP_ERP_ACTION_REOPEN_LUN :
2010-09-08 14:39:54 +02:00
if ( ! ( act - > status & ZFCP_STATUS_ERP_NO_REF ) )
2010-09-08 14:39:55 +02:00
scsi_device_put ( sdev ) ;
2008-07-02 10:56:40 +02:00
break ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
case ZFCP_ERP_ACTION_REOPEN_PORT :
2009-03-02 13:09:08 +01:00
if ( result = = ZFCP_ERP_SUCCEEDED )
zfcp_scsi_schedule_rport_register ( port ) ;
2010-07-08 09:53:05 +02:00
/* fall through */
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED :
2010-02-17 11:18:56 +01:00
put_device ( & port - > dev ) ;
2008-07-02 10:56:40 +02:00
break ;
case ZFCP_ERP_ACTION_REOPEN_ADAPTER :
2009-03-02 13:09:08 +01:00
if ( result = = ZFCP_ERP_SUCCEEDED ) {
2008-12-25 13:38:50 +01:00
register_service_level ( & adapter - > service_level ) ;
2009-11-24 16:54:06 +01:00
queue_work ( adapter - > work_queue , & adapter - > scan_work ) ;
2011-02-22 19:54:48 +01:00
queue_work ( adapter - > work_queue , & adapter - > ns_up_work ) ;
2009-03-02 13:09:08 +01:00
} else
unregister_service_level ( & adapter - > service_level ) ;
2011-02-22 19:54:48 +01:00
2009-11-24 16:53:59 +01:00
kref_put ( & adapter - > ref , zfcp_adapter_release ) ;
2008-07-02 10:56:40 +02:00
break ;
}
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_strategy_do_action ( struct zfcp_erp_action * erp_action )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
switch ( erp_action - > action ) {
case ZFCP_ERP_ACTION_REOPEN_ADAPTER :
return zfcp_erp_adapter_strategy ( erp_action ) ;
case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED :
return zfcp_erp_port_forced_strategy ( erp_action ) ;
case ZFCP_ERP_ACTION_REOPEN_PORT :
return zfcp_erp_port_strategy ( erp_action ) ;
2010-09-08 14:39:55 +02:00
case ZFCP_ERP_ACTION_REOPEN_LUN :
return zfcp_erp_lun_strategy ( erp_action ) ;
2008-07-02 10:56:40 +02:00
}
return ZFCP_ERP_FAILED ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_strategy ( struct zfcp_erp_action * erp_action )
2005-04-16 15:20:36 -07:00
{
int retval ;
2008-07-02 10:56:40 +02:00
unsigned long flags ;
2009-11-24 16:53:58 +01:00
struct zfcp_adapter * adapter = erp_action - > adapter ;
2005-04-16 15:20:36 -07:00
2009-11-24 16:53:59 +01:00
kref_get ( & adapter - > ref ) ;
2005-04-16 15:20:36 -07:00
2009-11-24 16:53:59 +01:00
write_lock_irqsave ( & adapter - > erp_lock , flags ) ;
2008-07-02 10:56:40 +02:00
zfcp_erp_strategy_check_fsfreq ( erp_action ) ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
if ( erp_action - > status & ZFCP_STATUS_ERP_DISMISSED ) {
zfcp_erp_action_dequeue ( erp_action ) ;
retval = ZFCP_ERP_DISMISSED ;
goto unlock ;
2005-06-13 13:15:15 +02:00
}
2005-04-16 15:20:36 -07:00
2010-07-08 09:53:09 +02:00
if ( erp_action - > status & ZFCP_STATUS_ERP_TIMEDOUT ) {
retval = ZFCP_ERP_FAILED ;
goto check_target ;
}
2006-02-11 01:41:50 +01:00
zfcp_erp_action_to_running ( erp_action ) ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
/* no lock to allow for blocking operations */
2009-11-24 16:53:58 +01:00
write_unlock_irqrestore ( & adapter - > erp_lock , flags ) ;
2008-07-02 10:56:40 +02:00
retval = zfcp_erp_strategy_do_action ( erp_action ) ;
2009-11-24 16:53:58 +01:00
write_lock_irqsave ( & adapter - > erp_lock , flags ) ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
if ( erp_action - > status & ZFCP_STATUS_ERP_DISMISSED )
retval = ZFCP_ERP_CONTINUES ;
2008-06-10 18:21:00 +02:00
2008-07-02 10:56:40 +02:00
switch ( retval ) {
case ZFCP_ERP_NOMEM :
if ( ! ( erp_action - > status & ZFCP_STATUS_ERP_LOWMEM ) ) {
+ + adapter - > erp_low_mem_count ;
erp_action - > status | = ZFCP_STATUS_ERP_LOWMEM ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
if ( adapter - > erp_total_count = = adapter - > erp_low_mem_count )
2010-12-02 15:16:16 +01:00
_zfcp_erp_adapter_reopen ( adapter , 0 , " erstgy1 " ) ;
2008-07-02 10:56:40 +02:00
else {
zfcp_erp_strategy_memwait ( erp_action ) ;
retval = ZFCP_ERP_CONTINUES ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
goto unlock ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
case ZFCP_ERP_CONTINUES :
if ( erp_action - > status & ZFCP_STATUS_ERP_LOWMEM ) {
- - adapter - > erp_low_mem_count ;
erp_action - > status & = ~ ZFCP_STATUS_ERP_LOWMEM ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
goto unlock ;
2005-04-16 15:20:36 -07:00
}
2010-07-08 09:53:09 +02:00
check_target :
2008-07-02 10:56:40 +02:00
retval = zfcp_erp_strategy_check_target ( erp_action , retval ) ;
zfcp_erp_action_dequeue ( erp_action ) ;
retval = zfcp_erp_strategy_statechange ( erp_action , retval ) ;
if ( retval = = ZFCP_ERP_EXIT )
goto unlock ;
2009-07-13 15:06:09 +02:00
if ( retval = = ZFCP_ERP_SUCCEEDED )
zfcp_erp_strategy_followup_success ( erp_action ) ;
if ( retval = = ZFCP_ERP_FAILED )
zfcp_erp_strategy_followup_failed ( erp_action ) ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
unlock :
2009-11-24 16:53:58 +01:00
write_unlock_irqrestore ( & adapter - > erp_lock , flags ) ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
if ( retval ! = ZFCP_ERP_CONTINUES )
zfcp_erp_action_cleanup ( erp_action , retval ) ;
2005-04-16 15:20:36 -07:00
2009-11-24 16:53:59 +01:00
kref_put ( & adapter - > ref , zfcp_adapter_release ) ;
2005-04-16 15:20:36 -07:00
return retval ;
}
2008-07-02 10:56:40 +02:00
static int zfcp_erp_thread ( void * data )
2005-04-16 15:20:36 -07:00
{
2008-07-02 10:56:40 +02:00
struct zfcp_adapter * adapter = ( struct zfcp_adapter * ) data ;
struct list_head * next ;
struct zfcp_erp_action * act ;
unsigned long flags ;
2009-04-17 15:08:06 +02:00
2009-08-18 15:43:25 +02:00
for ( ; ; ) {
wait_event_interruptible ( adapter - > erp_ready_wq ,
! list_empty ( & adapter - > erp_ready_head ) | |
kthread_should_stop ( ) ) ;
2009-04-17 15:08:06 +02:00
2009-08-18 15:43:25 +02:00
if ( kthread_should_stop ( ) )
break ;
2008-07-02 10:56:40 +02:00
write_lock_irqsave ( & adapter - > erp_lock , flags ) ;
next = adapter - > erp_ready_head . next ;
write_unlock_irqrestore ( & adapter - > erp_lock , flags ) ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
if ( next ! = & adapter - > erp_ready_head ) {
act = list_entry ( next , struct zfcp_erp_action , list ) ;
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
/* there is more to come after dismission, no notify */
if ( zfcp_erp_strategy ( act ) ! = ZFCP_ERP_DISMISSED )
zfcp_erp_wakeup ( adapter ) ;
2005-04-16 15:20:36 -07:00
}
}
2008-07-02 10:56:40 +02:00
return 0 ;
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
/**
* zfcp_erp_thread_setup - Start ERP thread for adapter
* @ adapter : Adapter to start the ERP thread for
*
* Returns 0 on success or error code from kernel_thread ( )
*/
int zfcp_erp_thread_setup ( struct zfcp_adapter * adapter )
{
2009-08-18 15:43:25 +02:00
struct task_struct * thread ;
2005-04-16 15:20:36 -07:00
2009-08-18 15:43:25 +02:00
thread = kthread_run ( zfcp_erp_thread , adapter , " zfcperp%s " ,
dev_name ( & adapter - > ccw_device - > dev ) ) ;
if ( IS_ERR ( thread ) ) {
2008-07-02 10:56:40 +02:00
dev_err ( & adapter - > ccw_device - > dev ,
2008-10-01 12:42:15 +02:00
" Creating an ERP thread for the FCP device failed. \n " ) ;
2009-08-18 15:43:25 +02:00
return PTR_ERR ( thread ) ;
2005-04-16 15:20:36 -07:00
}
2009-08-18 15:43:25 +02:00
adapter - > erp_thread = thread ;
2008-07-02 10:56:40 +02:00
return 0 ;
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
/**
* zfcp_erp_thread_kill - Stop ERP thread .
* @ adapter : Adapter where the ERP thread should be stopped .
*
* The caller of this routine ensures that the specified adapter has
* been shut down and that this operation has been completed . Thus ,
* there are no pending erp_actions which would need to be handled
* here .
*/
void zfcp_erp_thread_kill ( struct zfcp_adapter * adapter )
{
2009-08-18 15:43:25 +02:00
kthread_stop ( adapter - > erp_thread ) ;
adapter - > erp_thread = NULL ;
2009-08-18 15:43:27 +02:00
WARN_ON ( ! list_empty ( & adapter - > erp_ready_head ) ) ;
WARN_ON ( ! list_empty ( & adapter - > erp_running_head ) ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
/**
2010-09-08 14:40:01 +02:00
* zfcp_erp_wait - wait for completion of error recovery on an adapter
* @ adapter : adapter for which to wait for completion of its error recovery
2008-07-02 10:56:40 +02:00
*/
2010-09-08 14:40:01 +02:00
void zfcp_erp_wait ( struct zfcp_adapter * adapter )
2005-04-16 15:20:36 -07:00
{
2010-09-08 14:40:01 +02:00
wait_event ( adapter - > erp_done_wqh ,
! ( atomic_read ( & adapter - > status ) &
ZFCP_STATUS_ADAPTER_ERP_PENDING ) ) ;
2008-07-02 10:56:40 +02:00
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
/**
2010-09-08 14:40:01 +02:00
* zfcp_erp_set_adapter_status - set adapter status bits
* @ adapter : adapter to change the status
* @ mask : status bits to change
*
* Changes in common status bits are propagated to attached ports and LUNs .
2008-07-02 10:56:40 +02:00
*/
2010-09-08 14:40:01 +02:00
void zfcp_erp_set_adapter_status ( struct zfcp_adapter * adapter , u32 mask )
2008-07-02 10:56:40 +02:00
{
2010-09-08 14:40:01 +02:00
struct zfcp_port * port ;
struct scsi_device * sdev ;
unsigned long flags ;
u32 common_mask = mask & ZFCP_COMMON_FLAGS ;
2005-04-16 15:20:36 -07:00
2010-09-08 14:40:01 +02:00
atomic_set_mask ( mask , & adapter - > status ) ;
2005-04-16 15:20:36 -07:00
2010-09-08 14:40:01 +02:00
if ( ! common_mask )
return ;
read_lock_irqsave ( & adapter - > port_list_lock , flags ) ;
list_for_each_entry ( port , & adapter - > port_list , list )
atomic_set_mask ( common_mask , & port - > status ) ;
read_unlock_irqrestore ( & adapter - > port_list_lock , flags ) ;
shost_for_each_device ( sdev , adapter - > scsi_host )
atomic_set_mask ( common_mask , & sdev_to_zfcp ( sdev ) - > status ) ;
2008-07-02 10:56:40 +02:00
}
2005-04-16 15:20:36 -07:00
2008-07-02 10:56:40 +02:00
/**
2010-09-08 14:40:01 +02:00
* zfcp_erp_clear_adapter_status - clear adapter status bits
2008-07-02 10:56:40 +02:00
* @ adapter : adapter to change the status
* @ mask : status bits to change
*
2010-09-08 14:39:55 +02:00
* Changes in common status bits are propagated to attached ports and LUNs .
2008-07-02 10:56:40 +02:00
*/
2010-09-08 14:40:01 +02:00
void zfcp_erp_clear_adapter_status ( struct zfcp_adapter * adapter , u32 mask )
2005-04-16 15:20:36 -07:00
{
struct zfcp_port * port ;
2010-09-08 14:40:01 +02:00
struct scsi_device * sdev ;
2009-11-24 16:53:58 +01:00
unsigned long flags ;
2008-07-02 10:56:40 +02:00
u32 common_mask = mask & ZFCP_COMMON_FLAGS ;
2010-09-08 14:40:01 +02:00
u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED ;
2005-04-16 15:20:36 -07:00
2010-09-08 14:40:01 +02:00
atomic_clear_mask ( mask , & adapter - > status ) ;
if ( ! common_mask )
return ;
if ( clear_counter )
atomic_set ( & adapter - > erp_counter , 0 ) ;
read_lock_irqsave ( & adapter - > port_list_lock , flags ) ;
list_for_each_entry ( port , & adapter - > port_list , list ) {
atomic_clear_mask ( common_mask , & port - > status ) ;
if ( clear_counter )
atomic_set ( & port - > erp_counter , 0 ) ;
2008-07-02 10:56:40 +02:00
}
2010-09-08 14:40:01 +02:00
read_unlock_irqrestore ( & adapter - > port_list_lock , flags ) ;
2008-07-02 10:56:40 +02:00
2010-09-08 14:40:01 +02:00
shost_for_each_device ( sdev , adapter - > scsi_host ) {
atomic_clear_mask ( common_mask , & sdev_to_zfcp ( sdev ) - > status ) ;
if ( clear_counter )
atomic_set ( & sdev_to_zfcp ( sdev ) - > erp_counter , 0 ) ;
2009-11-24 16:53:58 +01:00
}
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
/**
2010-09-08 14:40:01 +02:00
* zfcp_erp_set_port_status - set port status bits
* @ port : port to change the status
2008-07-02 10:56:40 +02:00
* @ mask : status bits to change
*
2010-09-08 14:39:55 +02:00
* Changes in common status bits are propagated to attached LUNs .
2008-07-02 10:56:40 +02:00
*/
2010-09-08 14:40:01 +02:00
void zfcp_erp_set_port_status ( struct zfcp_port * port , u32 mask )
2005-04-16 15:20:36 -07:00
{
2010-09-08 14:39:55 +02:00
struct scsi_device * sdev ;
2008-07-02 10:56:40 +02:00
u32 common_mask = mask & ZFCP_COMMON_FLAGS ;
2005-04-16 15:20:36 -07:00
2010-09-08 14:40:01 +02:00
atomic_set_mask ( mask , & port - > status ) ;
2005-04-16 15:20:36 -07:00
2010-09-08 14:40:01 +02:00
if ( ! common_mask )
return ;
shost_for_each_device ( sdev , port - > adapter - > scsi_host )
if ( sdev_to_zfcp ( sdev ) - > port = = port )
atomic_set_mask ( common_mask ,
& sdev_to_zfcp ( sdev ) - > status ) ;
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
/**
2010-09-08 14:40:01 +02:00
* zfcp_erp_clear_port_status - clear port status bits
* @ port : adapter to change the status
2008-07-02 10:56:40 +02:00
* @ mask : status bits to change
2010-09-08 14:40:01 +02:00
*
* Changes in common status bits are propagated to attached LUNs .
2008-07-02 10:56:40 +02:00
*/
2010-09-08 14:40:01 +02:00
void zfcp_erp_clear_port_status ( struct zfcp_port * port , u32 mask )
2005-04-16 15:20:36 -07:00
{
2010-09-08 14:40:01 +02:00
struct scsi_device * sdev ;
u32 common_mask = mask & ZFCP_COMMON_FLAGS ;
u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED ;
atomic_clear_mask ( mask , & port - > status ) ;
if ( ! common_mask )
return ;
2010-09-08 14:39:55 +02:00
2010-09-08 14:40:01 +02:00
if ( clear_counter )
atomic_set ( & port - > erp_counter , 0 ) ;
shost_for_each_device ( sdev , port - > adapter - > scsi_host )
if ( sdev_to_zfcp ( sdev ) - > port = = port ) {
atomic_clear_mask ( common_mask ,
& sdev_to_zfcp ( sdev ) - > status ) ;
if ( clear_counter )
atomic_set ( & sdev_to_zfcp ( sdev ) - > erp_counter , 0 ) ;
2008-07-02 10:56:40 +02:00
}
2005-04-16 15:20:36 -07:00
}
2008-07-02 10:56:40 +02:00
/**
2010-09-08 14:40:01 +02:00
* zfcp_erp_set_lun_status - set lun status bits
* @ sdev : SCSI device / lun to set the status bits
* @ mask : status bits to change
2008-07-02 10:56:40 +02:00
*/
2010-09-08 14:40:01 +02:00
void zfcp_erp_set_lun_status ( struct scsi_device * sdev , u32 mask )
2005-06-13 13:23:57 +02:00
{
2010-09-08 14:40:01 +02:00
struct zfcp_scsi_dev * zfcp_sdev = sdev_to_zfcp ( sdev ) ;
atomic_set_mask ( mask , & zfcp_sdev - > status ) ;
2005-06-13 13:23:57 +02:00
}
2008-07-02 10:56:40 +02:00
/**
2010-09-08 14:40:01 +02:00
* zfcp_erp_clear_lun_status - clear lun status bits
* @ sdev : SCSi device / lun to clear the status bits
* @ mask : status bits to change
2008-07-02 10:56:40 +02:00
*/
2010-09-08 14:40:01 +02:00
void zfcp_erp_clear_lun_status ( struct scsi_device * sdev , u32 mask )
2005-06-13 13:23:57 +02:00
{
2010-09-08 14:40:01 +02:00
struct zfcp_scsi_dev * zfcp_sdev = sdev_to_zfcp ( sdev ) ;
atomic_clear_mask ( mask , & zfcp_sdev - > status ) ;
if ( mask & ZFCP_STATUS_COMMON_ERP_FAILED )
atomic_set ( & zfcp_sdev - > erp_counter , 0 ) ;
2005-06-13 13:23:57 +02:00
}
2010-09-08 14:40:01 +02:00