]> err.no Git - linux-2.6/blobdiff - drivers/scsi/lpfc/lpfc_ct.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluet...
[linux-2.6] / drivers / scsi / lpfc / lpfc_ct.c
index 92441ce610ede4601dd113ee9175f7ef5ebc81e8..7fc74cf5823b5d0b8587ed5dcdd2213c73271833 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2008 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -63,7 +63,7 @@ lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
 {
        if (!mp) {
                lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                               "0146 Ignoring unsolicted CT No HBQ "
+                               "0146 Ignoring unsolicited CT No HBQ "
                                "status = x%x\n",
                                piocbq->iocb.ulpStatus);
        }
@@ -101,7 +101,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                /* Not enough posted buffers; Try posting more buffers */
                phba->fc_stat.NoRcvBuf++;
                if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
-                       lpfc_post_buffer(phba, pring, 2, 1);
+                       lpfc_post_buffer(phba, pring, 2);
                return;
        }
 
@@ -151,7 +151,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                        }
                        list_del(&iocbq->list);
                        lpfc_sli_release_iocbq(phba, iocbq);
-                       lpfc_post_buffer(phba, pring, i, 1);
+                       lpfc_post_buffer(phba, pring, i);
                }
        }
 }
@@ -294,7 +294,7 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
        /* Save for completion so we can release these resources */
        geniocb->context1 = (uint8_t *) inp;
        geniocb->context2 = (uint8_t *) outp;
-       geniocb->context_un.ndlp = ndlp;
+       geniocb->context_un.ndlp = lpfc_nlp_get(ndlp);
 
        /* Fill in payload, bp points to frame payload */
        icmd->ulpCommand = CMD_GEN_REQUEST64_CR;
@@ -438,7 +438,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
                                    (!(vport->ct_flags & FC_CT_RFF_ID)) ||
                                    (!vport->cfg_restrict_login)) {
                                        ndlp = lpfc_setup_disc_node(vport, Did);
-                                       if (ndlp) {
+                                       if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
                                                lpfc_debugfs_disc_trc(vport,
                                                LPFC_DISC_TRC_CT,
                                                "Parse GID_FTrsp: "
@@ -489,8 +489,10 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
                                                 */
                                                ndlp = lpfc_findnode_did(vport,
                                                        Did);
-                                               if (ndlp && (ndlp->nlp_type &
-                                                       NLP_FCP_TARGET))
+                                               if (ndlp &&
+                                                   NLP_CHK_NODE_ACT(ndlp)
+                                                   && (ndlp->nlp_type &
+                                                    NLP_FCP_TARGET))
                                                        lpfc_setup_disc_node
                                                                (vport, Did);
                                                else if (lpfc_ns_cmd(vport,
@@ -541,7 +543,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        struct lpfc_dmabuf *outp;
        struct lpfc_sli_ct_request *CTrsp;
        struct lpfc_nodelist *ndlp;
-       int rc, retry;
+       int rc;
 
        /* First save ndlp, before we overwrite it */
        ndlp = cmdiocb->context_un.ndlp;
@@ -561,45 +563,29 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        if (vport->load_flag & FC_UNLOADING)
                goto out;
 
-       if (lpfc_els_chk_latt(vport) || lpfc_error_lost_link(irsp)) {
+       if (lpfc_els_chk_latt(vport)) {
                lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
                                 "0216 Link event during NS query\n");
                lpfc_vport_set_state(vport, FC_VPORT_FAILED);
                goto out;
        }
-
+       if (lpfc_error_lost_link(irsp)) {
+               lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+                                "0226 NS query failed due to link event\n");
+               goto out;
+       }
        if (irsp->ulpStatus) {
                /* Check for retry */
                if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
-                       retry = 1;
-                       if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
-                               switch (irsp->un.ulpWord[4]) {
-                               case IOERR_NO_RESOURCES:
-                                       /* We don't increment the retry
-                                        * count for this case.
-                                        */
-                                       break;
-                               case IOERR_LINK_DOWN:
-                               case IOERR_SLI_ABORTED:
-                               case IOERR_SLI_DOWN:
-                                       retry = 0;
-                                       break;
-                               default:
-                                       vport->fc_ns_retry++;
-                               }
-                       }
-                       else
+                       if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
+                           irsp->un.ulpWord[4] != IOERR_NO_RESOURCES)
                                vport->fc_ns_retry++;
 
-                       if (retry) {
-                               /* CT command is being retried */
-                               rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
+                       /* CT command is being retried */
+                       rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
                                         vport->fc_ns_retry, 0);
-                               if (rc == 0) {
-                                       /* success */
-                                       goto out;
-                               }
-                       }
+                       if (rc == 0)
+                               goto out;
                }
                lpfc_vport_set_state(vport, FC_VPORT_FAILED);
                lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
@@ -773,12 +759,12 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                                 "0267 NameServer GFF Rsp "
                                 "x%x Error (%d %d) Data: x%x x%x\n",
                                 did, irsp->ulpStatus, irsp->un.ulpWord[4],
-                                vport->fc_flag, vport->fc_rscn_id_cnt)
+                                vport->fc_flag, vport->fc_rscn_id_cnt);
        }
 
        /* This is a target port, unregistered port, or the GFF_ID failed */
        ndlp = lpfc_setup_disc_node(vport, did);
-       if (ndlp) {
+       if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
                lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
                                 "0242 Process x%x GFF "
                                 "NameServer Rsp Data: x%x x%x x%x\n",
@@ -1004,7 +990,7 @@ lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        return;
 }
 
-static int
+int
 lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol,
        size_t size)
 {
@@ -1064,7 +1050,8 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
        int rc = 0;
 
        ndlp = lpfc_findnode_did(vport, NameServer_DID);
-       if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) {
+       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)
+           || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) {
                rc=1;
                goto ns_cmd_exit;
        }
@@ -1213,8 +1200,9 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
                cmpl = lpfc_cmpl_ct_cmd_rff_id;
                break;
        }
-       lpfc_nlp_get(ndlp);
-
+       /* The lpfc_ct_cmd/lpfc_get_req shall increment ndlp reference count
+        * to hold ndlp reference for the corresponding callback function.
+        */
        if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) {
                /* On success, The cmpl function will free the buffers */
                lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
@@ -1222,9 +1210,13 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
                        cmdcode, ndlp->nlp_DID, 0);
                return 0;
        }
-
        rc=6;
+
+       /* Decrement ndlp reference count to release ndlp reference held
+        * for the failed command's callback function.
+        */
        lpfc_nlp_put(ndlp);
+
        lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
 ns_cmd_free_bmp:
        kfree(bmp);
@@ -1271,6 +1263,9 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        }
 
        ndlp = lpfc_findnode_did(vport, FDMI_DID);
+       if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
+               goto fail_out;
+
        if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
                /* FDMI rsp failed */
                lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
@@ -1294,6 +1289,8 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA);
                break;
        }
+
+fail_out:
        lpfc_ct_free_iocb(phba, cmdiocb);
        return;
 }
@@ -1650,12 +1647,18 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode)
        bpl->tus.w = le32_to_cpu(bpl->tus.w);
 
        cmpl = lpfc_cmpl_ct_cmd_fdmi;
-       lpfc_nlp_get(ndlp);
 
+       /* The lpfc_ct_cmd/lpfc_get_req shall increment ndlp reference count
+        * to hold ndlp reference for the corresponding callback function.
+        */
        if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP, 0))
                return 0;
 
+       /* Decrement ndlp reference count to release ndlp reference held
+        * for the failed command's callback function.
+        */
        lpfc_nlp_put(ndlp);
+
        lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
 fdmi_cmd_free_bmp:
        kfree(bmp);
@@ -1676,20 +1679,18 @@ lpfc_fdmi_tmo(unsigned long ptr)
 {
        struct lpfc_vport *vport = (struct lpfc_vport *)ptr;
        struct lpfc_hba   *phba = vport->phba;
+       uint32_t tmo_posted;
        unsigned long iflag;
 
        spin_lock_irqsave(&vport->work_port_lock, iflag);
-       if (!(vport->work_port_events & WORKER_FDMI_TMO)) {
+       tmo_posted = vport->work_port_events & WORKER_FDMI_TMO;
+       if (!tmo_posted)
                vport->work_port_events |= WORKER_FDMI_TMO;
-               spin_unlock_irqrestore(&vport->work_port_lock, iflag);
+       spin_unlock_irqrestore(&vport->work_port_lock, iflag);
 
-               spin_lock_irqsave(&phba->hbalock, iflag);
-               if (phba->work_wait)
-                       lpfc_worker_wake_up(phba);
-               spin_unlock_irqrestore(&phba->hbalock, iflag);
-       }
-       else
-               spin_unlock_irqrestore(&vport->work_port_lock, iflag);
+       if (!tmo_posted)
+               lpfc_worker_wake_up(phba);
+       return;
 }
 
 void
@@ -1698,7 +1699,7 @@ lpfc_fdmi_timeout_handler(struct lpfc_vport *vport)
        struct lpfc_nodelist *ndlp;
 
        ndlp = lpfc_findnode_did(vport, FDMI_DID);
-       if (ndlp) {
+       if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
                if (init_utsname()->nodename[0] != '\0')
                        lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA);
                else