scsi: lpfc: Fix memory leak on lcb_context
[linux-2.6-microblaze.git] / drivers / scsi / lpfc / lpfc_els.c
index 388728f..cfd95ca 100644 (file)
@@ -1424,7 +1424,8 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
                if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
                        ndlp = (struct lpfc_nodelist *)(iocb->context1);
                        if (ndlp && (ndlp->nlp_DID == Fabric_DID))
-                               lpfc_sli_issue_abort_iotag(phba, pring, iocb);
+                               lpfc_sli_issue_abort_iotag(phba, pring, iocb,
+                                                          NULL);
                }
        }
        spin_unlock_irq(&phba->hbalock);
@@ -1508,6 +1509,10 @@ lpfc_initial_fdisc(struct lpfc_vport *vport)
                ndlp = lpfc_nlp_init(vport, Fabric_DID);
                if (!ndlp)
                        return 0;
+
+               /* NPIV is only supported in Fabrics. */
+               ndlp->nlp_type |= NLP_FABRIC;
+
                /* Put ndlp onto node list */
                lpfc_enqueue_node(vport, ndlp);
        }
@@ -2831,8 +2836,9 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        /* LOGO completes to NPort <nlp_DID> */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
                         "0105 LOGO completes to NPort x%x "
-                        "Data: x%x x%x x%x x%x\n",
-                        ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4],
+                        "refcnt %d nflags x%x Data: x%x x%x x%x x%x\n",
+                        ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp->nlp_flag,
+                        irsp->ulpStatus, irsp->un.ulpWord[4],
                         irsp->ulpTimeout, vport->num_disc_nodes);
 
        if (lpfc_els_chk_latt(vport)) {
@@ -2840,17 +2846,6 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                goto out;
        }
 
-       /* Check to see if link went down during discovery */
-       if (ndlp->nlp_flag & NLP_TARGET_REMOVE) {
-               /* NLP_EVT_DEVICE_RM should unregister the RPI
-                * which should abort all outstanding IOs.
-                */
-               lpfc_disc_state_machine(vport, ndlp, cmdiocb,
-                                       NLP_EVT_DEVICE_RM);
-               skip_recovery = 1;
-               goto out;
-       }
-
        /* The LOGO will not be retried on failure.  A LOGO was
         * issued to the remote rport and a ACC or RJT or no Answer are
         * all acceptable.  Note the failure and move forward with
@@ -2872,6 +2867,19 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        /* Call state machine. This will unregister the rpi if needed. */
        lpfc_disc_state_machine(vport, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO);
 
+       /* The driver sets this flag for an NPIV instance that doesn't want to
+        * log into the remote port.
+        */
+       if (ndlp->nlp_flag & NLP_TARGET_REMOVE) {
+               lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+                                       NLP_EVT_DEVICE_RM);
+               lpfc_els_free_iocb(phba, cmdiocb);
+               lpfc_nlp_put(ndlp);
+
+               /* Presume the node was released. */
+               return;
+       }
+
 out:
        /* Driver is done with the IO.  */
        lpfc_els_free_iocb(phba, cmdiocb);
@@ -4395,10 +4403,10 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID);
        /* ACC to LOGO completes to NPort <nlp_DID> */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
-                        "0109 ACC to LOGO completes to NPort x%x "
+                        "0109 ACC to LOGO completes to NPort x%x refcnt %d"
                         "Data: x%x x%x x%x\n",
-                        ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
-                        ndlp->nlp_rpi);
+                        ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp->nlp_flag,
+                        ndlp->nlp_state, ndlp->nlp_rpi);
 
        if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
                /* NPort Recovery mode or node is just allocated */
@@ -6507,18 +6515,20 @@ lpfc_els_rcv_lcb(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
        lcb_context->ndlp = lpfc_nlp_get(ndlp);
        if (!lcb_context->ndlp) {
                rjt_err = LSRJT_UNABLE_TPC;
-               goto rjt;
+               goto rjt_free;
        }
 
        if (lpfc_sli4_set_beacon(vport, lcb_context, state)) {
                lpfc_printf_vlog(ndlp->vport, KERN_ERR, LOG_TRACE_EVENT,
                                 "0193 failed to send mail box");
-               kfree(lcb_context);
                lpfc_nlp_put(ndlp);
                rjt_err = LSRJT_UNABLE_TPC;
-               goto rjt;
+               goto rjt_free;
        }
        return 0;
+
+rjt_free:
+       kfree(lcb_context);
 rjt:
        memset(&stat, 0, sizeof(stat));
        stat.un.b.lsRjtRsnCode = rjt_err;
@@ -8128,7 +8138,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
                         remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
                spin_lock_irq(&phba->hbalock);
                list_del_init(&piocb->dlist);
-               lpfc_sli_issue_abort_iotag(phba, pring, piocb);
+               lpfc_sli_issue_abort_iotag(phba, pring, piocb, NULL);
                spin_unlock_irq(&phba->hbalock);
        }
 
@@ -8228,7 +8238,7 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
        list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) {
                spin_lock_irqsave(&phba->hbalock, iflags);
                list_del_init(&piocb->dlist);
-               lpfc_sli_issue_abort_iotag(phba, pring, piocb);
+               lpfc_sli_issue_abort_iotag(phba, pring, piocb, NULL);
                spin_unlock_irqrestore(&phba->hbalock, iflags);
        }
        if (!list_empty(&abort_list))
@@ -8646,9 +8656,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
        /* ELS command <elsCmd> received from NPORT <did> */
        lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
                         "0112 ELS command x%x received from NPORT x%x "
-                        "Data: x%x x%x x%x x%x\n",
-                       cmd, did, vport->port_state, vport->fc_flag,
-                       vport->fc_myDID, vport->fc_prevDID);
+                        "refcnt %d Data: x%x x%x x%x x%x\n",
+                        cmd, did, kref_read(&ndlp->kref), vport->port_state,
+                        vport->fc_flag, vport->fc_myDID, vport->fc_prevDID);
 
        /* reject till our FLOGI completes or PLOGI assigned DID via PT2PT */
        if ((vport->port_state < LPFC_FABRIC_CFG_LINK) &&
@@ -8728,7 +8738,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 
                lpfc_els_rcv_flogi(vport, elsiocb, ndlp);
                if (newnode)
-                       lpfc_nlp_put(ndlp);
+                       lpfc_disc_state_machine(vport, ndlp, NULL,
+                                       NLP_EVT_DEVICE_RM);
                break;
        case ELS_CMD_LOGO:
                lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -8770,7 +8781,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                phba->fc_stat.elsRcvRSCN++;
                lpfc_els_rcv_rscn(vport, elsiocb, ndlp);
                if (newnode)
-                       lpfc_nlp_put(ndlp);
+                       lpfc_disc_state_machine(vport, ndlp, NULL,
+                                       NLP_EVT_DEVICE_RM);
                break;
        case ELS_CMD_ADISC:
                lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -8848,7 +8860,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                phba->fc_stat.elsRcvLIRR++;
                lpfc_els_rcv_lirr(vport, elsiocb, ndlp);
                if (newnode)
-                       lpfc_nlp_put(ndlp);
+                       lpfc_disc_state_machine(vport, ndlp, NULL,
+                                       NLP_EVT_DEVICE_RM);
                break;
        case ELS_CMD_RLS:
                lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -8858,7 +8871,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                phba->fc_stat.elsRcvRLS++;
                lpfc_els_rcv_rls(vport, elsiocb, ndlp);
                if (newnode)
-                       lpfc_nlp_put(ndlp);
+                       lpfc_disc_state_machine(vport, ndlp, NULL,
+                                       NLP_EVT_DEVICE_RM);
                break;
        case ELS_CMD_RPL:
                lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -8868,7 +8882,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                phba->fc_stat.elsRcvRPL++;
                lpfc_els_rcv_rpl(vport, elsiocb, ndlp);
                if (newnode)
-                       lpfc_nlp_put(ndlp);
+                       lpfc_disc_state_machine(vport, ndlp, NULL,
+                                       NLP_EVT_DEVICE_RM);
                break;
        case ELS_CMD_RNID:
                lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -8878,7 +8893,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                phba->fc_stat.elsRcvRNID++;
                lpfc_els_rcv_rnid(vport, elsiocb, ndlp);
                if (newnode)
-                       lpfc_nlp_put(ndlp);
+                       lpfc_disc_state_machine(vport, ndlp, NULL,
+                                       NLP_EVT_DEVICE_RM);
                break;
        case ELS_CMD_RTV:
                lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -8887,7 +8903,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                phba->fc_stat.elsRcvRTV++;
                lpfc_els_rcv_rtv(vport, elsiocb, ndlp);
                if (newnode)
-                       lpfc_nlp_put(ndlp);
+                       lpfc_disc_state_machine(vport, ndlp, NULL,
+                                       NLP_EVT_DEVICE_RM);
                break;
        case ELS_CMD_RRQ:
                lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -8897,7 +8914,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                phba->fc_stat.elsRcvRRQ++;
                lpfc_els_rcv_rrq(vport, elsiocb, ndlp);
                if (newnode)
-                       lpfc_nlp_put(ndlp);
+                       lpfc_disc_state_machine(vport, ndlp, NULL,
+                                       NLP_EVT_DEVICE_RM);
                break;
        case ELS_CMD_ECHO:
                lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
@@ -8907,7 +8925,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                phba->fc_stat.elsRcvECHO++;
                lpfc_els_rcv_echo(vport, elsiocb, ndlp);
                if (newnode)
-                       lpfc_nlp_put(ndlp);
+                       lpfc_disc_state_machine(vport, ndlp, NULL,
+                                       NLP_EVT_DEVICE_RM);
                break;
        case ELS_CMD_REC:
                /* receive this due to exchange closed */
@@ -8938,7 +8957,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                                 "0115 Unknown ELS command x%x "
                                 "received from NPORT x%x\n", cmd, did);
                if (newnode)
-                       lpfc_nlp_put(ndlp);
+                       lpfc_disc_state_machine(vport, ndlp, NULL,
+                                       NLP_EVT_DEVICE_RM);
                break;
        }
 
@@ -8952,7 +8972,8 @@ lsrjt:
                                    NULL);
                /* Remove the reference from above for new nodes. */
                if (newnode)
-                       lpfc_nlp_put(ndlp);
+                       lpfc_disc_state_machine(vport, ndlp, NULL,
+                                       NLP_EVT_DEVICE_RM);
        }
 
        /* Release the reference on this elsiocb, not the ndlp. */
@@ -9129,9 +9150,9 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
        spin_lock_irq(shost->host_lock);
        if (vport->fc_flag & FC_DISC_DELAYED) {
                spin_unlock_irq(shost->host_lock);
-               lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
-                               "3334 Delay fc port discovery for %d seconds\n",
-                               phba->fc_ratov);
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
+                                "3334 Delay fc port discovery for %d secs\n",
+                                phba->fc_ratov);
                mod_timer(&vport->delayed_disc_tmo,
                        jiffies + msecs_to_jiffies(1000 * phba->fc_ratov));
                return;