aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_hbadisc.c
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 /drivers/scsi/lpfc/lpfc_hbadisc.c
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>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_hbadisc.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 56052f4510c3..6c846ad373bc 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