aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/lpfc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c28
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c19
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c83
3 files changed, 37 insertions, 93 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 56052f4510c..6c846ad373b 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -1028,6 +1028,7 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
if (ndlp->nlp_type & NLP_FCP_INITIATOR)
rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+ scsi_block_requests(phba->host);
ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids);
if (!rport) {
dev_printk(KERN_WARNING, &phba->pcidev->dev,
@@ -1044,6 +1045,23 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
}
rdata = rport->dd_data;
rdata->pnode = ndlp;
+ scsi_unblock_requests(phba->host);
+
+ return;
+}
+
+static void
+lpfc_unregister_remote_port(struct lpfc_hba * phba,
+ struct lpfc_nodelist * ndlp)
+{
+ struct fc_rport *rport = ndlp->rport;
+ struct lpfc_rport_data *rdata = rport->dd_data;
+
+ ndlp->rport = NULL;
+ rdata->pnode = NULL;
+ scsi_block_requests(phba->host);
+ fc_remote_port_delete(rport);
+ scsi_unblock_requests(phba->host);
return;
}
@@ -1260,7 +1278,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
* may have removed the remote port.
*/
if ((rport_del != none) && nlp->rport)
- fc_remote_port_block(nlp->rport);
+ lpfc_unregister_remote_port(phba, nlp);
if (rport_add != none) {
/*
@@ -1270,8 +1288,6 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
*/
if (!nlp->rport)
lpfc_register_remote_port(phba, nlp);
- else
- fc_remote_port_unblock(nlp->rport);
/*
* if we added to Mapped list, but the remote port
@@ -1490,7 +1506,6 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
LPFC_MBOXQ_t *mb;
LPFC_MBOXQ_t *nextmb;
struct lpfc_dmabuf *mp;
- struct fc_rport *rport;
/* Cleanup node for NPort <nlp_DID> */
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
@@ -1507,10 +1522,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
* and flush cache's w/o generating flush errors.
*/
if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
- rport = ndlp->rport;
- ndlp->rport = NULL;
- fc_remote_port_unblock(rport);
- fc_remote_port_delete(rport);
+ lpfc_unregister_remote_port(phba, ndlp);
ndlp->nlp_sid = NLP_NO_SID;
}
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 0856ff7d3b3..25d55f40424 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -537,12 +537,6 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
lpfc_offline(phba);
- /*
- * Restart all traffic to this host. Since the fc_transport
- * block functions (future) were not called in lpfc_offline,
- * don't call them here.
- */
- scsi_unblock_requests(phba->host);
}
}
@@ -1226,12 +1220,6 @@ lpfc_online(struct lpfc_hba * phba)
phba->fc_flag &= ~FC_OFFLINE_MODE;
spin_unlock_irq(phba->host->host_lock);
- /*
- * Restart all traffic to this host. Since the fc_transport block
- * functions (future) were not called in lpfc_offline, don't call them
- * here.
- */
- scsi_unblock_requests(phba->host);
return 0;
}
@@ -1249,13 +1237,6 @@ lpfc_offline(struct lpfc_hba * phba)
if (phba->fc_flag & FC_OFFLINE_MODE)
return 0;
- /*
- * Don't call the fc_transport block api (future). The device is
- * going offline and causing a timer to fire in the midlayer is
- * unproductive. Just block all new requests until the driver
- * comes back online.
- */
- scsi_block_requests(phba->host);
psli = &phba->sli;
pring = &psli->ring[psli->fcp_ring];
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index b5ad1871d34..c55ab1a630e 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -403,14 +403,9 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
break;
}
- if (pnode) {
- if (pnode->nlp_state != NLP_STE_MAPPED_NODE)
- cmd->result = ScsiResult(DID_BUS_BUSY,
- SAM_STAT_BUSY);
- }
- else {
- cmd->result = ScsiResult(DID_NO_CONNECT, 0);
- }
+ if ((pnode == NULL )
+ || (pnode->nlp_state != NLP_STE_MAPPED_NODE))
+ cmd->result = ScsiResult(DID_BUS_BUSY, SAM_STAT_BUSY);
} else {
cmd->result = ScsiResult(DID_OK, 0);
}
@@ -539,7 +534,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
struct lpfc_rport_data *rdata = scsi_dev->hostdata;
struct lpfc_nodelist *ndlp = rdata->pnode;
- if ((ndlp == 0) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
+ if ((ndlp == NULL) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
return 0;
}
@@ -727,39 +722,23 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
struct lpfc_rport_data *rdata = cmnd->device->hostdata;
struct lpfc_nodelist *ndlp = rdata->pnode;
struct lpfc_scsi_buf *lpfc_cmd = NULL;
+ struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
- int err = 0;
+ int err;
- /*
- * The target pointer is guaranteed not to be NULL because the driver
- * only clears the device->hostdata field in lpfc_slave_destroy. This
- * approach guarantees no further IO calls on this target.
- */
- if (!ndlp) {
- cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
+ err = fc_remote_port_chkready(rport);
+ if (err) {
+ cmnd->result = err;
goto out_fail_command;
}
/*
- * A Fibre Channel target is present and functioning only when the node
- * state is MAPPED. Any other state is a failure.
+ * Catch race where our node has transitioned, but the
+ * transport is still transitioning.
*/
- if (ndlp->nlp_state != NLP_STE_MAPPED_NODE) {
- if ((ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) ||
- (ndlp->nlp_state == NLP_STE_UNUSED_NODE)) {
- cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
- goto out_fail_command;
- }
- else if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
- cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
- goto out_fail_command;
- }
- /*
- * The device is most likely recovered and the driver
- * needs a bit more time to finish. Ask the midlayer
- * to retry.
- */
- goto out_host_busy;
+ if (!ndlp) {
+ cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
+ goto out_fail_command;
}
list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
@@ -1163,44 +1142,16 @@ static int
lpfc_slave_alloc(struct scsi_device *sdev)
{
struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata[0];
- struct lpfc_nodelist *ndlp = NULL;
- int match = 0;
struct lpfc_scsi_buf *scsi_buf = NULL;
+ struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
uint32_t total = 0, i;
uint32_t num_to_alloc = 0;
unsigned long flags;
- struct list_head *listp;
- struct list_head *node_list[6];
-
- /*
- * Store the target pointer in the scsi_device hostdata pointer provided
- * the driver has already discovered the target id.
- */
-
- /* Search the nlp lists other than unmap_list for this target ID */
- node_list[0] = &phba->fc_npr_list;
- node_list[1] = &phba->fc_nlpmap_list;
- node_list[2] = &phba->fc_prli_list;
- node_list[3] = &phba->fc_reglogin_list;
- node_list[4] = &phba->fc_adisc_list;
- node_list[5] = &phba->fc_plogi_list;
-
- for (i = 0; i < 6 && !match; i++) {
- listp = node_list[i];
- if (list_empty(listp))
- continue;
- list_for_each_entry(ndlp, listp, nlp_listp) {
- if ((sdev->id == ndlp->nlp_sid) && ndlp->rport) {
- match = 1;
- break;
- }
- }
- }
- if (!match)
+ if (!rport || fc_remote_port_chkready(rport))
return -ENXIO;
- sdev->hostdata = ndlp->rport->dd_data;
+ sdev->hostdata = rport->dd_data;
/*
* Populate the cmds_per_lun count scsi_bufs into this host's globally