aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_els.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2008-01-11 01:52:36 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-23 12:29:21 -0500
commit0ff10d46cf0a373c9c855a23cc9383ba4030d8d2 (patch)
tree111eb8303ad63cecad266d507af4c2c0bfec4d5b /drivers/scsi/lpfc/lpfc_els.c
parentb18268fc631034882f5f3dd93daa248a3bfdd085 (diff)
[SCSI] lpfc 8.2.4 : Miscellaneous Discovery/ELS Fixes
Miscellaneous Discovery/ELS Fixes: - Delay free's of ELS requests if adapter reject conditions - Fix concurrent PLOGI vs ADISC state handling - Add retry mechanism for GFF_ID - Correct some illegal state transitions around RSCN timeouts - Fix missing return in FAN handling Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c56
1 files changed, 53 insertions, 3 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index bf332cba2fc0..f5e002435972 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -783,6 +783,8 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
783{ 783{
784 struct lpfc_vport *vport = ndlp->vport; 784 struct lpfc_vport *vport = ndlp->vport;
785 struct lpfc_nodelist *new_ndlp; 785 struct lpfc_nodelist *new_ndlp;
786 struct lpfc_rport_data *rdata;
787 struct fc_rport *rport;
786 struct serv_parm *sp; 788 struct serv_parm *sp;
787 uint8_t name[sizeof(struct lpfc_name)]; 789 uint8_t name[sizeof(struct lpfc_name)];
788 uint32_t rc; 790 uint32_t rc;
@@ -819,6 +821,11 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
819 lpfc_unreg_rpi(vport, new_ndlp); 821 lpfc_unreg_rpi(vport, new_ndlp);
820 new_ndlp->nlp_DID = ndlp->nlp_DID; 822 new_ndlp->nlp_DID = ndlp->nlp_DID;
821 new_ndlp->nlp_prev_state = ndlp->nlp_prev_state; 823 new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
824
825 if (ndlp->nlp_flag & NLP_NPR_2B_DISC)
826 new_ndlp->nlp_flag |= NLP_NPR_2B_DISC;
827 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
828
822 lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state); 829 lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state);
823 830
824 /* Move this back to NPR state */ 831 /* Move this back to NPR state */
@@ -826,6 +833,20 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
826 /* The new_ndlp is replacing ndlp totally, so we need 833 /* The new_ndlp is replacing ndlp totally, so we need
827 * to put ndlp on UNUSED list and try to free it. 834 * to put ndlp on UNUSED list and try to free it.
828 */ 835 */
836
837 /* Fix up the rport accordingly */
838 rport = ndlp->rport;
839 if (rport) {
840 rdata = rport->dd_data;
841 if (rdata->pnode == ndlp) {
842 lpfc_nlp_put(ndlp);
843 ndlp->rport = NULL;
844 rdata->pnode = lpfc_nlp_get(new_ndlp);
845 new_ndlp->rport = rport;
846 }
847 new_ndlp->nlp_type = ndlp->nlp_type;
848 }
849
829 lpfc_drop_node(vport, ndlp); 850 lpfc_drop_node(vport, ndlp);
830 } 851 }
831 else { 852 else {
@@ -1149,7 +1170,7 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1149 return 0; 1170 return 0;
1150} 1171}
1151 1172
1152static void 1173void
1153lpfc_more_adisc(struct lpfc_vport *vport) 1174lpfc_more_adisc(struct lpfc_vport *vport)
1154{ 1175{
1155 int sentadisc; 1176 int sentadisc;
@@ -2100,8 +2121,35 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
2100 } 2121 }
2101 /* context2 = cmd, context2->next = rsp, context3 = bpl */ 2122 /* context2 = cmd, context2->next = rsp, context3 = bpl */
2102 if (elsiocb->context2) { 2123 if (elsiocb->context2) {
2103 buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2; 2124 if (elsiocb->iocb_flag & LPFC_DELAY_MEM_FREE) {
2104 lpfc_els_free_data(phba, buf_ptr1); 2125 /* Firmware could still be in progress of DMAing
2126 * payload, so don't free data buffer till after
2127 * a hbeat.
2128 */
2129 elsiocb->iocb_flag &= ~LPFC_DELAY_MEM_FREE;
2130 buf_ptr = elsiocb->context2;
2131 elsiocb->context2 = NULL;
2132 if (buf_ptr) {
2133 buf_ptr1 = NULL;
2134 spin_lock_irq(&phba->hbalock);
2135 if (!list_empty(&buf_ptr->list)) {
2136 list_remove_head(&buf_ptr->list,
2137 buf_ptr1, struct lpfc_dmabuf,
2138 list);
2139 INIT_LIST_HEAD(&buf_ptr1->list);
2140 list_add_tail(&buf_ptr1->list,
2141 &phba->elsbuf);
2142 phba->elsbuf_cnt++;
2143 }
2144 INIT_LIST_HEAD(&buf_ptr->list);
2145 list_add_tail(&buf_ptr->list, &phba->elsbuf);
2146 phba->elsbuf_cnt++;
2147 spin_unlock_irq(&phba->hbalock);
2148 }
2149 } else {
2150 buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
2151 lpfc_els_free_data(phba, buf_ptr1);
2152 }
2105 } 2153 }
2106 2154
2107 if (elsiocb->context3) { 2155 if (elsiocb->context3) {
@@ -3027,6 +3075,8 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport)
3027 3075
3028 /* To process RSCN, first compare RSCN data with NameServer */ 3076 /* To process RSCN, first compare RSCN data with NameServer */
3029 vport->fc_ns_retry = 0; 3077 vport->fc_ns_retry = 0;
3078 vport->num_disc_nodes = 0;
3079
3030 ndlp = lpfc_findnode_did(vport, NameServer_DID); 3080 ndlp = lpfc_findnode_did(vport, NameServer_DID);
3031 if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { 3081 if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
3032 /* Good ndlp, issue CT Request to NameServer */ 3082 /* Good ndlp, issue CT Request to NameServer */