phba->cfg_sg_seg_cnt = LPFC_DEFAULT_MENLO_SG_SEG_CNT;
        }
 
+       if (!phba->sli.ring)
+               phba->sli.ring = (struct lpfc_sli_ring *)
+                       kzalloc(LPFC_SLI3_MAX_RING *
+                       sizeof(struct lpfc_sli_ring), GFP_KERNEL);
+       if (!phba->sli.ring)
+               return -ENOMEM;
+
        /*
         * Since the sg_tablesize is module parameter, the sg_dma_buf_size
         * used to create the sg_dma_buf_pool must be dynamically calculated.
        if (phba->cfg_enable_bg)
                sges_per_segment = 2;
 
+       /*
+        * For SLI4, instead of using ring 0 (LPFC_FCP_RING) for FCP commands
+        * we will associate a new ring, for each FCP fastpath EQ/CQ/WQ tuple.
+        */
+       if (!phba->sli.ring)
+               phba->sli.ring = kzalloc(
+                       (LPFC_SLI3_MAX_RING + phba->cfg_fcp_eq_count) *
+                       sizeof(struct lpfc_sli_ring), GFP_KERNEL);
+       if (!phba->sli.ring)
+               return -ENOMEM;
        /*
         * Since the sg_tablesize is module parameter, the sg_dma_buf_size
         * used to create the sg_dma_buf_pool must be dynamically calculated.
        /* Release the driver assigned board number */
        idr_remove(&lpfc_hba_index, phba->brd_no);
 
+       /* Free memory allocated with sli rings */
+       kfree(phba->sli.ring);
+       phba->sli.ring = NULL;
+
        kfree(phba);
        return;
 }
 int
 lpfc_sli4_queue_setup(struct lpfc_hba *phba)
 {
+       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_sli_ring *pring;
        int rc = -ENOMEM;
        int fcp_eqidx, fcp_cqidx, fcp_wqidx;
        int fcp_cq_index = 0;
                                "rc = 0x%x\n", rc);
                goto out_destroy_mbx_wq;
        }
+
+       /* Bind this WQ to the ELS ring */
+       pring = &psli->ring[LPFC_ELS_RING];
+       pring->sli.sli4.wqp = (void *)phba->sli4_hba.els_wq;
+       phba->sli4_hba.els_cq->pring = pring;
+
        lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
                        "2590 ELS WQ setup: wq-id=%d, parent cq-id=%d\n",
                        phba->sli4_hba.els_wq->queue_id,
                                        "WQ (%d), rc = 0x%x\n", fcp_wqidx, rc);
                        goto out_destroy_fcp_wq;
                }
+
+               /* Bind this WQ to the next FCP ring */
+               pring = &psli->ring[MAX_SLI3_CONFIGURED_RINGS + fcp_wqidx];
+               pring->sli.sli4.wqp = (void *)phba->sli4_hba.fcp_wq[fcp_wqidx];
+               phba->sli4_hba.fcp_cq[fcp_cq_index]->pring = pring;
+
                lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
                                "2591 FCP WQ setup: wq[%d]-id=%d, "
                                "parent cq[%d]-id=%d\n",
 
  *
  * Return: index into SLI4 fast-path FCP queue index.
  **/
-static uint32_t
+static inline uint32_t
 lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba)
 {
-       ++phba->fcp_qidx;
-       if (phba->fcp_qidx >= phba->cfg_fcp_wq_count)
-               phba->fcp_qidx = 0;
+       int i;
 
-       return phba->fcp_qidx;
+       i = atomic_add_return(1, &phba->fcp_qidx);
+       i = (i % phba->cfg_fcp_wq_count);
+       return i;
 }
 
 /**
 
        if ((piocb->iocb_flag & LPFC_IO_FCP) ||
                (piocb->iocb_flag & LPFC_USE_FCPWQIDX)) {
-               /*
-                * For FCP command IOCB, get a new WQ index to distribute
-                * WQE across the WQsr. On the other hand, for abort IOCB,
-                * it carries the same WQ index to the original command
-                * IOCB.
-                */
-               if (piocb->iocb_flag & LPFC_IO_FCP)
-                       piocb->fcp_wqidx = lpfc_sli4_scmd_to_wqidx_distr(phba);
-               if (unlikely(!phba->sli4_hba.fcp_wq))
-                       return IOCB_ERROR;
                if (lpfc_sli4_wq_put(phba->sli4_hba.fcp_wq[piocb->fcp_wqidx],
                                     &wqe))
                        return IOCB_ERROR;
 lpfc_sli_issue_iocb(struct lpfc_hba *phba, uint32_t ring_number,
                    struct lpfc_iocbq *piocb, uint32_t flag)
 {
-       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+       struct lpfc_sli_ring *pring;
        unsigned long iflags;
-       int rc;
+       int rc, idx;
 
        if (phba->sli_rev == LPFC_SLI_REV4) {
+               if (piocb->iocb_flag &  LPFC_IO_FCP) {
+                       if (unlikely(!phba->sli4_hba.fcp_wq))
+                               return IOCB_ERROR;
+                       idx = lpfc_sli4_scmd_to_wqidx_distr(phba);
+                       piocb->fcp_wqidx = idx;
+                       ring_number = MAX_SLI3_CONFIGURED_RINGS + idx;
+               }
                pring = &phba->sli.ring[ring_number];
                spin_lock_irqsave(&pring->ring_lock, iflags);
                rc = __lpfc_sli_issue_iocb(phba, ring_number, piocb, flag);
        struct lpfc_sli *psli = &phba->sli;
        struct lpfc_sli_ring *pring;
 
-       psli->num_rings = MAX_CONFIGURED_RINGS;
+       psli->num_rings = MAX_SLI3_CONFIGURED_RINGS;
+       if (phba->sli_rev == LPFC_SLI_REV4)
+               psli->num_rings += phba->cfg_fcp_eq_count;
        psli->sli_flag = 0;
        psli->fcp_ring = LPFC_FCP_RING;
        psli->next_ring = LPFC_FCP_NEXT_RING;
 /**
  * lpfc_sli4_sp_handle_els_wcqe - Handle els work-queue completion event
  * @phba: Pointer to HBA context object.
+ * @cq: Pointer to associated CQ
  * @wcqe: Pointer to work-queue completion queue entry.
  *
  * This routine handles an ELS work-queue completion event.
  * Return: true if work posted to worker thread, otherwise false.
  **/
 static bool
-lpfc_sli4_sp_handle_els_wcqe(struct lpfc_hba *phba,
+lpfc_sli4_sp_handle_els_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
                             struct lpfc_wcqe_complete *wcqe)
 {
        struct lpfc_iocbq *irspiocbq;
        unsigned long iflags;
-       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+       struct lpfc_sli_ring *pring = cq->pring;
 
        /* Get an irspiocbq for later ELS response processing use */
        irspiocbq = lpfc_sli_get_iocbq(phba);
        case CQE_CODE_COMPL_WQE:
                /* Process the WQ/RQ complete event */
                phba->last_completion_time = jiffies;
-               workposted = lpfc_sli4_sp_handle_els_wcqe(phba,
+               workposted = lpfc_sli4_sp_handle_els_wcqe(phba, cq,
                                (struct lpfc_wcqe_complete *)&cqevt);
                break;
        case CQE_CODE_RELEASE_WQE:
 
 /**
  * lpfc_sli4_fp_handle_fcp_wcqe - Process fast-path work queue completion entry
- * @eqe: Pointer to fast-path completion queue entry.
+ * @phba: Pointer to HBA context object.
+ * @cq: Pointer to associated CQ
+ * @wcqe: Pointer to work-queue completion queue entry.
  *
  * This routine process a fast-path work queue completion entry from fast-path
  * event queue for FCP command response completion.
  **/
 static void
-lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba,
+lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
                             struct lpfc_wcqe_complete *wcqe)
 {
-       struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_FCP_RING];
+       struct lpfc_sli_ring *pring = cq->pring;
        struct lpfc_iocbq *cmdiocbq;
        struct lpfc_iocbq irspiocbq;
        unsigned long iflags;
                cq->CQ_wq++;
                /* Process the WQ complete event */
                phba->last_completion_time = jiffies;
-               lpfc_sli4_fp_handle_fcp_wcqe(phba,
+               lpfc_sli4_fp_handle_fcp_wcqe(phba, cq,
                                (struct lpfc_wcqe_complete *)&wcqe);
                break;
        case CQE_CODE_RELEASE_WQE: