Commit 65d430fa authored by Christof Schmitt's avatar Christof Schmitt Committed by James Bottomley

[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: default avatarJames Smart <james.smart@emulex.com>
Acked-by: default avatarGiridhar Malavali <giridhar.malavali@qlogic.com>
Acked-by: default avatarAbhijeet Joglekar <abjoglek@cisco.com>
Signed-off-by: default avatarChristof Schmitt <christof.schmitt@de.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 03b14708
...@@ -1225,22 +1225,6 @@ void fnic_terminate_rport_io(struct fc_rport *rport) ...@@ -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) ...@@ -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) ...@@ -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 *)) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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, ...@@ -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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment