aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_nportdisc.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-06-17 20:56:39 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-06-17 23:38:11 -0400
commit858c9f6c19c6f9bf86cbbc64ce0d17c61d6131b8 (patch)
tree9591b15b4424066023e375ad0aa33fdd37e1c452 /drivers/scsi/lpfc/lpfc_nportdisc.c
parent92d7f7b0cde3ad2260e7462b40867b57efd49851 (diff)
[SCSI] lpfc: bug fixes
Following the NPIV support, the following changes have been accumulated in the testing and qualification of the driver: - Fix affinity of ELS ring to slow/deferred event processing - Fix Ring attention masks - Defer dev_loss_tmo timeout handling to worker thread - Consolidate link down error classification for better error checking - Remove unused/deprecated nlp_initiator_tmr timer - Fix for async scan - move adapter init code back into pci_probe_one context. Fix async scan interfaces. - Expand validation of ability to create vports - Extract VPI resource cnt from firmware - Tuning of Login/Reject policies to better deal with overwhelmned targets - Misc ELS and discovery fixes - Export the npiv_enable attribute to sysfs - Mailbox handling fix - Add debugfs support - A few other small misc fixes: - wrong return values, double-frees, bad locking - Added adapter failure heartbeat Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_nportdisc.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c63
1 files changed, 49 insertions, 14 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 50a247602a6b..bca2f5c9b4ba 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -36,6 +36,7 @@
36#include "lpfc_logmsg.h" 36#include "lpfc_logmsg.h"
37#include "lpfc_crtn.h" 37#include "lpfc_crtn.h"
38#include "lpfc_vport.h" 38#include "lpfc_vport.h"
39#include "lpfc_debugfs.h"
39 40
40 41
41/* Called to verify a rcv'ed ADISC was intended for us. */ 42/* Called to verify a rcv'ed ADISC was intended for us. */
@@ -204,11 +205,9 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
204 /* First check the txq */ 205 /* First check the txq */
205 spin_lock_irq(&phba->hbalock); 206 spin_lock_irq(&phba->hbalock);
206 list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { 207 list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
207 /* Check to see if iocb matches the nport we are looking 208 /* Check to see if iocb matches the nport we are looking for */
208 for */
209 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { 209 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
210 /* It matches, so deque and call compl with an 210 /* It matches, so deque and call compl with anp error */
211 error */
212 list_move_tail(&iocb->list, &completions); 211 list_move_tail(&iocb->list, &completions);
213 pring->txq_cnt--; 212 pring->txq_cnt--;
214 } 213 }
@@ -216,8 +215,7 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
216 215
217 /* Next check the txcmplq */ 216 /* Next check the txcmplq */
218 list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) { 217 list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
219 /* Check to see if iocb matches the nport we are looking 218 /* Check to see if iocb matches the nport we are looking for */
220 for */
221 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { 219 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
222 lpfc_sli_issue_abort_iotag(phba, pring, iocb); 220 lpfc_sli_issue_abort_iotag(phba, pring, iocb);
223 } 221 }
@@ -282,7 +280,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
282 stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY; 280 stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
283 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; 281 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
284 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, 282 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
285 ndlp); 283 ndlp, NULL);
286 return 0; 284 return 0;
287 } 285 }
288 } 286 }
@@ -293,7 +291,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
293 /* Reject this request because invalid parameters */ 291 /* Reject this request because invalid parameters */
294 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; 292 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
295 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; 293 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
296 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); 294 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
295 NULL);
297 return 0; 296 return 0;
298 } 297 }
299 icmd = &cmdiocb->iocb; 298 icmd = &cmdiocb->iocb;
@@ -392,13 +391,30 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
392 lpfc_els_abort(phba, ndlp); 391 lpfc_els_abort(phba, ndlp);
393 } 392 }
394 393
394 if ((vport->port_type == LPFC_NPIV_PORT &&
395 phba->cfg_vport_restrict_login)) {
396
397 /* In order to preserve RPIs, we want to cleanup
398 * the default RPI the firmware created to rcv
399 * this ELS request. The only way to do this is
400 * to register, then unregister the RPI.
401 */
402 spin_lock_irq(shost->host_lock);
403 ndlp->nlp_flag |= NLP_RM_DFLT_RPI;
404 spin_unlock_irq(shost->host_lock);
405 stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;
406 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
407 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
408 ndlp, mbox);
409 return 1;
410 }
395 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); 411 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
396 return 1; 412 return 1;
397 413
398out: 414out:
399 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; 415 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
400 stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE; 416 stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE;
401 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); 417 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
402 return 0; 418 return 0;
403} 419}
404 420
@@ -445,7 +461,7 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
445 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; 461 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
446 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS; 462 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
447 stat.un.b.vendorUnique = 0; 463 stat.un.b.vendorUnique = 0;
448 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); 464 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
449 465
450 /* 1 sec timeout */ 466 /* 1 sec timeout */
451 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ); 467 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
@@ -535,6 +551,11 @@ lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
535 roles |= FC_RPORT_ROLE_FCP_INITIATOR; 551 roles |= FC_RPORT_ROLE_FCP_INITIATOR;
536 if (ndlp->nlp_type & NLP_FCP_TARGET) 552 if (ndlp->nlp_type & NLP_FCP_TARGET)
537 roles |= FC_RPORT_ROLE_FCP_TARGET; 553 roles |= FC_RPORT_ROLE_FCP_TARGET;
554
555 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
556 "rport rolechg: role:x%x did:x%x flg:x%x",
557 roles, ndlp->nlp_DID, ndlp->nlp_flag);
558
538 fc_remote_port_rolechg(rport, roles); 559 fc_remote_port_rolechg(rport, roles);
539 } 560 }
540} 561}
@@ -657,7 +678,8 @@ lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
657 ours */ 678 ours */
658 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; 679 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
659 stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS; 680 stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
660 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); 681 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
682 NULL);
661 } else { 683 } else {
662 lpfc_rcv_plogi(vport, ndlp, cmdiocb); 684 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
663 } /* If our portname was less */ 685 } /* If our portname was less */
@@ -675,7 +697,7 @@ lpfc_rcv_prli_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
675 memset(&stat, 0, sizeof (struct ls_rjt)); 697 memset(&stat, 0, sizeof (struct ls_rjt));
676 stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY; 698 stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
677 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; 699 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
678 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); 700 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
679 return ndlp->nlp_state; 701 return ndlp->nlp_state;
680} 702}
681 703
@@ -1335,6 +1357,10 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1335 1357
1336 irsp = &rspiocb->iocb; 1358 irsp = &rspiocb->iocb;
1337 if (irsp->ulpStatus) { 1359 if (irsp->ulpStatus) {
1360 if ((vport->port_type == LPFC_NPIV_PORT) &&
1361 phba->cfg_vport_restrict_login) {
1362 goto out;
1363 }
1338 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE; 1364 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
1339 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); 1365 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
1340 return ndlp->nlp_state; 1366 return ndlp->nlp_state;
@@ -1355,6 +1381,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1355 if (!(ndlp->nlp_type & NLP_FCP_TARGET) && 1381 if (!(ndlp->nlp_type & NLP_FCP_TARGET) &&
1356 (vport->port_type == LPFC_NPIV_PORT) && 1382 (vport->port_type == LPFC_NPIV_PORT) &&
1357 phba->cfg_vport_restrict_login) { 1383 phba->cfg_vport_restrict_login) {
1384out:
1358 spin_lock_irq(shost->host_lock); 1385 spin_lock_irq(shost->host_lock);
1359 ndlp->nlp_flag |= NLP_TARGET_REMOVE; 1386 ndlp->nlp_flag |= NLP_TARGET_REMOVE;
1360 spin_unlock_irq(shost->host_lock); 1387 spin_unlock_irq(shost->host_lock);
@@ -1606,7 +1633,7 @@ lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1606 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; 1633 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1607 1634
1608 /* Ignore PLOGI if we have an outstanding LOGO */ 1635 /* Ignore PLOGI if we have an outstanding LOGO */
1609 if (ndlp->nlp_flag & NLP_LOGO_SND) { 1636 if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC)) {
1610 return ndlp->nlp_state; 1637 return ndlp->nlp_state;
1611 } 1638 }
1612 1639
@@ -1638,7 +1665,7 @@ lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1638 memset(&stat, 0, sizeof (struct ls_rjt)); 1665 memset(&stat, 0, sizeof (struct ls_rjt));
1639 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; 1666 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
1640 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE; 1667 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
1641 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp); 1668 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
1642 1669
1643 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { 1670 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
1644 if (ndlp->nlp_flag & NLP_NPR_ADISC) { 1671 if (ndlp->nlp_flag & NLP_NPR_ADISC) {
@@ -2035,6 +2062,10 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2035 phba->brd_no, vport->vpi, 2062 phba->brd_no, vport->vpi,
2036 evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag); 2063 evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag);
2037 2064
2065 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
2066 "DSM in: evt:%d ste:%d did:x%x",
2067 evt, cur_state, ndlp->nlp_DID);
2068
2038 func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt]; 2069 func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt];
2039 rc = (func) (vport, ndlp, arg, evt); 2070 rc = (func) (vport, ndlp, arg, evt);
2040 2071
@@ -2045,6 +2076,10 @@ lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2045 phba->brd_no, vport->vpi, 2076 phba->brd_no, vport->vpi,
2046 rc, ndlp->nlp_DID, ndlp->nlp_flag); 2077 rc, ndlp->nlp_DID, ndlp->nlp_flag);
2047 2078
2079 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
2080 "DSM out: ste:%d did:x%x flg:x%x",
2081 rc, ndlp->nlp_DID, ndlp->nlp_flag);
2082
2048 lpfc_nlp_put(ndlp); 2083 lpfc_nlp_put(ndlp);
2049 2084
2050 return rc; 2085 return rc;