[SCSI] scsi_transport_fc: Introduce helper function for blocking scsi_eh
Move the duplicated code from FC LLDs to SCSI FC transport class. Acked-by: James Smart <james.smart@emulex.com> Acked-by: Giridhar Malavali <giridhar.malavali@qlogic.com> Acked-by: Abhijeet Joglekar <abjoglek@cisco.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
committed by
James Bottomley
parent
03b147083a
commit
65d430fa99
@@ -1225,22 +1225,6 @@ void fnic_terminate_rport_io(struct fc_rport *rport)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fnic_block_error_handler(struct scsi_cmnd *sc)
|
|
||||||
{
|
|
||||||
struct Scsi_Host *shost = sc->device->host;
|
|
||||||
struct fc_rport *rport = starget_to_rport(scsi_target(sc->device));
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(shost->host_lock, flags);
|
|
||||||
while (rport->port_state == FC_PORTSTATE_BLOCKED) {
|
|
||||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
|
||||||
msleep(1000);
|
|
||||||
spin_lock_irqsave(shost->host_lock, flags);
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is exported to SCSI for sending abort cmnds.
|
* This function is exported to SCSI for sending abort cmnds.
|
||||||
* A SCSI IO is represented by a io_req in the driver.
|
* A SCSI IO is represented by a io_req in the driver.
|
||||||
@@ -1260,7 +1244,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc)
|
|||||||
DECLARE_COMPLETION_ONSTACK(tm_done);
|
DECLARE_COMPLETION_ONSTACK(tm_done);
|
||||||
|
|
||||||
/* Wait for rport to unblock */
|
/* Wait for rport to unblock */
|
||||||
fnic_block_error_handler(sc);
|
fc_block_scsi_eh(sc);
|
||||||
|
|
||||||
/* Get local-port, check ready and link up */
|
/* Get local-port, check ready and link up */
|
||||||
lp = shost_priv(sc->device->host);
|
lp = shost_priv(sc->device->host);
|
||||||
@@ -1542,7 +1526,7 @@ int fnic_device_reset(struct scsi_cmnd *sc)
|
|||||||
DECLARE_COMPLETION_ONSTACK(tm_done);
|
DECLARE_COMPLETION_ONSTACK(tm_done);
|
||||||
|
|
||||||
/* Wait for rport to unblock */
|
/* Wait for rport to unblock */
|
||||||
fnic_block_error_handler(sc);
|
fc_block_scsi_eh(sc);
|
||||||
|
|
||||||
/* Get local-port, check ready and link up */
|
/* Get local-port, check ready and link up */
|
||||||
lp = shost_priv(sc->device->host);
|
lp = shost_priv(sc->device->host);
|
||||||
|
@@ -2916,28 +2916,6 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* lpfc_block_error_handler - Routine to block error handler
|
|
||||||
* @cmnd: Pointer to scsi_cmnd data structure.
|
|
||||||
*
|
|
||||||
* This routine blocks execution till fc_rport state is not FC_PORSTAT_BLCOEKD.
|
|
||||||
**/
|
|
||||||
static void
|
|
||||||
lpfc_block_error_handler(struct scsi_cmnd *cmnd)
|
|
||||||
{
|
|
||||||
struct Scsi_Host *shost = cmnd->device->host;
|
|
||||||
struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
|
|
||||||
|
|
||||||
spin_lock_irq(shost->host_lock);
|
|
||||||
while (rport->port_state == FC_PORTSTATE_BLOCKED) {
|
|
||||||
spin_unlock_irq(shost->host_lock);
|
|
||||||
msleep(1000);
|
|
||||||
spin_lock_irq(shost->host_lock);
|
|
||||||
}
|
|
||||||
spin_unlock_irq(shost->host_lock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lpfc_abort_handler - scsi_host_template eh_abort_handler entry point
|
* lpfc_abort_handler - scsi_host_template eh_abort_handler entry point
|
||||||
* @cmnd: Pointer to scsi_cmnd data structure.
|
* @cmnd: Pointer to scsi_cmnd data structure.
|
||||||
@@ -2961,7 +2939,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
|
|||||||
int ret = SUCCESS;
|
int ret = SUCCESS;
|
||||||
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
|
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
|
||||||
|
|
||||||
lpfc_block_error_handler(cmnd);
|
fc_block_scsi_eh(cmnd);
|
||||||
lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
|
lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
|
||||||
BUG_ON(!lpfc_cmd);
|
BUG_ON(!lpfc_cmd);
|
||||||
|
|
||||||
@@ -3259,7 +3237,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
|
|||||||
struct lpfc_scsi_event_header scsi_event;
|
struct lpfc_scsi_event_header scsi_event;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
lpfc_block_error_handler(cmnd);
|
fc_block_scsi_eh(cmnd);
|
||||||
|
|
||||||
status = lpfc_chk_tgt_mapped(vport, cmnd);
|
status = lpfc_chk_tgt_mapped(vport, cmnd);
|
||||||
if (status == FAILED) {
|
if (status == FAILED) {
|
||||||
@@ -3318,7 +3296,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd)
|
|||||||
struct lpfc_scsi_event_header scsi_event;
|
struct lpfc_scsi_event_header scsi_event;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
lpfc_block_error_handler(cmnd);
|
fc_block_scsi_eh(cmnd);
|
||||||
|
|
||||||
status = lpfc_chk_tgt_mapped(vport, cmnd);
|
status = lpfc_chk_tgt_mapped(vport, cmnd);
|
||||||
if (status == FAILED) {
|
if (status == FAILED) {
|
||||||
@@ -3384,7 +3362,7 @@ lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
|
|||||||
fc_host_post_vendor_event(shost, fc_get_event_number(),
|
fc_host_post_vendor_event(shost, fc_get_event_number(),
|
||||||
sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID);
|
sizeof(scsi_event), (char *)&scsi_event, LPFC_NL_VENDOR_ID);
|
||||||
|
|
||||||
lpfc_block_error_handler(cmnd);
|
fc_block_scsi_eh(cmnd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since the driver manages a single bus device, reset all
|
* Since the driver manages a single bus device, reset all
|
||||||
|
@@ -728,23 +728,6 @@ qla2x00_abort_fcport_cmds(fc_port_t *fcport)
|
|||||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
qla2x00_block_error_handler(struct scsi_cmnd *cmnd)
|
|
||||||
{
|
|
||||||
struct Scsi_Host *shost = cmnd->device->host;
|
|
||||||
struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(shost->host_lock, flags);
|
|
||||||
while (rport->port_state == FC_PORTSTATE_BLOCKED) {
|
|
||||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
|
||||||
msleep(1000);
|
|
||||||
spin_lock_irqsave(shost->host_lock, flags);
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* qla2xxx_eh_abort
|
* qla2xxx_eh_abort
|
||||||
*
|
*
|
||||||
@@ -774,7 +757,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
|||||||
struct req_que *req = vha->req;
|
struct req_que *req = vha->req;
|
||||||
srb_t *spt;
|
srb_t *spt;
|
||||||
|
|
||||||
qla2x00_block_error_handler(cmd);
|
fc_block_scsi_eh(cmd);
|
||||||
|
|
||||||
if (!CMD_SP(cmd))
|
if (!CMD_SP(cmd))
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
@@ -905,7 +888,7 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
|
|||||||
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
|
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
qla2x00_block_error_handler(cmd);
|
fc_block_scsi_eh(cmd);
|
||||||
|
|
||||||
if (!fcport)
|
if (!fcport)
|
||||||
return FAILED;
|
return FAILED;
|
||||||
@@ -985,7 +968,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
|
|||||||
unsigned long serial;
|
unsigned long serial;
|
||||||
srb_t *sp = (srb_t *) CMD_SP(cmd);
|
srb_t *sp = (srb_t *) CMD_SP(cmd);
|
||||||
|
|
||||||
qla2x00_block_error_handler(cmd);
|
fc_block_scsi_eh(cmd);
|
||||||
|
|
||||||
id = cmd->device->id;
|
id = cmd->device->id;
|
||||||
lun = cmd->device->lun;
|
lun = cmd->device->lun;
|
||||||
@@ -1048,7 +1031,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
|
|||||||
srb_t *sp = (srb_t *) CMD_SP(cmd);
|
srb_t *sp = (srb_t *) CMD_SP(cmd);
|
||||||
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
|
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
|
||||||
|
|
||||||
qla2x00_block_error_handler(cmd);
|
fc_block_scsi_eh(cmd);
|
||||||
|
|
||||||
id = cmd->device->id;
|
id = cmd->device->id;
|
||||||
lun = cmd->device->lun;
|
lun = cmd->device->lun;
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
#include <scsi/scsi_device.h>
|
#include <scsi/scsi_device.h>
|
||||||
#include <scsi/scsi_host.h>
|
#include <scsi/scsi_host.h>
|
||||||
#include <scsi/scsi_transport.h>
|
#include <scsi/scsi_transport.h>
|
||||||
@@ -3144,6 +3145,31 @@ fc_scsi_scan_rport(struct work_struct *work)
|
|||||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fc_block_scsi_eh - Block SCSI eh thread for blocked fc_rport
|
||||||
|
* @cmnd: SCSI command that scsi_eh is trying to recover
|
||||||
|
*
|
||||||
|
* This routine can be called from a FC LLD scsi_eh callback. It
|
||||||
|
* blocks the scsi_eh thread until the fc_rport leaves the
|
||||||
|
* FC_PORTSTATE_BLOCKED. This is necessary to avoid the scsi_eh
|
||||||
|
* failing recovery actions for blocked rports which would lead to
|
||||||
|
* offlined SCSI devices.
|
||||||
|
*/
|
||||||
|
void fc_block_scsi_eh(struct scsi_cmnd *cmnd)
|
||||||
|
{
|
||||||
|
struct Scsi_Host *shost = cmnd->device->host;
|
||||||
|
struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(shost->host_lock, flags);
|
||||||
|
while (rport->port_state == FC_PORTSTATE_BLOCKED) {
|
||||||
|
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||||
|
msleep(1000);
|
||||||
|
spin_lock_irqsave(shost->host_lock, flags);
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(fc_block_scsi_eh);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fc_vport_setup - allocates and creates a FC virtual port.
|
* fc_vport_setup - allocates and creates a FC virtual port.
|
||||||
|
@@ -807,5 +807,6 @@ void fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
|
|||||||
struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel,
|
struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel,
|
||||||
struct fc_vport_identifiers *);
|
struct fc_vport_identifiers *);
|
||||||
int fc_vport_terminate(struct fc_vport *vport);
|
int fc_vport_terminate(struct fc_vport *vport);
|
||||||
|
void fc_block_scsi_eh(struct scsi_cmnd *cmnd);
|
||||||
|
|
||||||
#endif /* SCSI_TRANSPORT_FC_H */
|
#endif /* SCSI_TRANSPORT_FC_H */
|
||||||
|
Reference in New Issue
Block a user