fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / scsi / lpfc / lpfc_nportdisc.c
index 27d60ad..0c7e731 100644 (file)
@@ -179,7 +179,7 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
 
        /* Abort outstanding I/O on NPort <nlp_DID> */
        lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-                       "%d:0201 Abort outstanding I/O on NPort x%x "
+                       "%d:0205 Abort outstanding I/O on NPort x%x "
                        "Data: x%x x%x x%x\n",
                        phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
                        ndlp->nlp_state, ndlp->nlp_rpi);
@@ -393,6 +393,20 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
        mbox->context2  = ndlp;
        ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
 
+       /*
+        * If there is an outstanding PLOGI issued, abort it before
+        * sending ACC rsp for received PLOGI. If pending plogi
+        * is not canceled here, the plogi will be rejected by
+        * remote port and will be retried. On a configuration with
+        * single discovery thread, this will cause a huge delay in
+        * discovery. Also this will cause multiple state machines
+        * running in parallel for this node.
+        */
+       if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) {
+               /* software abort outstanding PLOGI */
+               lpfc_els_abort(phba, ndlp, 1);
+       }
+
        lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
        return 1;
 
@@ -725,7 +739,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
                            uint32_t evt)
 {
        struct lpfc_iocbq *cmdiocb, *rspiocb;
-       struct lpfc_dmabuf *pcmd, *prsp;
+       struct lpfc_dmabuf *pcmd, *prsp, *mp;
        uint32_t *lp;
        IOCB_t *irsp;
        struct serv_parm *sp;
@@ -815,6 +829,9 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
                                      NLP_REGLOGIN_LIST);
                        return ndlp->nlp_state;
                }
+               mp = (struct lpfc_dmabuf *)mbox->context1;
+               lpfc_mbuf_free(phba, mp->virt, mp->phys);
+               kfree(mp);
                mempool_free(mbox, phba->mbox_mem_pool);
        } else {
                mempool_free(mbox, phba->mbox_mem_pool);
@@ -1110,6 +1127,17 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
                                phba->brd_no,
                                did, mb->mbxStatus, phba->hba_state);
 
+               /*
+                * If RegLogin failed due to lack of HBA resources do not
+                * retry discovery.
+                */
+               if (mb->mbxStatus == MBXERR_RPI_FULL) {
+                       ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
+                       ndlp->nlp_state = NLP_STE_UNUSED_NODE;
+                       lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
+                       return ndlp->nlp_state;
+               }
+
                /* Put ndlp in npr list set plogi timer for 1 sec */
                mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
                spin_lock_irq(phba->host->host_lock);
@@ -1590,7 +1618,13 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba,
 
        lpfc_rcv_padisc(phba, ndlp, cmdiocb);
 
-       if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
+       /*
+        * Do not start discovery if discovery is about to start
+        * or discovery in progress for this node. Starting discovery
+        * here will affect the counting of discovery threads.
+        */
+       if (!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
+               !(ndlp->nlp_flag & NLP_NPR_2B_DISC)){
                if (ndlp->nlp_flag & NLP_NPR_ADISC) {
                        ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
                        ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
@@ -1782,7 +1816,7 @@ lpfc_device_recov_npr_node(struct lpfc_hba * phba,
  */
 /*
  * For a Link Down, all nodes on the ADISC, PLOGI, unmapped or mapped
- * lists will receive a DEVICE_RECOVERY event. If the linkdown or nodev timers
+ * lists will receive a DEVICE_RECOVERY event. If the linkdown or devloss timers
  * expire, all effected nodes will receive a DEVICE_RM event.
  */
 /*