aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames.Smart@Emulex.Com <James.Smart@Emulex.Com>2005-10-18 12:03:35 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-10-28 22:20:07 -0400
commit19a7b4aebf9ad435c69a7e39930338499af4d152 (patch)
tree6d1c4cbc822009c8facb219dcd955d52070655d1
parent422c0d61d591cbfb70f029e13505fb437e169d68 (diff)
[SCSI] update fc_transport for removal of block/unblock functions
We recently went back to implement a board reset. When we perform the reset, we wanted to tear down the internal data structures and rebuild them. Unfortunately, when it came to the rport structure, things were odd. If we deleted them, the scsi targets and sdevs would be torn down. Not a good thing for a temporary reset. We could block the rports, but we either maintain the internal structures to keep the rport reference (perhaps even replicating what's in the transport), or we have to fatten the fc transport with new search routines to find the rport (and deal with a case of a dangling rport that the driver forgets). It dawned on me that we had actually reached this state incorrectly. When the fc transport first started, we did the block/unblock first, then added the rport interface. The purpose of block/unblock is to hide the temporary disappearance of the rport (e.g. being deleted, then readded). Why are we making the driver do the block/unblock ? We should be making the transport have only an rport add/delete, and the let the transport handle the block/unblock. So... This patch removes the existing fc_remote_port_block/unblock functions. It moves the block/unblock functionality into the fc_remote_port_add/delete functions. Updates for the lpfc driver are included. Qlogic driver updates are also enclosed, thanks to the contributions of Andrew Vasquez. [Note: the qla2xxx changes are relative to the scsi-misc-2.6 tree as of this morning - which does not include the recent patches sent by Andrew]. The zfcp driver does not use the block/unblock functions. One last comment: The resulting behavior feels very clean. The LLDD is concerned only with add/delete, which corresponds to the physical disappearance. However, the fact that the scsi target and sdevs are not immediately torn down after the LLDD calls delete causes an interesting scenario... the midlayer can call the xxx_slave_alloc and xxx_queuecommand functions with a sdev that is at the location the rport used to be. The driver must validate the device exists when it first enters these functions. In thinking about it, this has always been the case for the LLDD and these routines. The existing drivers already check for existence. However, this highlights that simple validation via data structure dereferencing needs to be watched. To deal with this, a new transport function, fc_remote_port_chkready() was created that LLDDs should call when they first enter these two routines. It validates the rport state, and returns a scsi result which could be returned. In addition to solving the above, it also creates consistent behavior from the LLDD's when the block and deletes are occuring. Rejections fixed up and Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-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
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h3
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c26
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c21
-rw-r--r--drivers/scsi/qla2xxx/qla_rscn.c3
-rw-r--r--drivers/scsi/scsi_transport_fc.c446
-rw-r--r--include/scsi/scsi_transport_fc.h31
9 files changed, 384 insertions, 276 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,
1028 if (ndlp->nlp_type & NLP_FCP_INITIATOR) 1028 if (ndlp->nlp_type & NLP_FCP_INITIATOR)
1029 rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR; 1029 rport_ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
1030 1030
1031 scsi_block_requests(phba->host);
1031 ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids); 1032 ndlp->rport = rport = fc_remote_port_add(phba->host, 0, &rport_ids);
1032 if (!rport) { 1033 if (!rport) {
1033 dev_printk(KERN_WARNING, &phba->pcidev->dev, 1034 dev_printk(KERN_WARNING, &phba->pcidev->dev,
@@ -1044,6 +1045,23 @@ lpfc_register_remote_port(struct lpfc_hba * phba,
1044 } 1045 }
1045 rdata = rport->dd_data; 1046 rdata = rport->dd_data;
1046 rdata->pnode = ndlp; 1047 rdata->pnode = ndlp;
1048 scsi_unblock_requests(phba->host);
1049
1050 return;
1051}
1052
1053static void
1054lpfc_unregister_remote_port(struct lpfc_hba * phba,
1055 struct lpfc_nodelist * ndlp)
1056{
1057 struct fc_rport *rport = ndlp->rport;
1058 struct lpfc_rport_data *rdata = rport->dd_data;
1059
1060 ndlp->rport = NULL;
1061 rdata->pnode = NULL;
1062 scsi_block_requests(phba->host);
1063 fc_remote_port_delete(rport);
1064 scsi_unblock_requests(phba->host);
1047 1065
1048 return; 1066 return;
1049} 1067}
@@ -1260,7 +1278,7 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
1260 * may have removed the remote port. 1278 * may have removed the remote port.
1261 */ 1279 */
1262 if ((rport_del != none) && nlp->rport) 1280 if ((rport_del != none) && nlp->rport)
1263 fc_remote_port_block(nlp->rport); 1281 lpfc_unregister_remote_port(phba, nlp);
1264 1282
1265 if (rport_add != none) { 1283 if (rport_add != none) {
1266 /* 1284 /*
@@ -1270,8 +1288,6 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
1270 */ 1288 */
1271 if (!nlp->rport) 1289 if (!nlp->rport)
1272 lpfc_register_remote_port(phba, nlp); 1290 lpfc_register_remote_port(phba, nlp);
1273 else
1274 fc_remote_port_unblock(nlp->rport);
1275 1291
1276 /* 1292 /*
1277 * if we added to Mapped list, but the remote port 1293 * if we added to Mapped list, but the remote port
@@ -1490,7 +1506,6 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
1490 LPFC_MBOXQ_t *mb; 1506 LPFC_MBOXQ_t *mb;
1491 LPFC_MBOXQ_t *nextmb; 1507 LPFC_MBOXQ_t *nextmb;
1492 struct lpfc_dmabuf *mp; 1508 struct lpfc_dmabuf *mp;
1493 struct fc_rport *rport;
1494 1509
1495 /* Cleanup node for NPort <nlp_DID> */ 1510 /* Cleanup node for NPort <nlp_DID> */
1496 lpfc_printf_log(phba, KERN_INFO, LOG_NODE, 1511 lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
@@ -1507,10 +1522,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
1507 * and flush cache's w/o generating flush errors. 1522 * and flush cache's w/o generating flush errors.
1508 */ 1523 */
1509 if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) { 1524 if ((ndlp->rport) && !(phba->fc_flag & FC_UNLOADING)) {
1510 rport = ndlp->rport; 1525 lpfc_unregister_remote_port(phba, ndlp);
1511 ndlp->rport = NULL;
1512 fc_remote_port_unblock(rport);
1513 fc_remote_port_delete(rport);
1514 ndlp->nlp_sid = NLP_NO_SID; 1526 ndlp->nlp_sid = NLP_NO_SID;
1515 } 1527 }
1516 1528
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)
537 537
538 lpfc_offline(phba); 538 lpfc_offline(phba);
539 539
540 /*
541 * Restart all traffic to this host. Since the fc_transport
542 * block functions (future) were not called in lpfc_offline,
543 * don't call them here.
544 */
545 scsi_unblock_requests(phba->host);
546 } 540 }
547} 541}
548 542
@@ -1226,12 +1220,6 @@ lpfc_online(struct lpfc_hba * phba)
1226 phba->fc_flag &= ~FC_OFFLINE_MODE; 1220 phba->fc_flag &= ~FC_OFFLINE_MODE;
1227 spin_unlock_irq(phba->host->host_lock); 1221 spin_unlock_irq(phba->host->host_lock);
1228 1222
1229 /*
1230 * Restart all traffic to this host. Since the fc_transport block
1231 * functions (future) were not called in lpfc_offline, don't call them
1232 * here.
1233 */
1234 scsi_unblock_requests(phba->host);
1235 return 0; 1223 return 0;
1236} 1224}
1237 1225
@@ -1249,13 +1237,6 @@ lpfc_offline(struct lpfc_hba * phba)
1249 if (phba->fc_flag & FC_OFFLINE_MODE) 1237 if (phba->fc_flag & FC_OFFLINE_MODE)
1250 return 0; 1238 return 0;
1251 1239
1252 /*
1253 * Don't call the fc_transport block api (future). The device is
1254 * going offline and causing a timer to fire in the midlayer is
1255 * unproductive. Just block all new requests until the driver
1256 * comes back online.
1257 */
1258 scsi_block_requests(phba->host);
1259 psli = &phba->sli; 1240 psli = &phba->sli;
1260 pring = &psli->ring[psli->fcp_ring]; 1241 pring = &psli->ring[psli->fcp_ring];
1261 1242
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,
403 break; 403 break;
404 } 404 }
405 405
406 if (pnode) { 406 if ((pnode == NULL )
407 if (pnode->nlp_state != NLP_STE_MAPPED_NODE) 407 || (pnode->nlp_state != NLP_STE_MAPPED_NODE))
408 cmd->result = ScsiResult(DID_BUS_BUSY, 408 cmd->result = ScsiResult(DID_BUS_BUSY, SAM_STAT_BUSY);
409 SAM_STAT_BUSY);
410 }
411 else {
412 cmd->result = ScsiResult(DID_NO_CONNECT, 0);
413 }
414 } else { 409 } else {
415 cmd->result = ScsiResult(DID_OK, 0); 410 cmd->result = ScsiResult(DID_OK, 0);
416 } 411 }
@@ -539,7 +534,7 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
539 struct lpfc_rport_data *rdata = scsi_dev->hostdata; 534 struct lpfc_rport_data *rdata = scsi_dev->hostdata;
540 struct lpfc_nodelist *ndlp = rdata->pnode; 535 struct lpfc_nodelist *ndlp = rdata->pnode;
541 536
542 if ((ndlp == 0) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) { 537 if ((ndlp == NULL) || (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
543 return 0; 538 return 0;
544 } 539 }
545 540
@@ -727,39 +722,23 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
727 struct lpfc_rport_data *rdata = cmnd->device->hostdata; 722 struct lpfc_rport_data *rdata = cmnd->device->hostdata;
728 struct lpfc_nodelist *ndlp = rdata->pnode; 723 struct lpfc_nodelist *ndlp = rdata->pnode;
729 struct lpfc_scsi_buf *lpfc_cmd = NULL; 724 struct lpfc_scsi_buf *lpfc_cmd = NULL;
725 struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
730 struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list; 726 struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
731 int err = 0; 727 int err;
732 728
733 /* 729 err = fc_remote_port_chkready(rport);
734 * The target pointer is guaranteed not to be NULL because the driver 730 if (err) {
735 * only clears the device->hostdata field in lpfc_slave_destroy. This 731 cmnd->result = err;
736 * approach guarantees no further IO calls on this target.
737 */
738 if (!ndlp) {
739 cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
740 goto out_fail_command; 732 goto out_fail_command;
741 } 733 }
742 734
743 /* 735 /*
744 * A Fibre Channel target is present and functioning only when the node 736 * Catch race where our node has transitioned, but the
745 * state is MAPPED. Any other state is a failure. 737 * transport is still transitioning.
746 */ 738 */
747 if (ndlp->nlp_state != NLP_STE_MAPPED_NODE) { 739 if (!ndlp) {
748 if ((ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) || 740 cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
749 (ndlp->nlp_state == NLP_STE_UNUSED_NODE)) { 741 goto out_fail_command;
750 cmnd->result = ScsiResult(DID_NO_CONNECT, 0);
751 goto out_fail_command;
752 }
753 else if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
754 cmnd->result = ScsiResult(DID_BUS_BUSY, 0);
755 goto out_fail_command;
756 }
757 /*
758 * The device is most likely recovered and the driver
759 * needs a bit more time to finish. Ask the midlayer
760 * to retry.
761 */
762 goto out_host_busy;
763 } 742 }
764 743
765 list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list); 744 list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
@@ -1163,44 +1142,16 @@ static int
1163lpfc_slave_alloc(struct scsi_device *sdev) 1142lpfc_slave_alloc(struct scsi_device *sdev)
1164{ 1143{
1165 struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata[0]; 1144 struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata[0];
1166 struct lpfc_nodelist *ndlp = NULL;
1167 int match = 0;
1168 struct lpfc_scsi_buf *scsi_buf = NULL; 1145 struct lpfc_scsi_buf *scsi_buf = NULL;
1146 struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
1169 uint32_t total = 0, i; 1147 uint32_t total = 0, i;
1170 uint32_t num_to_alloc = 0; 1148 uint32_t num_to_alloc = 0;
1171 unsigned long flags; 1149 unsigned long flags;
1172 struct list_head *listp;
1173 struct list_head *node_list[6];
1174
1175 /*
1176 * Store the target pointer in the scsi_device hostdata pointer provided
1177 * the driver has already discovered the target id.
1178 */
1179
1180 /* Search the nlp lists other than unmap_list for this target ID */
1181 node_list[0] = &phba->fc_npr_list;
1182 node_list[1] = &phba->fc_nlpmap_list;
1183 node_list[2] = &phba->fc_prli_list;
1184 node_list[3] = &phba->fc_reglogin_list;
1185 node_list[4] = &phba->fc_adisc_list;
1186 node_list[5] = &phba->fc_plogi_list;
1187
1188 for (i = 0; i < 6 && !match; i++) {
1189 listp = node_list[i];
1190 if (list_empty(listp))
1191 continue;
1192 list_for_each_entry(ndlp, listp, nlp_listp) {
1193 if ((sdev->id == ndlp->nlp_sid) && ndlp->rport) {
1194 match = 1;
1195 break;
1196 }
1197 }
1198 }
1199 1150
1200 if (!match) 1151 if (!rport || fc_remote_port_chkready(rport))
1201 return -ENXIO; 1152 return -ENXIO;
1202 1153
1203 sdev->hostdata = ndlp->rport->dd_data; 1154 sdev->hostdata = rport->dd_data;
1204 1155
1205 /* 1156 /*
1206 * Populate the cmds_per_lun count scsi_bufs into this host's globally 1157 * Populate the cmds_per_lun count scsi_bufs into this host's globally
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index fc3234c3625..7096945ea23 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -21,6 +21,7 @@
21#include <linux/spinlock.h> 21#include <linux/spinlock.h>
22#include <linux/completion.h> 22#include <linux/completion.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/workqueue.h>
24#include <asm/semaphore.h> 25#include <asm/semaphore.h>
25 26
26#include <scsi/scsi.h> 27#include <scsi/scsi.h>
@@ -1665,6 +1666,8 @@ typedef struct fc_port {
1665 1666
1666 struct fc_rport *rport; 1667 struct fc_rport *rport;
1667 u32 supported_classes; 1668 u32 supported_classes;
1669 struct work_struct rport_add_work;
1670 struct work_struct rport_del_work;
1668} fc_port_t; 1671} fc_port_t;
1669 1672
1670/* 1673/*
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index ce7e712ebe8..290a6b92616 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1668,6 +1668,24 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
1668 return (rval); 1668 return (rval);
1669} 1669}
1670 1670
1671static void
1672qla2x00_rport_add(void *data)
1673{
1674 fc_port_t *fcport = data;
1675
1676 qla2x00_reg_remote_port(fcport->ha, fcport);
1677}
1678
1679static void
1680qla2x00_rport_del(void *data)
1681{
1682 fc_port_t *fcport = data;
1683
1684 if (fcport->rport)
1685 fc_remote_port_delete(fcport->rport);
1686 fcport->rport = NULL;
1687}
1688
1671/** 1689/**
1672 * qla2x00_alloc_fcport() - Allocate a generic fcport. 1690 * qla2x00_alloc_fcport() - Allocate a generic fcport.
1673 * @ha: HA context 1691 * @ha: HA context
@@ -1693,6 +1711,8 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags)
1693 atomic_set(&fcport->state, FCS_UNCONFIGURED); 1711 atomic_set(&fcport->state, FCS_UNCONFIGURED);
1694 fcport->flags = FCF_RLC_SUPPORT; 1712 fcport->flags = FCF_RLC_SUPPORT;
1695 fcport->supported_classes = FC_COS_UNSPECIFIED; 1713 fcport->supported_classes = FC_COS_UNSPECIFIED;
1714 INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport);
1715 INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport);
1696 1716
1697 return (fcport); 1717 return (fcport);
1698} 1718}
@@ -2056,8 +2076,8 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
2056 struct fc_rport *rport; 2076 struct fc_rport *rport;
2057 2077
2058 if (fcport->rport) { 2078 if (fcport->rport) {
2059 fc_remote_port_unblock(fcport->rport); 2079 fc_remote_port_delete(fcport->rport);
2060 return; 2080 fcport->rport = NULL;
2061 } 2081 }
2062 2082
2063 rport_ids.node_name = wwn_to_u64(fcport->node_name); 2083 rport_ids.node_name = wwn_to_u64(fcport->node_name);
@@ -2071,7 +2091,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *ha, fc_port_t *fcport)
2071 "Unable to allocate fc remote port!\n"); 2091 "Unable to allocate fc remote port!\n");
2072 return; 2092 return;
2073 } 2093 }
2074 rport->dd_data = fcport; 2094 *((fc_port_t **)rport->dd_data) = fcport;
2075 rport->supported_classes = fcport->supported_classes; 2095 rport->supported_classes = fcport->supported_classes;
2076 2096
2077 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; 2097 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index b899282a856..c58c9d97b04 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -348,11 +348,13 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
348{ 348{
349 scsi_qla_host_t *ha = to_qla_host(cmd->device->host); 349 scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
350 fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; 350 fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
351 struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
351 srb_t *sp; 352 srb_t *sp;
352 int rval; 353 int rval;
353 354
354 if (!fcport) { 355 rval = fc_remote_port_chkready(rport);
355 cmd->result = DID_NO_CONNECT << 16; 356 if (rval) {
357 cmd->result = rval;
356 goto qc_fail_command; 358 goto qc_fail_command;
357 } 359 }
358 360
@@ -401,11 +403,13 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
401{ 403{
402 scsi_qla_host_t *ha = to_qla_host(cmd->device->host); 404 scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
403 fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; 405 fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
406 struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
404 srb_t *sp; 407 srb_t *sp;
405 int rval; 408 int rval;
406 409
407 if (!fcport) { 410 rval = fc_remote_port_chkready(rport);
408 cmd->result = DID_NO_CONNECT << 16; 411 if (rval) {
412 cmd->result = rval;
409 goto qc24_fail_command; 413 goto qc24_fail_command;
410 } 414 }
411 415
@@ -1041,10 +1045,10 @@ qla2xxx_slave_alloc(struct scsi_device *sdev)
1041{ 1045{
1042 struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); 1046 struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
1043 1047
1044 if (!rport) 1048 if (!rport || fc_remote_port_chkready(rport))
1045 return -ENXIO; 1049 return -ENXIO;
1046 1050
1047 sdev->hostdata = rport->dd_data; 1051 sdev->hostdata = *(fc_port_t **)rport->dd_data;
1048 1052
1049 return 0; 1053 return 0;
1050} 1054}
@@ -1636,7 +1640,8 @@ void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport,
1636 int do_login) 1640 int do_login)
1637{ 1641{
1638 if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) 1642 if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport)
1639 fc_remote_port_block(fcport->rport); 1643 schedule_work(&fcport->rport_del_work);
1644
1640 /* 1645 /*
1641 * We may need to retry the login, so don't change the state of the 1646 * We may need to retry the login, so don't change the state of the
1642 * port but do the retries. 1647 * port but do the retries.
@@ -1697,7 +1702,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha)
1697 if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) 1702 if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD)
1698 continue; 1703 continue;
1699 if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport) 1704 if (atomic_read(&fcport->state) == FCS_ONLINE && fcport->rport)
1700 fc_remote_port_block(fcport->rport); 1705 schedule_work(&fcport->rport_del_work);
1701 atomic_set(&fcport->state, FCS_DEVICE_LOST); 1706 atomic_set(&fcport->state, FCS_DEVICE_LOST);
1702 } 1707 }
1703} 1708}
diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c
index 3e53f62d640..2c3342108dd 100644
--- a/drivers/scsi/qla2xxx/qla_rscn.c
+++ b/drivers/scsi/qla2xxx/qla_rscn.c
@@ -320,8 +320,7 @@ qla2x00_update_login_fcport(scsi_qla_host_t *ha, struct mbx_entry *mbxstat,
320 fcport->flags &= ~FCF_FAILOVER_NEEDED; 320 fcport->flags &= ~FCF_FAILOVER_NEEDED;
321 fcport->iodesc_idx_sent = IODESC_INVALID_INDEX; 321 fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
322 atomic_set(&fcport->state, FCS_ONLINE); 322 atomic_set(&fcport->state, FCS_ONLINE);
323 if (fcport->rport) 323 schedule_work(&fcport->rport_add_work);
324 fc_remote_port_unblock(fcport->rport);
325} 324}
326 325
327 326
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 27702097b7f..ca098fc2a60 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -210,7 +210,7 @@ fc_bitfield_name_search(remote_port_roles, fc_remote_port_role_names)
210#define FC_MGMTSRVR_PORTID 0x00000a 210#define FC_MGMTSRVR_PORTID 0x00000a
211 211
212 212
213static void fc_timeout_blocked_rport(void *data); 213static void fc_timeout_deleted_rport(void *data);
214static void fc_scsi_scan_rport(void *data); 214static void fc_scsi_scan_rport(void *data);
215static void fc_rport_terminate(struct fc_rport *rport); 215static void fc_rport_terminate(struct fc_rport *rport);
216 216
@@ -384,7 +384,9 @@ show_fc_rport_##field (struct class_device *cdev, char *buf) \
384 struct fc_rport *rport = transport_class_to_rport(cdev); \ 384 struct fc_rport *rport = transport_class_to_rport(cdev); \
385 struct Scsi_Host *shost = rport_to_shost(rport); \ 385 struct Scsi_Host *shost = rport_to_shost(rport); \
386 struct fc_internal *i = to_fc_internal(shost->transportt); \ 386 struct fc_internal *i = to_fc_internal(shost->transportt); \
387 if (i->f->get_rport_##field) \ 387 if ((i->f->get_rport_##field) && \
388 !((rport->port_state == FC_PORTSTATE_BLOCKED) || \
389 (rport->port_state == FC_PORTSTATE_NOTPRESENT))) \
388 i->f->get_rport_##field(rport); \ 390 i->f->get_rport_##field(rport); \
389 return snprintf(buf, sz, format_string, cast rport->field); \ 391 return snprintf(buf, sz, format_string, cast rport->field); \
390} 392}
@@ -398,6 +400,9 @@ store_fc_rport_##field(struct class_device *cdev, const char *buf, \
398 struct fc_rport *rport = transport_class_to_rport(cdev); \ 400 struct fc_rport *rport = transport_class_to_rport(cdev); \
399 struct Scsi_Host *shost = rport_to_shost(rport); \ 401 struct Scsi_Host *shost = rport_to_shost(rport); \
400 struct fc_internal *i = to_fc_internal(shost->transportt); \ 402 struct fc_internal *i = to_fc_internal(shost->transportt); \
403 if ((rport->port_state == FC_PORTSTATE_BLOCKED) || \
404 (rport->port_state == FC_PORTSTATE_NOTPRESENT)) \
405 return -EBUSY; \
401 val = simple_strtoul(buf, NULL, 0); \ 406 val = simple_strtoul(buf, NULL, 0); \
402 i->f->set_rport_##field(rport, val); \ 407 i->f->set_rport_##field(rport, val); \
403 return count; \ 408 return count; \
@@ -500,7 +505,29 @@ static FC_CLASS_DEVICE_ATTR(rport, supported_classes, S_IRUGO,
500 505
501/* Dynamic Remote Port Attributes */ 506/* Dynamic Remote Port Attributes */
502 507
503fc_rport_rw_attr(dev_loss_tmo, "%d\n", 20); 508/*
509 * dev_loss_tmo attribute
510 */
511fc_rport_show_function(dev_loss_tmo, "%d\n", 20, )
512static ssize_t
513store_fc_rport_dev_loss_tmo(struct class_device *cdev, const char *buf,
514 size_t count)
515{
516 int val;
517 struct fc_rport *rport = transport_class_to_rport(cdev);
518 struct Scsi_Host *shost = rport_to_shost(rport);
519 struct fc_internal *i = to_fc_internal(shost->transportt);
520 if ((rport->port_state == FC_PORTSTATE_BLOCKED) ||
521 (rport->port_state == FC_PORTSTATE_NOTPRESENT))
522 return -EBUSY;
523 val = simple_strtoul(buf, NULL, 0);
524 if ((val < 0) || (val > SCSI_DEVICE_BLOCK_MAX_TIMEOUT))
525 return -EINVAL;
526 i->f->set_rport_dev_loss_tmo(rport, val);
527 return count;
528}
529static FC_CLASS_DEVICE_ATTR(rport, dev_loss_tmo, S_IRUGO | S_IWUSR,
530 show_fc_rport_dev_loss_tmo, store_fc_rport_dev_loss_tmo);
504 531
505 532
506/* Private Remote Port Attributes */ 533/* Private Remote Port Attributes */
@@ -1214,6 +1241,25 @@ fc_remove_host(struct Scsi_Host *shost)
1214} 1241}
1215EXPORT_SYMBOL(fc_remove_host); 1242EXPORT_SYMBOL(fc_remove_host);
1216 1243
1244/*
1245 * fc_rport_tgt_remove - Removes the scsi target on the remote port
1246 * @rport: The remote port to be operated on
1247 */
1248static void
1249fc_rport_tgt_remove(struct fc_rport *rport)
1250{
1251 struct Scsi_Host *shost = rport_to_shost(rport);
1252
1253 scsi_target_unblock(&rport->dev);
1254
1255 /* Stop anything on the workq */
1256 if (!cancel_delayed_work(&rport->dev_loss_work))
1257 flush_scheduled_work();
1258 scsi_flush_work(shost);
1259
1260 scsi_remove_target(&rport->dev);
1261}
1262
1217/** 1263/**
1218 * fc_rport_create - allocates and creates a remote FC port. 1264 * fc_rport_create - allocates and creates a remote FC port.
1219 * @shost: scsi host the remote port is connected to. 1265 * @shost: scsi host the remote port is connected to.
@@ -1260,7 +1306,7 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
1260 rport->dd_data = &rport[1]; 1306 rport->dd_data = &rport[1];
1261 rport->channel = channel; 1307 rport->channel = channel;
1262 1308
1263 INIT_WORK(&rport->dev_loss_work, fc_timeout_blocked_rport, rport); 1309 INIT_WORK(&rport->dev_loss_work, fc_timeout_deleted_rport, rport);
1264 INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport); 1310 INIT_WORK(&rport->scan_work, fc_scsi_scan_rport, rport);
1265 1311
1266 spin_lock_irqsave(shost->host_lock, flags); 1312 spin_lock_irqsave(shost->host_lock, flags);
@@ -1352,17 +1398,93 @@ struct fc_rport *
1352fc_remote_port_add(struct Scsi_Host *shost, int channel, 1398fc_remote_port_add(struct Scsi_Host *shost, int channel,
1353 struct fc_rport_identifiers *ids) 1399 struct fc_rport_identifiers *ids)
1354{ 1400{
1401 struct fc_internal *fci = to_fc_internal(shost->transportt);
1355 struct fc_rport *rport; 1402 struct fc_rport *rport;
1356 unsigned long flags; 1403 unsigned long flags;
1357 int match = 0; 1404 int match = 0;
1358 1405
1406 /*
1407 * Search the list of "active" rports, for an rport that has been
1408 * deleted, but we've held off the real delete while the target
1409 * is in a "blocked" state.
1410 */
1411 spin_lock_irqsave(shost->host_lock, flags);
1412
1413 list_for_each_entry(rport, &fc_host_rports(shost), peers) {
1414
1415 if ((rport->port_state == FC_PORTSTATE_BLOCKED) &&
1416 (rport->channel == channel)) {
1417
1418 switch (fc_host_tgtid_bind_type(shost)) {
1419 case FC_TGTID_BIND_BY_WWPN:
1420 case FC_TGTID_BIND_NONE:
1421 if (rport->port_name == ids->port_name)
1422 match = 1;
1423 break;
1424 case FC_TGTID_BIND_BY_WWNN:
1425 if (rport->node_name == ids->node_name)
1426 match = 1;
1427 break;
1428 case FC_TGTID_BIND_BY_ID:
1429 if (rport->port_id == ids->port_id)
1430 match = 1;
1431 break;
1432 }
1433
1434 if (match) {
1435 struct work_struct *work =
1436 &rport->dev_loss_work;
1437
1438 memcpy(&rport->node_name, &ids->node_name,
1439 sizeof(rport->node_name));
1440 memcpy(&rport->port_name, &ids->port_name,
1441 sizeof(rport->port_name));
1442 rport->port_id = ids->port_id;
1443
1444 rport->port_state = FC_PORTSTATE_ONLINE;
1445 rport->roles = ids->roles;
1446
1447 spin_unlock_irqrestore(shost->host_lock, flags);
1448
1449 if (fci->f->dd_fcrport_size)
1450 memset(rport->dd_data, 0,
1451 fci->f->dd_fcrport_size);
1452
1453 /*
1454 * If we were blocked, we were a target.
1455 * If no longer a target, we leave the timer
1456 * running in case the port changes roles
1457 * prior to the timer expiring. If the timer
1458 * fires, the target will be torn down.
1459 */
1460 if (!(ids->roles & FC_RPORT_ROLE_FCP_TARGET))
1461 return rport;
1462
1463 /* restart the target */
1464
1465 /*
1466 * Stop the target timer first. Take no action
1467 * on the del_timer failure as the state
1468 * machine state change will validate the
1469 * transaction.
1470 */
1471 if (!cancel_delayed_work(work))
1472 flush_scheduled_work();
1473
1474 /* initiate a scan of the target */
1475 scsi_queue_work(shost, &rport->scan_work);
1476
1477 return rport;
1478 }
1479 }
1480 }
1481
1482 /* Search the bindings array */
1359 if (likely((ids->roles & FC_RPORT_ROLE_FCP_TARGET) && 1483 if (likely((ids->roles & FC_RPORT_ROLE_FCP_TARGET) &&
1360 (fc_host_tgtid_bind_type(shost) != FC_TGTID_BIND_NONE))) { 1484 (fc_host_tgtid_bind_type(shost) != FC_TGTID_BIND_NONE))) {
1361 1485
1362 /* search for a matching consistent binding */ 1486 /* search for a matching consistent binding */
1363 1487
1364 spin_lock_irqsave(shost->host_lock, flags);
1365
1366 list_for_each_entry(rport, &fc_host_rport_bindings(shost), 1488 list_for_each_entry(rport, &fc_host_rport_bindings(shost),
1367 peers) { 1489 peers) {
1368 if (rport->channel != channel) 1490 if (rport->channel != channel)
@@ -1392,8 +1514,6 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
1392 } 1514 }
1393 } 1515 }
1394 1516
1395 spin_unlock_irqrestore(shost->host_lock, flags);
1396
1397 if (match) { 1517 if (match) {
1398 memcpy(&rport->node_name, &ids->node_name, 1518 memcpy(&rport->node_name, &ids->node_name,
1399 sizeof(rport->node_name)); 1519 sizeof(rport->node_name));
@@ -1403,6 +1523,12 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
1403 rport->roles = ids->roles; 1523 rport->roles = ids->roles;
1404 rport->port_state = FC_PORTSTATE_ONLINE; 1524 rport->port_state = FC_PORTSTATE_ONLINE;
1405 1525
1526 spin_unlock_irqrestore(shost->host_lock, flags);
1527
1528 if (fci->f->dd_fcrport_size)
1529 memset(rport->dd_data, 0,
1530 fci->f->dd_fcrport_size);
1531
1406 if (rport->roles & FC_RPORT_ROLE_FCP_TARGET) 1532 if (rport->roles & FC_RPORT_ROLE_FCP_TARGET)
1407 /* initiate a scan of the target */ 1533 /* initiate a scan of the target */
1408 scsi_queue_work(shost, &rport->scan_work); 1534 scsi_queue_work(shost, &rport->scan_work);
@@ -1411,6 +1537,8 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
1411 } 1537 }
1412 } 1538 }
1413 1539
1540 spin_unlock_irqrestore(shost->host_lock, flags);
1541
1414 /* No consistent binding found - create new remote port entry */ 1542 /* No consistent binding found - create new remote port entry */
1415 rport = fc_rport_create(shost, channel, ids); 1543 rport = fc_rport_create(shost, channel, ids);
1416 1544
@@ -1419,25 +1547,6 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
1419EXPORT_SYMBOL(fc_remote_port_add); 1547EXPORT_SYMBOL(fc_remote_port_add);
1420 1548
1421/* 1549/*
1422 * fc_rport_tgt_remove - Removes the scsi target on the remote port
1423 * @rport: The remote port to be operated on
1424 */
1425static void
1426fc_rport_tgt_remove(struct fc_rport *rport)
1427{
1428 struct Scsi_Host *shost = rport_to_shost(rport);
1429
1430 scsi_target_unblock(&rport->dev);
1431
1432 /* Stop anything on the workq */
1433 if (!cancel_delayed_work(&rport->dev_loss_work))
1434 flush_scheduled_work();
1435 scsi_flush_work(shost);
1436
1437 scsi_remove_target(&rport->dev);
1438}
1439
1440/*
1441 * fc_rport_terminate - this routine tears down and deallocates a remote port. 1550 * fc_rport_terminate - this routine tears down and deallocates a remote port.
1442 * @rport: The remote port to be terminated 1551 * @rport: The remote port to be terminated
1443 * 1552 *
@@ -1470,24 +1579,44 @@ fc_rport_terminate(struct fc_rport *rport)
1470 * The LLDD calls this routine to notify the transport that a remote 1579 * The LLDD calls this routine to notify the transport that a remote
1471 * port is no longer part of the topology. Note: Although a port 1580 * port is no longer part of the topology. Note: Although a port
1472 * may no longer be part of the topology, it may persist in the remote 1581 * may no longer be part of the topology, it may persist in the remote
1473 * ports displayed by the fc_host. This is done so that target id 1582 * ports displayed by the fc_host. We do this under 2 conditions:
1474 * mappings (managed via the remote port structures), are always visible 1583 * - If the port was a scsi target, we delay its deletion by "blocking" it.
1475 * as long as the mapping is valid, regardless of port state, 1584 * This allows the port to temporarily disappear, then reappear without
1585 * disrupting the SCSI device tree attached to it. During the "blocked"
1586 * period the port will still exist.
1587 * - If the port was a scsi target and disappears for longer than we
1588 * expect, we'll delete the port and the tear down the SCSI device tree
1589 * attached to it. However, we want to semi-persist the target id assigned
1590 * to that port if it eventually does exist. The port structure will
1591 * remain (although with minimal information) so that the target id
1592 * bindings remails.
1476 * 1593 *
1477 * If the remote port is not an FCP Target, it will be fully torn down 1594 * If the remote port is not an FCP Target, it will be fully torn down
1478 * and deallocated, including the fc_remote_port class device. 1595 * and deallocated, including the fc_remote_port class device.
1479 * 1596 *
1480 * If the remote port is an FCP Target, the port structure will be 1597 * If the remote port is an FCP Target, the port will be placed in a
1481 * marked as Not Present, but will remain as long as there is a valid 1598 * temporary blocked state. From the LLDD's perspective, the rport no
1482 * SCSI target id mapping associated with the port structure. Validity 1599 * longer exists. From the SCSI midlayer's perspective, the SCSI target
1483 * is determined by the binding type. If binding by wwpn, then the port 1600 * exists, but all sdevs on it are blocked from further I/O. The following
1484 * structure is always valid and will not be deallocated until the host 1601 * is then expected:
1485 * is removed. If binding by wwnn, then the port structure is valid 1602 * If the remote port does not return (signaled by a LLDD call to
1486 * until another port with the same node name is found in the topology. 1603 * fc_remote_port_add()) within the dev_loss_tmo timeout, then the
1487 * If binding by port id (fc address), then the port structure is valid 1604 * scsi target is removed - killing all outstanding i/o and removing the
1488 * valid until another port with the same address is identified. 1605 * scsi devices attached ot it. The port structure will be marked Not
1606 * Present and be partially cleared, leaving only enough information to
1607 * recognize the remote port relative to the scsi target id binding if
1608 * it later appears. The port will remain as long as there is a valid
1609 * binding (e.g. until the user changes the binding type or unloads the
1610 * scsi host with the binding).
1489 * 1611 *
1490 * Called from interrupt or normal process context. 1612 * If the remote port returns within the dev_loss_tmo value (and matches
1613 * according to the target id binding type), the port structure will be
1614 * reused. If it is no longer a SCSI target, the target will be torn
1615 * down. If it continues to be a SCSI target, then the target will be
1616 * unblocked (allowing i/o to be resumed), and a scan will be activated
1617 * to ensure that all luns are detected.
1618 *
1619 * Called from normal process context only - cannot be called from interrupt.
1491 * 1620 *
1492 * Notes: 1621 * Notes:
1493 * This routine assumes no locks are held on entry. 1622 * This routine assumes no locks are held on entry.
@@ -1495,53 +1624,20 @@ fc_rport_terminate(struct fc_rport *rport)
1495void 1624void
1496fc_remote_port_delete(struct fc_rport *rport) 1625fc_remote_port_delete(struct fc_rport *rport)
1497{ 1626{
1498 struct Scsi_Host *shost = rport_to_shost(rport); 1627 int timeout = rport->dev_loss_tmo;
1499 unsigned long flags;
1500 1628
1501 /* If no scsi target id mapping or consistent binding type, delete it */ 1629 /* If no scsi target id mapping, delete it */
1502 if ((rport->scsi_target_id == -1) || 1630 if (rport->scsi_target_id == -1) {
1503 (fc_host_tgtid_bind_type(shost) == FC_TGTID_BIND_NONE)) {
1504 fc_rport_terminate(rport); 1631 fc_rport_terminate(rport);
1505 return; 1632 return;
1506 } 1633 }
1507 1634
1508 fc_rport_tgt_remove(rport); 1635 scsi_target_block(&rport->dev);
1509
1510 spin_lock_irqsave(shost->host_lock, flags);
1511 list_move_tail(&rport->peers, &fc_host_rport_bindings(shost));
1512 spin_unlock_irqrestore(shost->host_lock, flags);
1513
1514 /*
1515 * Note: We do not remove or clear the hostdata area. This allows
1516 * host-specific target data to persist along with the
1517 * scsi_target_id. It's up to the host to manage it's hostdata area.
1518 */
1519 1636
1520 /* 1637 /* cap the length the devices can be blocked until they are deleted */
1521 * Reinitialize port attributes that may change if the port comes back. 1638 schedule_delayed_work(&rport->dev_loss_work, timeout * HZ);
1522 */
1523 rport->maxframe_size = -1;
1524 rport->supported_classes = FC_COS_UNSPECIFIED;
1525 rport->roles = FC_RPORT_ROLE_UNKNOWN;
1526 rport->port_state = FC_PORTSTATE_NOTPRESENT;
1527 1639
1528 /* remove the identifiers that aren't used in the consisting binding */ 1640 rport->port_state = FC_PORTSTATE_BLOCKED;
1529 switch (fc_host_tgtid_bind_type(shost)) {
1530 case FC_TGTID_BIND_BY_WWPN:
1531 rport->node_name = -1;
1532 rport->port_id = -1;
1533 break;
1534 case FC_TGTID_BIND_BY_WWNN:
1535 rport->port_name = -1;
1536 rport->port_id = -1;
1537 break;
1538 case FC_TGTID_BIND_BY_ID:
1539 rport->node_name = -1;
1540 rport->port_name = -1;
1541 break;
1542 case FC_TGTID_BIND_NONE: /* to keep compiler happy */
1543 break;
1544 }
1545} 1641}
1546EXPORT_SYMBOL(fc_remote_port_delete); 1642EXPORT_SYMBOL(fc_remote_port_delete);
1547 1643
@@ -1574,127 +1670,140 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
1574 unsigned long flags; 1670 unsigned long flags;
1575 int create = 0; 1671 int create = 0;
1576 1672
1577 rport->roles = roles;
1578
1579 spin_lock_irqsave(shost->host_lock, flags); 1673 spin_lock_irqsave(shost->host_lock, flags);
1580 if ((rport->scsi_target_id == -1) && 1674 if (roles & FC_RPORT_ROLE_FCP_TARGET) {
1581 (rport->roles & FC_RPORT_ROLE_FCP_TARGET)) { 1675 if (rport->scsi_target_id == -1) {
1582 rport->scsi_target_id = fc_host->next_target_id++; 1676 rport->scsi_target_id = fc_host->next_target_id++;
1583 create = 1; 1677 create = 1;
1678 } else if (!(rport->roles & FC_RPORT_ROLE_FCP_TARGET))
1679 create = 1;
1584 } 1680 }
1585 spin_unlock_irqrestore(shost->host_lock, flags); 1681 spin_unlock_irqrestore(shost->host_lock, flags);
1586 1682
1587 if (create) 1683 rport->roles = roles;
1684
1685 if (create) {
1686 /*
1687 * There may have been a delete timer running on the
1688 * port. Ensure that it is cancelled as we now know
1689 * the port is an FCP Target.
1690 * Note: we know the rport is exists and in an online
1691 * state as the LLDD would not have had an rport
1692 * reference to pass us.
1693 *
1694 * Take no action on the del_timer failure as the state
1695 * machine state change will validate the
1696 * transaction.
1697 */
1698 if (!cancel_delayed_work(&rport->dev_loss_work))
1699 flush_scheduled_work();
1700
1588 /* initiate a scan of the target */ 1701 /* initiate a scan of the target */
1589 scsi_queue_work(shost, &rport->scan_work); 1702 scsi_queue_work(shost, &rport->scan_work);
1703 }
1590} 1704}
1591EXPORT_SYMBOL(fc_remote_port_rolechg); 1705EXPORT_SYMBOL(fc_remote_port_rolechg);
1592 1706
1593/** 1707/**
1594 * fc_timeout_blocked_rport - Timeout handler for blocked remote port 1708 * fc_timeout_deleted_rport - Timeout handler for a deleted remote port that
1595 * that fails to return in the alloted time. 1709 * was a SCSI target (thus was blocked), and failed
1596 * @data: scsi target that failed to reappear in the alloted time. 1710 * to return in the alloted time.
1711 *
1712 * @data: rport target that failed to reappear in the alloted time.
1597 **/ 1713 **/
1598static void 1714static void
1599fc_timeout_blocked_rport(void *data) 1715fc_timeout_deleted_rport(void *data)
1600{ 1716{
1601 struct fc_rport *rport = (struct fc_rport *)data; 1717 struct fc_rport *rport = (struct fc_rport *)data;
1718 struct Scsi_Host *shost = rport_to_shost(rport);
1719 unsigned long flags;
1602 1720
1603 rport->port_state = FC_PORTSTATE_OFFLINE; 1721 spin_lock_irqsave(shost->host_lock, flags);
1604
1605 dev_printk(KERN_ERR, &rport->dev,
1606 "blocked FC remote port time out: removing target\n");
1607 1722
1608 /* 1723 /*
1609 * As this only occurs if the remote port (scsi target) 1724 * If the port is ONLINE, then it came back, but was no longer an
1610 * went away and didn't come back - we'll remove 1725 * FCP target. Thus we need to tear down the scsi_target on it.
1611 * all attached scsi devices.
1612 */ 1726 */
1613 scsi_target_unblock(&rport->dev); 1727 if (rport->port_state == FC_PORTSTATE_ONLINE) {
1614 scsi_remove_target(&rport->dev); 1728 spin_unlock_irqrestore(shost->host_lock, flags);
1615}
1616 1729
1617/** 1730 dev_printk(KERN_ERR, &rport->dev,
1618 * fc_remote_port_block - temporarily block any scsi traffic to a remote port. 1731 "blocked FC remote port time out: removing target\n");
1619 * @rport: remote port to be blocked.
1620 *
1621 * scsi lldd's with a FC transport call this routine to temporarily stop
1622 * all scsi traffic to a remote port. If the port is not a SCSI target,
1623 * no action is taken. If the port is a SCSI target, all attached devices
1624 * are placed into a SDEV_BLOCK state and a timer is started. The timer is
1625 * represents the maximum amount of time the port may be blocked. If the
1626 * timer expires, the port is considered non-existent and the attached
1627 * scsi devices will be removed.
1628 *
1629 * Called from interrupt or normal process context.
1630 *
1631 * Returns zero if successful or error if not
1632 *
1633 * Notes:
1634 * This routine assumes no locks are held on entry.
1635 *
1636 * The timeout and timer types are extracted from the fc transport
1637 * attributes from the caller's rport pointer.
1638 **/
1639int
1640fc_remote_port_block(struct fc_rport *rport)
1641{
1642 int timeout = rport->dev_loss_tmo;
1643 struct work_struct *work = &rport->dev_loss_work;
1644 1732
1645 if (timeout < 0 || timeout > SCSI_DEVICE_BLOCK_MAX_TIMEOUT) 1733 fc_rport_tgt_remove(rport);
1646 return -EINVAL;
1647 1734
1648 scsi_target_block(&rport->dev); 1735 return;
1736 }
1649 1737
1650 /* cap the length the devices can be blocked */ 1738 if (rport->port_state != FC_PORTSTATE_BLOCKED) {
1651 schedule_delayed_work(work, timeout * HZ); 1739 spin_unlock_irqrestore(shost->host_lock, flags);
1740 dev_printk(KERN_ERR, &rport->dev,
1741 "blocked FC remote port time out: leaving target alone\n");
1742 return;
1743 }
1652 1744
1653 rport->port_state = FC_PORTSTATE_BLOCKED; 1745 if (fc_host_tgtid_bind_type(shost) == FC_TGTID_BIND_NONE) {
1654 return 0; 1746 spin_unlock_irqrestore(shost->host_lock, flags);
1655} 1747 dev_printk(KERN_ERR, &rport->dev,
1656EXPORT_SYMBOL(fc_remote_port_block); 1748 "blocked FC remote port time out: removing target\n");
1749 fc_rport_terminate(rport);
1750 return;
1751 }
1657 1752
1658/** 1753 dev_printk(KERN_ERR, &rport->dev,
1659 * fc_remote_port_unblock - restart any blocked scsi traffic to a remote port. 1754 "blocked FC remote port time out: removing target and "
1660 * @rport: remote port to be unblocked. 1755 "saving binding\n");
1661 * 1756
1662 * scsi lld's with a FC transport call this routine to restart IO to all 1757 list_move_tail(&rport->peers, &fc_host_rport_bindings(shost));
1663 * devices associated with the caller's scsi target following a fc_target_block
1664 * request. Called from interrupt or normal process context.
1665 *
1666 * Notes:
1667 * This routine assumes no locks are held on entry.
1668 **/
1669 void
1670fc_remote_port_unblock(struct fc_rport *rport)
1671{
1672 struct work_struct *work = &rport->dev_loss_work;
1673 struct Scsi_Host *shost = rport_to_shost(rport);
1674 1758
1675 /* 1759 /*
1676 * Stop the target timer first. Take no action on the del_timer 1760 * Note: We do not remove or clear the hostdata area. This allows
1677 * failure as the state machine state change will validate the 1761 * host-specific target data to persist along with the
1678 * transaction. 1762 * scsi_target_id. It's up to the host to manage it's hostdata area.
1679 */ 1763 */
1680 if (!cancel_delayed_work(work))
1681 flush_scheduled_work();
1682 1764
1683 if (rport->port_state == FC_PORTSTATE_OFFLINE) 1765 /*
1684 /* 1766 * Reinitialize port attributes that may change if the port comes back.
1685 * initiate a scan of the target as the target has 1767 */
1686 * been torn down. 1768 rport->maxframe_size = -1;
1687 */ 1769 rport->supported_classes = FC_COS_UNSPECIFIED;
1688 scsi_queue_work(shost, &rport->scan_work); 1770 rport->roles = FC_RPORT_ROLE_UNKNOWN;
1689 else 1771 rport->port_state = FC_PORTSTATE_NOTPRESENT;
1690 scsi_target_unblock(&rport->dev);
1691 1772
1692 rport->port_state = FC_PORTSTATE_ONLINE; 1773 /* remove the identifiers that aren't used in the consisting binding */
1774 switch (fc_host_tgtid_bind_type(shost)) {
1775 case FC_TGTID_BIND_BY_WWPN:
1776 rport->node_name = -1;
1777 rport->port_id = -1;
1778 break;
1779 case FC_TGTID_BIND_BY_WWNN:
1780 rport->port_name = -1;
1781 rport->port_id = -1;
1782 break;
1783 case FC_TGTID_BIND_BY_ID:
1784 rport->node_name = -1;
1785 rport->port_name = -1;
1786 break;
1787 case FC_TGTID_BIND_NONE: /* to keep compiler happy */
1788 break;
1789 }
1790
1791 spin_unlock_irqrestore(shost->host_lock, flags);
1792
1793 /*
1794 * As this only occurs if the remote port (scsi target)
1795 * went away and didn't come back - we'll remove
1796 * all attached scsi devices.
1797 */
1798 fc_rport_tgt_remove(rport);
1693} 1799}
1694EXPORT_SYMBOL(fc_remote_port_unblock);
1695 1800
1696/** 1801/**
1697 * fc_scsi_scan_rport - called to perform a scsi scan on a remote port. 1802 * fc_scsi_scan_rport - called to perform a scsi scan on a remote port.
1803 *
1804 * Will unblock the target (in case it went away and has now come back),
1805 * then invoke a scan.
1806 *
1698 * @data: remote port to be scanned. 1807 * @data: remote port to be scanned.
1699 **/ 1808 **/
1700static void 1809static void
@@ -1702,6 +1811,7 @@ fc_scsi_scan_rport(void *data)
1702{ 1811{
1703 struct fc_rport *rport = (struct fc_rport *)data; 1812 struct fc_rport *rport = (struct fc_rport *)data;
1704 1813
1814 scsi_target_unblock(&rport->dev);
1705 scsi_scan_target(&rport->dev, rport->channel, rport->scsi_target_id, 1815 scsi_scan_target(&rport->dev, rport->channel, rport->scsi_target_id,
1706 SCAN_WILD_CARD, 1); 1816 SCAN_WILD_CARD, 1);
1707} 1817}
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 4496b32972e..319ff7a60df 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -28,6 +28,7 @@
28#define SCSI_TRANSPORT_FC_H 28#define SCSI_TRANSPORT_FC_H
29 29
30#include <linux/config.h> 30#include <linux/config.h>
31#include <scsi/scsi.h>
31 32
32struct scsi_transport_template; 33struct scsi_transport_template;
33 34
@@ -429,6 +430,34 @@ struct fc_function_template {
429}; 430};
430 431
431 432
433/**
434 * fc_remote_port_chkready - called to validate the remote port state
435 * prior to initiating io to the port.
436 *
437 * Returns a scsi result code that can be returned by the LLDD.
438 *
439 * @rport: remote port to be checked
440 **/
441static inline int
442fc_remote_port_chkready(struct fc_rport *rport)
443{
444 int result;
445
446 switch (rport->port_state) {
447 case FC_PORTSTATE_ONLINE:
448 result = 0;
449 break;
450 case FC_PORTSTATE_BLOCKED:
451 result = DID_BUS_BUSY << 16;
452 break;
453 default:
454 result = DID_NO_CONNECT << 16;
455 break;
456 }
457 return result;
458}
459
460
432struct scsi_transport_template *fc_attach_transport( 461struct scsi_transport_template *fc_attach_transport(
433 struct fc_function_template *); 462 struct fc_function_template *);
434void fc_release_transport(struct scsi_transport_template *); 463void fc_release_transport(struct scsi_transport_template *);
@@ -437,8 +466,6 @@ struct fc_rport *fc_remote_port_add(struct Scsi_Host *shost,
437 int channel, struct fc_rport_identifiers *ids); 466 int channel, struct fc_rport_identifiers *ids);
438void fc_remote_port_delete(struct fc_rport *rport); 467void fc_remote_port_delete(struct fc_rport *rport);
439void fc_remote_port_rolechg(struct fc_rport *rport, u32 roles); 468void fc_remote_port_rolechg(struct fc_rport *rport, u32 roles);
440int fc_remote_port_block(struct fc_rport *rport);
441void fc_remote_port_unblock(struct fc_rport *rport);
442int scsi_is_fc_rport(const struct device *); 469int scsi_is_fc_rport(const struct device *);
443 470
444static inline u64 wwn_to_u64(u8 *wwn) 471static inline u64 wwn_to_u64(u8 *wwn)