]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/scsi/lpfc/lpfc_init.c
Fix crash after issuing lip reset
[karo-tx-linux.git] / drivers / scsi / lpfc / lpfc_init.c
index 6cc561b042118ed6d172dddb8221d77c8a793ee4..b1957f868eeeabdb8e05d1241d3b3fa9c1f3e2df 100644 (file)
@@ -2874,34 +2874,38 @@ lpfc_sli4_node_prep(struct lpfc_hba *phba)
 {
        struct lpfc_nodelist  *ndlp, *next_ndlp;
        struct lpfc_vport **vports;
-       int i;
+       int i, rpi;
+       unsigned long flags;
 
        if (phba->sli_rev != LPFC_SLI_REV4)
                return;
 
        vports = lpfc_create_vport_work_array(phba);
-       if (vports != NULL) {
-               for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
-                       if (vports[i]->load_flag & FC_UNLOADING)
-                               continue;
+       if (vports == NULL)
+               return;
 
-                       list_for_each_entry_safe(ndlp, next_ndlp,
-                                                &vports[i]->fc_nodes,
-                                                nlp_listp) {
-                               if (NLP_CHK_NODE_ACT(ndlp)) {
-                                       ndlp->nlp_rpi =
-                                               lpfc_sli4_alloc_rpi(phba);
-                                       lpfc_printf_vlog(ndlp->vport, KERN_INFO,
-                                                        LOG_NODE,
-                                                        "0009 rpi:%x DID:%x "
-                                                        "flg:%x map:%x %p\n",
-                                                        ndlp->nlp_rpi,
-                                                        ndlp->nlp_DID,
-                                                        ndlp->nlp_flag,
-                                                        ndlp->nlp_usg_map,
-                                                        ndlp);
-                               }
+       for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
+               if (vports[i]->load_flag & FC_UNLOADING)
+                       continue;
+
+               list_for_each_entry_safe(ndlp, next_ndlp,
+                                        &vports[i]->fc_nodes,
+                                        nlp_listp) {
+                       if (!NLP_CHK_NODE_ACT(ndlp))
+                               continue;
+                       rpi = lpfc_sli4_alloc_rpi(phba);
+                       if (rpi == LPFC_RPI_ALLOC_ERROR) {
+                               spin_lock_irqsave(&phba->ndlp_lock, flags);
+                               NLP_CLR_NODE_ACT(ndlp);
+                               spin_unlock_irqrestore(&phba->ndlp_lock, flags);
+                               continue;
                        }
+                       ndlp->nlp_rpi = rpi;
+                       lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE,
+                                        "0009 rpi:%x DID:%x "
+                                        "flg:%x map:%x %p\n", ndlp->nlp_rpi,
+                                        ndlp->nlp_DID, ndlp->nlp_flag,
+                                        ndlp->nlp_usg_map, ndlp);
                }
        }
        lpfc_destroy_vport_work_array(phba, vports);
@@ -3508,6 +3512,12 @@ lpfc_sli4_scsi_sgl_update(struct lpfc_hba *phba)
        spin_unlock(&phba->scsi_buf_list_put_lock);
        spin_unlock_irq(&phba->scsi_buf_list_get_lock);
 
+       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                       "6060 Current allocated SCSI xri-sgl count:%d, "
+                       "maximum  SCSI xri count:%d (split:%d)\n",
+                       phba->sli4_hba.scsi_xri_cnt,
+                       phba->sli4_hba.scsi_xri_max, phba->cfg_xri_split);
+
        if (phba->sli4_hba.scsi_xri_cnt > phba->sli4_hba.scsi_xri_max) {
                /* max scsi xri shrinked below the allocated scsi buffers */
                scsi_xri_cnt = phba->sli4_hba.scsi_xri_cnt -
@@ -4716,10 +4726,9 @@ lpfc_sli4_perform_vport_cvl(struct lpfc_vport *vport)
        ndlp = lpfc_findnode_did(vport, Fabric_DID);
        if (!ndlp) {
                /* Cannot find existing Fabric ndlp, so allocate a new one */
-               ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+               ndlp = lpfc_nlp_init(vport, Fabric_DID);
                if (!ndlp)
                        return 0;
-               lpfc_nlp_init(vport, ndlp, Fabric_DID);
                /* Set the node type */
                ndlp->nlp_type |= NLP_FABRIC;
                /* Put ndlp onto node list */
@@ -5809,6 +5818,12 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
        INIT_LIST_HEAD(&phba->sli4_hba.lpfc_vfi_blk_list);
        INIT_LIST_HEAD(&phba->lpfc_vpi_blk_list);
 
+       /* Initialize mboxq lists. If the early init routines fail
+        * these lists need to be correctly initialized.
+        */
+       INIT_LIST_HEAD(&phba->sli.mboxq);
+       INIT_LIST_HEAD(&phba->sli.mboxq_cmpl);
+
        /* initialize optic_state to 0xFF */
        phba->sli4_hba.lnk_info.optic_state = 0xff;
 
@@ -5874,6 +5889,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                                        "READ_NV, mbxStatus x%x\n",
                                        bf_get(lpfc_mqe_command, &mboxq->u.mqe),
                                        bf_get(lpfc_mqe_status, &mboxq->u.mqe));
+                       mempool_free(mboxq, phba->mbox_mem_pool);
                        rc = -EIO;
                        goto out_free_bsmbx;
                }
@@ -7799,7 +7815,7 @@ lpfc_alloc_fcp_wq_cq(struct lpfc_hba *phba, int wqidx)
 
        /* Create Fast Path FCP WQs */
        wqesize = (phba->fcp_embed_io) ?
-                               LPFC_WQE128_SIZE : phba->sli4_hba.wq_esize;
+               LPFC_WQE128_SIZE : phba->sli4_hba.wq_esize;
        qdesc = lpfc_sli4_queue_alloc(phba, wqesize, phba->sli4_hba.wq_ecount);
        if (!qdesc) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -7830,7 +7846,7 @@ int
 lpfc_sli4_queue_create(struct lpfc_hba *phba)
 {
        struct lpfc_queue *qdesc;
-       int idx, io_channel, max;
+       int idx, io_channel;
 
        /*
         * Create HBA Record arrays.
@@ -7991,15 +8007,6 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
                if (lpfc_alloc_nvme_wq_cq(phba, idx))
                        goto out_error;
 
-       /* allocate MRQ CQs */
-       max = phba->cfg_nvme_io_channel;
-       if (max < phba->cfg_nvmet_mrq)
-               max = phba->cfg_nvmet_mrq;
-
-       for (idx = 0; idx < max; idx++)
-               if (lpfc_alloc_nvme_wq_cq(phba, idx))
-                       goto out_error;
-
        if (phba->nvmet_support) {
                for (idx = 0; idx < phba->cfg_nvmet_mrq; idx++) {
                        qdesc = lpfc_sli4_queue_alloc(phba,
@@ -8221,11 +8228,11 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
 
        /* Release FCP cqs */
        lpfc_sli4_release_queues(&phba->sli4_hba.fcp_cq,
-                                       phba->cfg_fcp_io_channel);
+                                phba->cfg_fcp_io_channel);
 
        /* Release FCP wqs */
        lpfc_sli4_release_queues(&phba->sli4_hba.fcp_wq,
-                                       phba->cfg_fcp_io_channel);
+                                phba->cfg_fcp_io_channel);
 
        /* Release FCP CQ mapping array */
        lpfc_sli4_release_queue_map(&phba->sli4_hba.fcp_cq_map);
@@ -8571,15 +8578,15 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "0528 %s not allocated\n",
                                phba->sli4_hba.mbx_cq ?
-                                               "Mailbox WQ" : "Mailbox CQ");
+                               "Mailbox WQ" : "Mailbox CQ");
                rc = -ENOMEM;
                goto out_destroy;
        }
 
        rc = lpfc_create_wq_cq(phba, phba->sli4_hba.hba_eq[0],
-                                       phba->sli4_hba.mbx_cq,
-                                       phba->sli4_hba.mbx_wq,
-                                       NULL, 0, LPFC_MBOX);
+                              phba->sli4_hba.mbx_cq,
+                              phba->sli4_hba.mbx_wq,
+                              NULL, 0, LPFC_MBOX);
        if (rc) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                        "0529 Failed setup of mailbox WQ/CQ: rc = 0x%x\n",
@@ -10048,9 +10055,14 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
        /* Stop kthread signal shall trigger work_done one more time */
        kthread_stop(phba->worker_thread);
 
+       /* Unset the queues shared with the hardware then release all
+        * allocated resources.
+        */
+       lpfc_sli4_queue_unset(phba);
+       lpfc_sli4_queue_destroy(phba);
+
        /* Reset SLI4 HBA FCoE function */
        lpfc_pci_function_reset(phba);
-       lpfc_sli4_queue_destroy(phba);
 
        /* Stop the SLI4 device port */
        phba->pport->work_port_events = 0;
@@ -10306,6 +10318,7 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
        }
 
        /* Initialize and populate the iocb list per host */
+
        error = lpfc_init_iocb_list(phba, LPFC_IOCB_LIST_CNT);
        if (error) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -11051,7 +11064,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        struct lpfc_hba   *phba;
        struct lpfc_vport *vport = NULL;
        struct Scsi_Host  *shost = NULL;
-       int error;
+       int error, cnt;
        uint32_t cfg_mode, intr_mode;
 
        /* Allocate memory for HBA structure */
@@ -11085,12 +11098,15 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
                goto out_unset_pci_mem_s4;
        }
 
-       /* Initialize and populate the iocb list per host */
+       cnt = phba->cfg_iocb_cnt * 1024;
+       if (phba->nvmet_support)
+               cnt += phba->cfg_nvmet_mrq_post * phba->cfg_nvmet_mrq;
 
+       /* Initialize and populate the iocb list per host */
        lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                       "2821 initialize iocb list %d.\n",
-                       phba->cfg_iocb_cnt*1024);
-       error = lpfc_init_iocb_list(phba, phba->cfg_iocb_cnt*1024);
+                       "2821 initialize iocb list %d total %d\n",
+                       phba->cfg_iocb_cnt, cnt);
+       error = lpfc_init_iocb_list(phba, cnt);
 
        if (error) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -11177,7 +11193,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        if ((phba->nvmet_support == 0) &&
            (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) {
                /* Create NVME binding with nvme_fc_transport. This
-                * ensures the vport is initialized.
+                * ensures the vport is initialized.  If the localport
+                * create fails, it should not unload the driver to
+                * support field issues.
                 */
                error = lpfc_nvme_create_localport(vport);
                if (error) {
@@ -11185,7 +11203,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
                                        "6004 NVME registration failed, "
                                        "error x%x\n",
                                        error);
-                       goto out_disable_intr;
                }
        }