[SCSI] lpfc 8.3.31: Correct handling of SLI4-port XRI resource-provisioning profile...
authorJames Smart <james.smart@emulex.com>
Thu, 10 May 2012 01:16:12 +0000 (21:16 -0400)
committerJames Bottomley <JBottomley@Parallels.com>
Thu, 17 May 2012 09:29:22 +0000 (10:29 +0100)
Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/lpfc/lpfc_crtn.h
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli4.h

index 330dd7192a7f0216373228d0aab44156caf4e019..620fa45866dc1edb0c0038c1640718040fb95170 100644 (file)
@@ -460,6 +460,7 @@ int lpfc_hba_init_link_fc_topology(struct lpfc_hba *, uint32_t, uint32_t);
 int lpfc_issue_reg_vfi(struct lpfc_vport *);
 int lpfc_issue_unreg_vfi(struct lpfc_vport *);
 int lpfc_selective_reset(struct lpfc_hba *);
-int lpfc_sli4_read_config(struct lpfc_hba *phba);
-int lpfc_scsi_buf_update(struct lpfc_hba *phba);
-void lpfc_sli4_node_prep(struct lpfc_hba *phba);
+int lpfc_sli4_read_config(struct lpfc_hba *);
+void lpfc_sli4_node_prep(struct lpfc_hba *);
+int lpfc_sli4_xri_sgl_update(struct lpfc_hba *);
+void lpfc_free_sgl_list(struct lpfc_hba *, struct list_head *);
index 91f09761bd328136142fd3a37bd737789c6cee47..24344c1fab5a1f596ed46207fffd6dc4a51699fe 100644 (file)
@@ -228,19 +228,15 @@ struct lpfc_sli4_flags {
 #define lpfc_idx_rsrc_rdy_MASK         0x00000001
 #define lpfc_idx_rsrc_rdy_WORD         word0
 #define LPFC_IDX_RSRC_RDY              1
-#define lpfc_xri_rsrc_rdy_SHIFT                1
-#define lpfc_xri_rsrc_rdy_MASK         0x00000001
-#define lpfc_xri_rsrc_rdy_WORD         word0
-#define LPFC_XRI_RSRC_RDY              1
-#define lpfc_rpi_rsrc_rdy_SHIFT                2
+#define lpfc_rpi_rsrc_rdy_SHIFT                1
 #define lpfc_rpi_rsrc_rdy_MASK         0x00000001
 #define lpfc_rpi_rsrc_rdy_WORD         word0
 #define LPFC_RPI_RSRC_RDY              1
-#define lpfc_vpi_rsrc_rdy_SHIFT                3
+#define lpfc_vpi_rsrc_rdy_SHIFT                2
 #define lpfc_vpi_rsrc_rdy_MASK         0x00000001
 #define lpfc_vpi_rsrc_rdy_WORD         word0
 #define LPFC_VPI_RSRC_RDY              1
-#define lpfc_vfi_rsrc_rdy_SHIFT                4
+#define lpfc_vfi_rsrc_rdy_SHIFT                3
 #define lpfc_vfi_rsrc_rdy_MASK         0x00000001
 #define lpfc_vfi_rsrc_rdy_WORD         word0
 #define LPFC_VFI_RSRC_RDY              1
index 5538cd06861159d96801b1f0384242f228465c4c..411ed48d79da8c9ec1439628d8ef2f290a942fb7 100644 (file)
@@ -64,8 +64,8 @@ static int lpfc_sli4_queue_verify(struct lpfc_hba *);
 static int lpfc_create_bootstrap_mbox(struct lpfc_hba *);
 static int lpfc_setup_endian_order(struct lpfc_hba *);
 static void lpfc_destroy_bootstrap_mbox(struct lpfc_hba *);
-static void lpfc_free_sgl_list(struct lpfc_hba *);
-static int lpfc_init_sgl_list(struct lpfc_hba *);
+static void lpfc_free_els_sgl_list(struct lpfc_hba *);
+static void lpfc_init_sgl_list(struct lpfc_hba *);
 static int lpfc_init_active_sgl_array(struct lpfc_hba *);
 static void lpfc_free_active_sgl(struct lpfc_hba *);
 static int lpfc_hba_down_post_s3(struct lpfc_hba *phba);
@@ -2766,36 +2766,6 @@ lpfc_offline(struct lpfc_hba *phba)
        lpfc_destroy_vport_work_array(phba, vports);
 }
 
-/**
- * lpfc_scsi_buf_update - Update the scsi_buffers that are already allocated.
- * @phba: pointer to lpfc hba data structure.
- *
- * This routine goes through all the scsi buffers in the system and updates the
- * Physical XRIs assigned to the SCSI buffer because these may change after any
- * firmware reset
- *
- * Return codes
- *   0 - successful (for now, it always returns 0)
- **/
-int
-lpfc_scsi_buf_update(struct lpfc_hba *phba)
-{
-       struct lpfc_scsi_buf *sb, *sb_next;
-
-       spin_lock_irq(&phba->hbalock);
-       spin_lock(&phba->scsi_buf_list_lock);
-       list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) {
-               sb->cur_iocbq.sli4_xritag =
-                       phba->sli4_hba.xri_ids[sb->cur_iocbq.sli4_lxritag];
-               set_bit(sb->cur_iocbq.sli4_lxritag, phba->sli4_hba.xri_bmask);
-               phba->sli4_hba.max_cfg_param.xri_used++;
-               phba->sli4_hba.xri_count++;
-       }
-       spin_unlock(&phba->scsi_buf_list_lock);
-       spin_unlock_irq(&phba->hbalock);
-       return 0;
-}
-
 /**
  * lpfc_scsi_free - Free all the SCSI buffers and IOCBs from driver lists
  * @phba: pointer to lpfc hba data structure.
@@ -2803,11 +2773,8 @@ lpfc_scsi_buf_update(struct lpfc_hba *phba)
  * This routine is to free all the SCSI buffers and IOCBs from the driver
  * list back to kernel. It is called from lpfc_pci_remove_one to free
  * the internal resources before the device is removed from the system.
- *
- * Return codes
- *   0 - successful (for now, it always returns 0)
  **/
-static int
+static void
 lpfc_scsi_free(struct lpfc_hba *phba)
 {
        struct lpfc_scsi_buf *sb, *sb_next;
@@ -2833,7 +2800,178 @@ lpfc_scsi_free(struct lpfc_hba *phba)
        }
 
        spin_unlock_irq(&phba->hbalock);
+}
+
+/**
+ * lpfc_sli4_xri_sgl_update - update xri-sgl sizing and mapping
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine first calculates the sizes of the current els and allocated
+ * scsi sgl lists, and then goes through all sgls to updates the physical
+ * XRIs assigned due to port function reset. During port initialization, the
+ * current els and allocated scsi sgl lists are 0s.
+ *
+ * Return codes
+ *   0 - successful (for now, it always returns 0)
+ **/
+int
+lpfc_sli4_xri_sgl_update(struct lpfc_hba *phba)
+{
+       struct lpfc_sglq *sglq_entry = NULL, *sglq_entry_next = NULL;
+       struct lpfc_scsi_buf *psb = NULL, *psb_next = NULL;
+       uint16_t i, lxri, xri_cnt, els_xri_cnt, scsi_xri_cnt;
+       LIST_HEAD(els_sgl_list);
+       LIST_HEAD(scsi_sgl_list);
+       int rc;
+
+       /*
+        * update on pci function's els xri-sgl list
+        */
+       els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba);
+       if (els_xri_cnt > phba->sli4_hba.els_xri_cnt) {
+               /* els xri-sgl expanded */
+               xri_cnt = els_xri_cnt - phba->sli4_hba.els_xri_cnt;
+               lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                               "3157 ELS xri-sgl count increased from "
+                               "%d to %d\n", phba->sli4_hba.els_xri_cnt,
+                               els_xri_cnt);
+               /* allocate the additional els sgls */
+               for (i = 0; i < xri_cnt; i++) {
+                       sglq_entry = kzalloc(sizeof(struct lpfc_sglq),
+                                            GFP_KERNEL);
+                       if (sglq_entry == NULL) {
+                               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                                               "2562 Failure to allocate an "
+                                               "ELS sgl entry:%d\n", i);
+                               rc = -ENOMEM;
+                               goto out_free_mem;
+                       }
+                       sglq_entry->buff_type = GEN_BUFF_TYPE;
+                       sglq_entry->virt = lpfc_mbuf_alloc(phba, 0,
+                                                          &sglq_entry->phys);
+                       if (sglq_entry->virt == NULL) {
+                               kfree(sglq_entry);
+                               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                                               "2563 Failure to allocate an "
+                                               "ELS mbuf:%d\n", i);
+                               rc = -ENOMEM;
+                               goto out_free_mem;
+                       }
+                       sglq_entry->sgl = sglq_entry->virt;
+                       memset(sglq_entry->sgl, 0, LPFC_BPL_SIZE);
+                       sglq_entry->state = SGL_FREED;
+                       list_add_tail(&sglq_entry->list, &els_sgl_list);
+               }
+               spin_lock(&phba->hbalock);
+               list_splice_init(&els_sgl_list, &phba->sli4_hba.lpfc_sgl_list);
+               spin_unlock(&phba->hbalock);
+       } else if (els_xri_cnt < phba->sli4_hba.els_xri_cnt) {
+               /* els xri-sgl shrinked */
+               xri_cnt = phba->sli4_hba.els_xri_cnt - els_xri_cnt;
+               lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                               "3158 ELS xri-sgl count decreased from "
+                               "%d to %d\n", phba->sli4_hba.els_xri_cnt,
+                               els_xri_cnt);
+               spin_lock_irq(&phba->hbalock);
+               list_splice_init(&phba->sli4_hba.lpfc_sgl_list, &els_sgl_list);
+               spin_unlock_irq(&phba->hbalock);
+               /* release extra els sgls from list */
+               for (i = 0; i < xri_cnt; i++) {
+                       list_remove_head(&els_sgl_list,
+                                        sglq_entry, struct lpfc_sglq, list);
+                       if (sglq_entry) {
+                               lpfc_mbuf_free(phba, sglq_entry->virt,
+                                              sglq_entry->phys);
+                               kfree(sglq_entry);
+                       }
+               }
+               spin_lock_irq(&phba->hbalock);
+               list_splice_init(&els_sgl_list, &phba->sli4_hba.lpfc_sgl_list);
+               spin_unlock_irq(&phba->hbalock);
+       } else
+               lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                               "3163 ELS xri-sgl count unchanged: %d\n",
+                               els_xri_cnt);
+       phba->sli4_hba.els_xri_cnt = els_xri_cnt;
+
+       /* update xris to els sgls on the list */
+       sglq_entry = NULL;
+       sglq_entry_next = NULL;
+       list_for_each_entry_safe(sglq_entry, sglq_entry_next,
+                                &phba->sli4_hba.lpfc_sgl_list, list) {
+               lxri = lpfc_sli4_next_xritag(phba);
+               if (lxri == NO_XRI) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                                       "2400 Failed to allocate xri for "
+                                       "ELS sgl\n");
+                       rc = -ENOMEM;
+                       goto out_free_mem;
+               }
+               sglq_entry->sli4_lxritag = lxri;
+               sglq_entry->sli4_xritag = phba->sli4_hba.xri_ids[lxri];
+       }
+
+       /*
+        * update on pci function's allocated scsi xri-sgl list
+        */
+       phba->total_scsi_bufs = 0;
+
+       /* maximum number of xris available for scsi buffers */
+       phba->sli4_hba.scsi_xri_max = phba->sli4_hba.max_cfg_param.max_xri -
+                                     els_xri_cnt;
+
+       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                       "2401 Current allocated SCSI xri-sgl count:%d, "
+                       "maximum  SCSI xri count:%d\n",
+                       phba->sli4_hba.scsi_xri_cnt,
+                       phba->sli4_hba.scsi_xri_max);
+
+       spin_lock_irq(&phba->scsi_buf_list_lock);
+       list_splice_init(&phba->lpfc_scsi_buf_list, &scsi_sgl_list);
+       spin_unlock_irq(&phba->scsi_buf_list_lock);
+
+       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 -
+                                       phba->sli4_hba.scsi_xri_max;
+               /* release the extra allocated scsi buffers */
+               for (i = 0; i < scsi_xri_cnt; i++) {
+                       list_remove_head(&scsi_sgl_list, psb,
+                                        struct lpfc_scsi_buf, list);
+                       pci_pool_free(phba->lpfc_scsi_dma_buf_pool, psb->data,
+                                     psb->dma_handle);
+                       kfree(psb);
+               }
+               spin_lock_irq(&phba->scsi_buf_list_lock);
+               phba->sli4_hba.scsi_xri_cnt -= scsi_xri_cnt;
+               spin_unlock_irq(&phba->scsi_buf_list_lock);
+       }
+
+       /* update xris associated to remaining allocated scsi buffers */
+       psb = NULL;
+       psb_next = NULL;
+       list_for_each_entry_safe(psb, psb_next, &scsi_sgl_list, list) {
+               lxri = lpfc_sli4_next_xritag(phba);
+               if (lxri == NO_XRI) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                                       "2560 Failed to allocate xri for "
+                                       "scsi buffer\n");
+                       rc = -ENOMEM;
+                       goto out_free_mem;
+               }
+               psb->cur_iocbq.sli4_lxritag = lxri;
+               psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri];
+       }
+       spin_lock(&phba->scsi_buf_list_lock);
+       list_splice_init(&scsi_sgl_list, &phba->lpfc_scsi_buf_list);
+       spin_unlock(&phba->scsi_buf_list_lock);
+
        return 0;
+
+out_free_mem:
+       lpfc_free_els_sgl_list(phba);
+       lpfc_scsi_free(phba);
+       return rc;
 }
 
 /**
@@ -4636,18 +4774,15 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
        if (rc)
                goto out_free_bsmbx;
 
-       /* Initialize and populate the iocb list per host */
-       rc = lpfc_init_sgl_list(phba);
-       if (rc) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "1400 Failed to initialize sgl list.\n");
-               goto out_destroy_cq_event_pool;
-       }
+       /* Initialize sgl lists per host */
+       lpfc_init_sgl_list(phba);
+
+       /* Allocate and initialize active sgl array */
        rc = lpfc_init_active_sgl_array(phba);
        if (rc) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "1430 Failed to initialize sgl list.\n");
-               goto out_free_sgl_list;
+               goto out_destroy_cq_event_pool;
        }
        rc = lpfc_sli4_init_rpi_hdrs(phba);
        if (rc) {
@@ -4722,8 +4857,6 @@ out_remove_rpi_hdrs:
        lpfc_sli4_remove_rpi_hdrs(phba);
 out_free_active_sgl:
        lpfc_free_active_sgl(phba);
-out_free_sgl_list:
-       lpfc_free_sgl_list(phba);
 out_destroy_cq_event_pool:
        lpfc_sli4_cq_event_pool_destroy(phba);
 out_free_bsmbx:
@@ -4760,10 +4893,7 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
 
        /* Free the ELS sgl list */
        lpfc_free_active_sgl(phba);
-       lpfc_free_sgl_list(phba);
-
-       /* Free the SCSI sgl management array */
-       kfree(phba->sli4_hba.lpfc_scsi_psb_array);
+       lpfc_free_els_sgl_list(phba);
 
        /* Free the completion queue EQ event pool */
        lpfc_sli4_cq_event_release_all(phba);
@@ -4990,29 +5120,42 @@ out_free_iocbq:
 }
 
 /**
- * lpfc_free_sgl_list - Free sgl list.
+ * lpfc_free_sgl_list - Free a given sgl list.
  * @phba: pointer to lpfc hba data structure.
+ * @sglq_list: pointer to the head of sgl list.
  *
- * This routine is invoked to free the driver's sgl list and memory.
+ * This routine is invoked to free a give sgl list and memory.
  **/
-static void
-lpfc_free_sgl_list(struct lpfc_hba *phba)
+void
+lpfc_free_sgl_list(struct lpfc_hba *phba, struct list_head *sglq_list)
 {
        struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
+
+       list_for_each_entry_safe(sglq_entry, sglq_next, sglq_list, list) {
+               list_del(&sglq_entry->list);
+               lpfc_mbuf_free(phba, sglq_entry->virt, sglq_entry->phys);
+               kfree(sglq_entry);
+       }
+}
+
+/**
+ * lpfc_free_els_sgl_list - Free els sgl list.
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to free the driver's els sgl list and memory.
+ **/
+static void
+lpfc_free_els_sgl_list(struct lpfc_hba *phba)
+{
        LIST_HEAD(sglq_list);
 
+       /* Retrieve all els sgls from driver list */
        spin_lock_irq(&phba->hbalock);
        list_splice_init(&phba->sli4_hba.lpfc_sgl_list, &sglq_list);
        spin_unlock_irq(&phba->hbalock);
 
-       list_for_each_entry_safe(sglq_entry, sglq_next,
-                                &sglq_list, list) {
-               list_del(&sglq_entry->list);
-               lpfc_mbuf_free(phba, sglq_entry->virt, sglq_entry->phys);
-               kfree(sglq_entry);
-               phba->sli4_hba.total_sglq_bufs--;
-       }
-       kfree(phba->sli4_hba.lpfc_els_sgl_array);
+       /* Now free the sgl list */
+       lpfc_free_sgl_list(phba, &sglq_list);
 }
 
 /**
@@ -5057,99 +5200,19 @@ lpfc_free_active_sgl(struct lpfc_hba *phba)
  * This routine is invoked to allocate and initizlize the driver's sgl
  * list and set up the sgl xritag tag array accordingly.
  *
- * Return codes
- *     0 - successful
- *     other values - error
  **/
-static int
+static void
 lpfc_init_sgl_list(struct lpfc_hba *phba)
 {
-       struct lpfc_sglq *sglq_entry = NULL;
-       int i;
-       int els_xri_cnt;
-
-       els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba);
-       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
-                               "2400 ELS XRI count %d.\n",
-                               els_xri_cnt);
        /* Initialize and populate the sglq list per host/VF. */
        INIT_LIST_HEAD(&phba->sli4_hba.lpfc_sgl_list);
        INIT_LIST_HEAD(&phba->sli4_hba.lpfc_abts_els_sgl_list);
 
-       /* Sanity check on XRI management */
-       if (phba->sli4_hba.max_cfg_param.max_xri <= els_xri_cnt) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                               "2562 No room left for SCSI XRI allocation: "
-                               "max_xri=%d, els_xri=%d\n",
-                               phba->sli4_hba.max_cfg_param.max_xri,
-                               els_xri_cnt);
-               return -ENOMEM;
-       }
-
-       /* Allocate memory for the ELS XRI management array */
-       phba->sli4_hba.lpfc_els_sgl_array =
-                       kzalloc((sizeof(struct lpfc_sglq *) * els_xri_cnt),
-                       GFP_KERNEL);
+       /* els xri-sgl book keeping */
+       phba->sli4_hba.els_xri_cnt = 0;
 
-       if (!phba->sli4_hba.lpfc_els_sgl_array) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                               "2401 Failed to allocate memory for ELS "
-                               "XRI management array of size %d.\n",
-                               els_xri_cnt);
-               return -ENOMEM;
-       }
-
-       /* Keep the SCSI XRI into the XRI management array */
-       phba->sli4_hba.scsi_xri_max =
-                       phba->sli4_hba.max_cfg_param.max_xri - els_xri_cnt;
+       /* scsi xri-buffer book keeping */
        phba->sli4_hba.scsi_xri_cnt = 0;
-       phba->sli4_hba.lpfc_scsi_psb_array =
-                       kzalloc((sizeof(struct lpfc_scsi_buf *) *
-                       phba->sli4_hba.scsi_xri_max), GFP_KERNEL);
-
-       if (!phba->sli4_hba.lpfc_scsi_psb_array) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                               "2563 Failed to allocate memory for SCSI "
-                               "XRI management array of size %d.\n",
-                               phba->sli4_hba.scsi_xri_max);
-               kfree(phba->sli4_hba.lpfc_els_sgl_array);
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < els_xri_cnt; i++) {
-               sglq_entry = kzalloc(sizeof(struct lpfc_sglq), GFP_KERNEL);
-               if (sglq_entry == NULL) {
-                       printk(KERN_ERR "%s: only allocated %d sgls of "
-                               "expected %d count. Unloading driver.\n",
-                               __func__, i, els_xri_cnt);
-                       goto out_free_mem;
-               }
-
-               sglq_entry->buff_type = GEN_BUFF_TYPE;
-               sglq_entry->virt = lpfc_mbuf_alloc(phba, 0, &sglq_entry->phys);
-               if (sglq_entry->virt == NULL) {
-                       kfree(sglq_entry);
-                       printk(KERN_ERR "%s: failed to allocate mbuf.\n"
-                               "Unloading driver.\n", __func__);
-                       goto out_free_mem;
-               }
-               sglq_entry->sgl = sglq_entry->virt;
-               memset(sglq_entry->sgl, 0, LPFC_BPL_SIZE);
-
-               /* The list order is used by later block SGL registraton */
-               spin_lock_irq(&phba->hbalock);
-               sglq_entry->state = SGL_FREED;
-               list_add_tail(&sglq_entry->list, &phba->sli4_hba.lpfc_sgl_list);
-               phba->sli4_hba.lpfc_els_sgl_array[i] = sglq_entry;
-               phba->sli4_hba.total_sglq_bufs++;
-               spin_unlock_irq(&phba->hbalock);
-       }
-       return 0;
-
-out_free_mem:
-       kfree(phba->sli4_hba.lpfc_scsi_psb_array);
-       lpfc_free_sgl_list(phba);
-       return -ENOMEM;
 }
 
 /**
@@ -7320,9 +7383,11 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
                                        phba->sli4_hba.u.if_type2.ERR2regaddr);
                                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                        "2890 Port error detected during port "
-                                       "reset(%d): port status reg 0x%x, "
+                                       "reset(%d): wait_tmo:%d ms, "
+                                       "port status reg 0x%x, "
                                        "error 1=0x%x, error 2=0x%x\n",
-                                       num_resets, reg_data.word0,
+                                       num_resets, rdy_chk*10,
+                                       reg_data.word0,
                                        phba->work_status[0],
                                        phba->work_status[1]);
                                rc = -ENODEV;
@@ -9118,8 +9183,12 @@ lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *phba)
                        return 50;
                else if (max_xri <= 1024)
                        return 100;
-               else
+               else if (max_xri <= 1536)
                        return 150;
+               else if (max_xri <= 2048)
+                       return 200;
+               else
+                       return 250;
        } else
                return 0;
 }
index 88f3a83dbd2eaf45a36d08a0c92b8fe186158ea3..bf0048a7a3026018a45e7b9ff46043580072f270 100644 (file)
@@ -718,72 +718,162 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
 }
 
 /**
- * lpfc_sli4_repost_scsi_sgl_list - Repsot the Scsi buffers sgl pages as block
+ * lpfc_sli4_post_scsi_sgl_list - Psot blocks of scsi buffer sgls from a list
  * @phba: pointer to lpfc hba data structure.
+ * @post_sblist: pointer to the scsi buffer list.
  *
- * This routine walks the list of scsi buffers that have been allocated and
- * repost them to the HBA by using SGL block post. This is needed after a
- * pci_function_reset/warm_start or start. The lpfc_hba_down_post_s4 routine
- * is responsible for moving all scsi buffers on the lpfc_abts_scsi_sgl_list
- * to the lpfc_scsi_buf_list. If the repost fails, reject all scsi buffers.
+ * This routine walks a list of scsi buffers that was passed in. It attempts
+ * to construct blocks of scsi buffer sgls which contains contiguous xris and
+ * uses the non-embedded SGL block post mailbox commands to post to the port.
+ * For single SCSI buffer sgl with non-contiguous xri, if any, it shall use
+ * embedded SGL post mailbox command for posting. The @post_sblist passed in
+ * must be local list, thus no lock is needed when manipulate the list.
  *
- * Returns: 0 = success, non-zero failure.
+ * Returns: 0 = failure, non-zero number of successfully posted buffers.
  **/
 int
-lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
+lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba,
+                            struct list_head *post_sblist, int sb_count)
 {
-       struct lpfc_scsi_buf *psb;
-       int index, status, bcnt = 0, rcnt = 0, rc = 0;
-       LIST_HEAD(sblist);
-
-       for (index = 0; index < phba->sli4_hba.scsi_xri_cnt; index++) {
-               psb = phba->sli4_hba.lpfc_scsi_psb_array[index];
-               if (psb) {
-                       /* Remove from SCSI buffer list */
-                       list_del(&psb->list);
-                       /* Add it to a local SCSI buffer list */
-                       list_add_tail(&psb->list, &sblist);
-                       if (++rcnt == LPFC_NEMBED_MBOX_SGL_CNT) {
-                               bcnt = rcnt;
-                               rcnt = 0;
+       struct lpfc_scsi_buf *psb, *psb_next;
+       int status;
+       int post_cnt = 0, block_cnt = 0, num_posting = 0, num_posted = 0;
+       dma_addr_t pdma_phys_bpl1;
+       int last_xritag = NO_XRI;
+       LIST_HEAD(prep_sblist);
+       LIST_HEAD(blck_sblist);
+       LIST_HEAD(scsi_sblist);
+
+       /* sanity check */
+       if (sb_count <= 0)
+               return -EINVAL;
+
+       list_for_each_entry_safe(psb, psb_next, post_sblist, list) {
+               list_del_init(&psb->list);
+               block_cnt++;
+               if ((last_xritag != NO_XRI) &&
+                   (psb->cur_iocbq.sli4_xritag != last_xritag + 1)) {
+                       /* a hole in xri block, form a sgl posting block */
+                       list_splice_init(&prep_sblist, &blck_sblist);
+                       post_cnt = block_cnt - 1;
+                       /* prepare list for next posting block */
+                       list_add_tail(&psb->list, &prep_sblist);
+                       block_cnt = 1;
+               } else {
+                       /* prepare list for next posting block */
+                       list_add_tail(&psb->list, &prep_sblist);
+                       /* enough sgls for non-embed sgl mbox command */
+                       if (block_cnt == LPFC_NEMBED_MBOX_SGL_CNT) {
+                               list_splice_init(&prep_sblist, &blck_sblist);
+                               post_cnt = block_cnt;
+                               block_cnt = 0;
                        }
-               } else
-                       /* A hole present in the XRI array, need to skip */
-                       bcnt = rcnt;
+               }
+               num_posting++;
+               last_xritag = psb->cur_iocbq.sli4_xritag;
 
-               if (index == phba->sli4_hba.scsi_xri_cnt - 1)
-                       /* End of XRI array for SCSI buffer, complete */
-                       bcnt = rcnt;
+               /* end of repost sgl list condition for SCSI buffers */
+               if (num_posting == sb_count) {
+                       if (post_cnt == 0) {
+                               /* last sgl posting block */
+                               list_splice_init(&prep_sblist, &blck_sblist);
+                               post_cnt = block_cnt;
+                       } else if (block_cnt == 1) {
+                               /* last single sgl with non-contiguous xri */
+                               if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
+                                       pdma_phys_bpl1 = psb->dma_phys_bpl +
+                                                               SGL_PAGE_SIZE;
+                               else
+                                       pdma_phys_bpl1 = 0;
+                               status = lpfc_sli4_post_sgl(phba,
+                                               psb->dma_phys_bpl,
+                                               pdma_phys_bpl1,
+                                               psb->cur_iocbq.sli4_xritag);
+                               if (status) {
+                                       /* failure, put on abort scsi list */
+                                       psb->exch_busy = 1;
+                               } else {
+                                       /* success, put on SCSI buffer list */
+                                       psb->exch_busy = 0;
+                                       psb->status = IOSTAT_SUCCESS;
+                                       num_posted++;
+                               }
+                               /* success, put on SCSI buffer sgl list */
+                               list_add_tail(&psb->list, &scsi_sblist);
+                       }
+               }
 
-               /* Continue until collect up to a nembed page worth of sgls */
-               if (bcnt == 0)
+               /* continue until a nembed page worth of sgls */
+               if (post_cnt == 0)
                        continue;
-               /* Now, post the SCSI buffer list sgls as a block */
-               if (!phba->sli4_hba.extents_in_use)
-                       status = lpfc_sli4_post_scsi_sgl_block(phba,
-                                                       &sblist,
-                                                       bcnt);
-               else
-                       status = lpfc_sli4_post_scsi_sgl_blk_ext(phba,
-                                                       &sblist,
-                                                       bcnt);
-               /* Reset SCSI buffer count for next round of posting */
-               bcnt = 0;
-               while (!list_empty(&sblist)) {
-                       list_remove_head(&sblist, psb, struct lpfc_scsi_buf,
-                                        list);
+
+               /* post block of SCSI buffer list sgls */
+               status = lpfc_sli4_post_scsi_sgl_block(phba, &blck_sblist,
+                                                      post_cnt);
+
+               /* don't reset xirtag due to hole in xri block */
+               if (block_cnt == 0)
+                       last_xritag = NO_XRI;
+
+               /* reset SCSI buffer post count for next round of posting */
+               post_cnt = 0;
+
+               /* put posted SCSI buffer-sgl posted on SCSI buffer sgl list */
+               while (!list_empty(&blck_sblist)) {
+                       list_remove_head(&blck_sblist, psb,
+                                        struct lpfc_scsi_buf, list);
                        if (status) {
-                               /* Put this back on the abort scsi list */
+                               /* failure, put on abort scsi list */
                                psb->exch_busy = 1;
-                               rc++;
                        } else {
+                               /* success, put on SCSI buffer list */
                                psb->exch_busy = 0;
                                psb->status = IOSTAT_SUCCESS;
+                               num_posted++;
                        }
-                       /* Put it back into the SCSI buffer list */
-                       lpfc_release_scsi_buf_s4(phba, psb);
+                       list_add_tail(&psb->list, &scsi_sblist);
                }
        }
+       /* Push SCSI buffers with sgl posted to the availble list */
+       while (!list_empty(&scsi_sblist)) {
+               list_remove_head(&scsi_sblist, psb,
+                                struct lpfc_scsi_buf, list);
+               lpfc_release_scsi_buf_s4(phba, psb);
+       }
+       return num_posted;
+}
+
+/**
+ * lpfc_sli4_repost_scsi_sgl_list - Repsot all the allocated scsi buffer sgls
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine walks the list of scsi buffers that have been allocated and
+ * repost them to the port by using SGL block post. This is needed after a
+ * pci_function_reset/warm_start or start. The lpfc_hba_down_post_s4 routine
+ * is responsible for moving all scsi buffers on the lpfc_abts_scsi_sgl_list
+ * to the lpfc_scsi_buf_list. If the repost fails, reject all scsi buffers.
+ *
+ * Returns: 0 = success, non-zero failure.
+ **/
+int
+lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
+{
+       LIST_HEAD(post_sblist);
+       int num_posted, rc = 0;
+
+       /* get all SCSI buffers need to repost to a local list */
+       spin_lock(&phba->scsi_buf_list_lock);
+       list_splice_init(&phba->lpfc_scsi_buf_list, &post_sblist);
+       spin_unlock(&phba->scsi_buf_list_lock);
+
+       /* post the list of scsi buffer sgls to port if available */
+       if (!list_empty(&post_sblist)) {
+               num_posted = lpfc_sli4_post_scsi_sgl_list(phba, &post_sblist,
+                                               phba->sli4_hba.scsi_xri_cnt);
+               /* failed to post any scsi buffer, return error */
+               if (num_posted == 0)
+                       rc = -EIO;
+       }
        return rc;
 }
 
@@ -792,12 +882,13 @@ lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
  * @vport: The virtual port for which this call being executed.
  * @num_to_allocate: The requested number of buffers to allocate.
  *
- * This routine allocates a scsi buffer for device with SLI-4 interface spec,
+ * This routine allocates scsi buffers for device with SLI-4 interface spec,
  * the scsi buffer contains all the necessary information needed to initiate
- * a SCSI I/O.
+ * a SCSI I/O. After allocating up to @num_to_allocate SCSI buffers and put
+ * them on a list, it post them to the port by using SGL block post.
  *
  * Return codes:
- *   int - number of scsi buffers that were allocated.
+ *   int - number of scsi buffers that were allocated and posted.
  *   0 = failure, less than num_to_alloc is a partial failure.
  **/
 static int
@@ -810,22 +901,21 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
        dma_addr_t pdma_phys_fcp_cmd;
        dma_addr_t pdma_phys_fcp_rsp;
        dma_addr_t pdma_phys_bpl, pdma_phys_bpl1;
-       uint16_t iotag, last_xritag = NO_XRI, lxri = 0;
-       int status = 0, index;
-       int bcnt;
-       int non_sequential_xri = 0;
-       LIST_HEAD(sblist);
+       uint16_t iotag, lxri = 0;
+       int bcnt, num_posted;
+       LIST_HEAD(prep_sblist);
+       LIST_HEAD(post_sblist);
+       LIST_HEAD(scsi_sblist);
 
        for (bcnt = 0; bcnt < num_to_alloc; bcnt++) {
                psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL);
                if (!psb)
                        break;
-
                /*
-                * Get memory from the pci pool to map the virt space to pci bus
-                * space for an I/O.  The DMA buffer includes space for the
-                * struct fcp_cmnd, struct fcp_rsp and the number of bde's
-                * necessary to support the sg_tablesize.
+                * Get memory from the pci pool to map the virt space to
+                * pci bus space for an I/O. The DMA buffer includes space
+                * for the struct fcp_cmnd, struct fcp_rsp and the number
+                * of bde's necessary to support the sg_tablesize.
                 */
                psb->data = pci_pool_alloc(phba->lpfc_scsi_dma_buf_pool,
                                                GFP_KERNEL, &psb->dma_handle);
@@ -833,8 +923,6 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
                        kfree(psb);
                        break;
                }
-
-               /* Initialize virtual ptrs to dma_buf region. */
                memset(psb->data, 0, phba->cfg_sg_dma_buf_size);
 
                /* Allocate iotag for psb->cur_iocbq. */
@@ -855,16 +943,7 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
                }
                psb->cur_iocbq.sli4_lxritag = lxri;
                psb->cur_iocbq.sli4_xritag = phba->sli4_hba.xri_ids[lxri];
-               if (last_xritag != NO_XRI
-                       && psb->cur_iocbq.sli4_xritag != (last_xritag+1)) {
-                       non_sequential_xri = 1;
-               } else
-                       list_add_tail(&psb->list, &sblist);
-               last_xritag = psb->cur_iocbq.sli4_xritag;
-
-               index = phba->sli4_hba.scsi_xri_cnt++;
                psb->cur_iocbq.iocb_flag |= LPFC_IO_FCP;
-
                psb->fcp_bpl = psb->data;
                psb->fcp_cmnd = (psb->data + phba->cfg_sg_dma_buf_size)
                        - (sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
@@ -880,9 +959,9 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
                pdma_phys_fcp_rsp = pdma_phys_fcp_cmd + sizeof(struct fcp_cmnd);
 
                /*
-                * The first two bdes are the FCP_CMD and FCP_RSP.  The balance
-                * are sg list bdes.  Initialize the first two and leave the
-                * rest for queuecommand.
+                * The first two bdes are the FCP_CMD and FCP_RSP.
+                * The balance are sg list bdes. Initialize the
+                * first two and leave the rest for queuecommand.
                 */
                sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_cmd));
                sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_cmd));
@@ -917,62 +996,31 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc)
                iocb->ulpBdeCount = 1;
                iocb->ulpLe = 1;
                iocb->ulpClass = CLASS3;
-               psb->cur_iocbq.context1  = psb;
+               psb->cur_iocbq.context1 = psb;
                if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
                        pdma_phys_bpl1 = pdma_phys_bpl + SGL_PAGE_SIZE;
                else
                        pdma_phys_bpl1 = 0;
                psb->dma_phys_bpl = pdma_phys_bpl;
-               phba->sli4_hba.lpfc_scsi_psb_array[index] = psb;
-               if (non_sequential_xri) {
-                       status = lpfc_sli4_post_sgl(phba, pdma_phys_bpl,
-                                               pdma_phys_bpl1,
-                                               psb->cur_iocbq.sli4_xritag);
-                       if (status) {
-                               /* Put this back on the abort scsi list */
-                               psb->exch_busy = 1;
-                       } else {
-                               psb->exch_busy = 0;
-                               psb->status = IOSTAT_SUCCESS;
-                       }
-                       /* Put it back into the SCSI buffer list */
-                       lpfc_release_scsi_buf_s4(phba, psb);
-                       break;
-               }
-       }
-       if (bcnt) {
-               if (!phba->sli4_hba.extents_in_use)
-                       status = lpfc_sli4_post_scsi_sgl_block(phba,
-                                                               &sblist,
-                                                               bcnt);
-               else
-                       status = lpfc_sli4_post_scsi_sgl_blk_ext(phba,
-                                                               &sblist,
-                                                               bcnt);
-
-               if (status) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
-                                       "3021 SCSI SGL post error %d\n",
-                                       status);
-                       bcnt = 0;
-               }
-               /* Reset SCSI buffer count for next round of posting */
-               while (!list_empty(&sblist)) {
-                       list_remove_head(&sblist, psb, struct lpfc_scsi_buf,
-                                list);
-                       if (status) {
-                               /* Put this back on the abort scsi list */
-                               psb->exch_busy = 1;
-                       } else {
-                               psb->exch_busy = 0;
-                               psb->status = IOSTAT_SUCCESS;
-                       }
-                       /* Put it back into the SCSI buffer list */
-                       lpfc_release_scsi_buf_s4(phba, psb);
-               }
+
+               /* add the scsi buffer to a post list */
+               list_add_tail(&psb->list, &post_sblist);
+               spin_lock_irq(&phba->scsi_buf_list_lock);
+               phba->sli4_hba.scsi_xri_cnt++;
+               spin_unlock_irq(&phba->scsi_buf_list_lock);
        }
+       lpfc_printf_log(phba, KERN_INFO, LOG_BG,
+                       "3021 Allocate %d out of %d requested new SCSI "
+                       "buffers\n", bcnt, num_to_alloc);
+
+       /* post the list of scsi buffer sgls to port if available */
+       if (!list_empty(&post_sblist))
+               num_posted = lpfc_sli4_post_scsi_sgl_list(phba,
+                                                         &post_sblist, bcnt);
+       else
+               num_posted = 0;
 
-       return bcnt + non_sequential_xri;
+       return num_posted;
 }
 
 /**
index dbaf5b963bff2f0cd07c028ddedd5b1ff0bc0bcc..b887c9c5372a9fc06e0a787d762b3f3e54665e11 100644 (file)
@@ -67,6 +67,8 @@ static void lpfc_sli4_send_seq_to_ulp(struct lpfc_vport *,
                                      struct hbq_dmabuf *);
 static int lpfc_sli4_fp_handle_wcqe(struct lpfc_hba *, struct lpfc_queue *,
                                    struct lpfc_cqe *);
+static int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *, struct list_head *,
+                                      int);
 
 static IOCB_t *
 lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq)
@@ -4967,7 +4969,12 @@ lpfc_sli4_get_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type,
                              &rsrc_info->u.rsp);
        *extnt_size = bf_get(lpfc_mbx_get_rsrc_extent_info_size,
                             &rsrc_info->u.rsp);
- err_exit:
+
+       lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+                       "3162 Retrieved extents type-%d from port: count:%d, "
+                       "size:%d\n", type, *extnt_count, *extnt_size);
+
+err_exit:
        mempool_free(mbox, phba->mbox_mem_pool);
        return rc;
 }
@@ -5051,7 +5058,7 @@ lpfc_sli4_chk_avail_extnt_rsrc(struct lpfc_hba *phba, uint16_t type)
  *   0: if successful
  **/
 static int
-lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
+lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t extnt_cnt,
                          uint16_t type, bool *emb, LPFC_MBOXQ_t *mbox)
 {
        int rc = 0;
@@ -5060,7 +5067,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
        uint32_t alloc_len, mbox_tmo;
 
        /* Calculate the total requested length of the dma memory */
-       req_len = *extnt_cnt * sizeof(uint16_t);
+       req_len = extnt_cnt * sizeof(uint16_t);
 
        /*
         * Calculate the size of an embedded mailbox.  The uint32_t
@@ -5075,7 +5082,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
         */
        *emb = LPFC_SLI4_MBX_EMBED;
        if (req_len > emb_len) {
-               req_len = *extnt_cnt * sizeof(uint16_t) +
+               req_len = extnt_cnt * sizeof(uint16_t) +
                        sizeof(union lpfc_sli4_cfg_shdr) +
                        sizeof(uint32_t);
                *emb = LPFC_SLI4_MBX_NEMBED;
@@ -5091,7 +5098,7 @@ lpfc_sli4_cfg_post_extnts(struct lpfc_hba *phba, uint16_t *extnt_cnt,
                        "size (x%x)\n", alloc_len, req_len);
                return -ENOMEM;
        }
-       rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, *extnt_cnt, type, *emb);
+       rc = lpfc_sli4_mbox_rsrc_extent(phba, mbox, extnt_cnt, type, *emb);
        if (unlikely(rc))
                return -EIO;
 
@@ -5149,17 +5156,15 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type)
                return -ENOMEM;
        }
 
-       lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_INIT,
-                       "2903 Available Resource Extents "
-                       "for resource type 0x%x: Count: 0x%x, "
-                       "Size 0x%x\n", type, rsrc_cnt,
-                       rsrc_size);
+       lpfc_printf_log(phba, KERN_INFO, LOG_MBOX | LOG_INIT | LOG_SLI,
+                       "2903 Post resource extents type-0x%x: "
+                       "count:%d, size %d\n", type, rsrc_cnt, rsrc_size);
 
        mbox = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (!mbox)
                return -ENOMEM;
 
-       rc = lpfc_sli4_cfg_post_extnts(phba, &rsrc_cnt, type, &emb, mbox);
+       rc = lpfc_sli4_cfg_post_extnts(phba, rsrc_cnt, type, &emb, mbox);
        if (unlikely(rc)) {
                rc = -EIO;
                goto err_exit;
@@ -5250,6 +5255,7 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type)
                        rc = -ENOMEM;
                        goto err_exit;
                }
+               phba->sli4_hba.max_cfg_param.xri_used = 0;
                phba->sli4_hba.xri_ids = kzalloc(rsrc_id_cnt *
                                                 sizeof(uint16_t),
                                                 GFP_KERNEL);
@@ -5420,7 +5426,6 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type)
        case LPFC_RSC_TYPE_FCOE_XRI:
                kfree(phba->sli4_hba.xri_bmask);
                kfree(phba->sli4_hba.xri_ids);
-               bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0);
                list_for_each_entry_safe(rsrc_blk, rsrc_blk_next,
                                    &phba->sli4_hba.lpfc_xri_blk_list, list) {
                        list_del_init(&rsrc_blk->list);
@@ -5612,7 +5617,6 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
                        goto free_vpi_ids;
                }
                phba->sli4_hba.max_cfg_param.xri_used = 0;
-               phba->sli4_hba.xri_count = 0;
                phba->sli4_hba.xri_ids = kzalloc(count *
                                                 sizeof(uint16_t),
                                                 GFP_KERNEL);
@@ -5694,7 +5698,6 @@ lpfc_sli4_dealloc_resource_identifiers(struct lpfc_hba *phba)
                bf_set(lpfc_vpi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0);
                kfree(phba->sli4_hba.xri_bmask);
                kfree(phba->sli4_hba.xri_ids);
-               bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0);
                kfree(phba->sli4_hba.vfi_bmask);
                kfree(phba->sli4_hba.vfi_ids);
                bf_set(lpfc_vfi_rsrc_rdy, &phba->sli4_hba.sli4_flags, 0);
@@ -5852,6 +5855,149 @@ lpfc_sli4_get_allocated_extnts(struct lpfc_hba *phba, uint16_t type,
        return rc;
 }
 
+/**
+ * lpfc_sli4_repost_els_sgl_list - Repsot the els buffers sgl pages as block
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine walks the list of els buffers that have been allocated and
+ * repost them to the port by using SGL block post. This is needed after a
+ * pci_function_reset/warm_start or start. It attempts to construct blocks
+ * of els buffer sgls which contains contiguous xris and uses the non-embedded
+ * SGL block post mailbox commands to post them to the port. For single els
+ * buffer sgl with non-contiguous xri, if any, it shall use embedded SGL post
+ * mailbox command for posting.
+ *
+ * Returns: 0 = success, non-zero failure.
+ **/
+static int
+lpfc_sli4_repost_els_sgl_list(struct lpfc_hba *phba)
+{
+       struct lpfc_sglq *sglq_entry = NULL;
+       struct lpfc_sglq *sglq_entry_next = NULL;
+       struct lpfc_sglq *sglq_entry_first = NULL;
+       int status, post_cnt = 0, num_posted = 0, block_cnt = 0;
+       int last_xritag = NO_XRI;
+       LIST_HEAD(prep_sgl_list);
+       LIST_HEAD(blck_sgl_list);
+       LIST_HEAD(allc_sgl_list);
+       LIST_HEAD(post_sgl_list);
+       LIST_HEAD(free_sgl_list);
+
+       spin_lock(&phba->hbalock);
+       list_splice_init(&phba->sli4_hba.lpfc_sgl_list, &allc_sgl_list);
+       spin_unlock(&phba->hbalock);
+
+       list_for_each_entry_safe(sglq_entry, sglq_entry_next,
+                                &allc_sgl_list, list) {
+               list_del_init(&sglq_entry->list);
+               block_cnt++;
+               if ((last_xritag != NO_XRI) &&
+                   (sglq_entry->sli4_xritag != last_xritag + 1)) {
+                       /* a hole in xri block, form a sgl posting block */
+                       list_splice_init(&prep_sgl_list, &blck_sgl_list);
+                       post_cnt = block_cnt - 1;
+                       /* prepare list for next posting block */
+                       list_add_tail(&sglq_entry->list, &prep_sgl_list);
+                       block_cnt = 1;
+               } else {
+                       /* prepare list for next posting block */
+                       list_add_tail(&sglq_entry->list, &prep_sgl_list);
+                       /* enough sgls for non-embed sgl mbox command */
+                       if (block_cnt == LPFC_NEMBED_MBOX_SGL_CNT) {
+                               list_splice_init(&prep_sgl_list,
+                                                &blck_sgl_list);
+                               post_cnt = block_cnt;
+                               block_cnt = 0;
+                       }
+               }
+               num_posted++;
+
+               /* keep track of last sgl's xritag */
+               last_xritag = sglq_entry->sli4_xritag;
+
+               /* end of repost sgl list condition for els buffers */
+               if (num_posted == phba->sli4_hba.els_xri_cnt) {
+                       if (post_cnt == 0) {
+                               list_splice_init(&prep_sgl_list,
+                                                &blck_sgl_list);
+                               post_cnt = block_cnt;
+                       } else if (block_cnt == 1) {
+                               status = lpfc_sli4_post_sgl(phba,
+                                               sglq_entry->phys, 0,
+                                               sglq_entry->sli4_xritag);
+                               if (!status) {
+                                       /* successful, put sgl to posted list */
+                                       list_add_tail(&sglq_entry->list,
+                                                     &post_sgl_list);
+                               } else {
+                                       /* Failure, put sgl to free list */
+                                       lpfc_printf_log(phba, KERN_WARNING,
+                                               LOG_SLI,
+                                               "3159 Failed to post els "
+                                               "sgl, xritag:x%x\n",
+                                               sglq_entry->sli4_xritag);
+                                       list_add_tail(&sglq_entry->list,
+                                                     &free_sgl_list);
+                                       spin_lock_irq(&phba->hbalock);
+                                       phba->sli4_hba.els_xri_cnt--;
+                                       spin_unlock_irq(&phba->hbalock);
+                               }
+                       }
+               }
+
+               /* continue until a nembed page worth of sgls */
+               if (post_cnt == 0)
+                       continue;
+
+               /* post the els buffer list sgls as a block */
+               status = lpfc_sli4_post_els_sgl_list(phba, &blck_sgl_list,
+                                                    post_cnt);
+
+               if (!status) {
+                       /* success, put sgl list to posted sgl list */
+                       list_splice_init(&blck_sgl_list, &post_sgl_list);
+               } else {
+                       /* Failure, put sgl list to free sgl list */
+                       sglq_entry_first = list_first_entry(&blck_sgl_list,
+                                                           struct lpfc_sglq,
+                                                           list);
+                       lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
+                                       "3160 Failed to post els sgl-list, "
+                                       "xritag:x%x-x%x\n",
+                                       sglq_entry_first->sli4_xritag,
+                                       (sglq_entry_first->sli4_xritag +
+                                        post_cnt - 1));
+                       list_splice_init(&blck_sgl_list, &free_sgl_list);
+                       spin_lock_irq(&phba->hbalock);
+                       phba->sli4_hba.els_xri_cnt -= post_cnt;
+                       spin_unlock_irq(&phba->hbalock);
+               }
+
+               /* don't reset xirtag due to hole in xri block */
+               if (block_cnt == 0)
+                       last_xritag = NO_XRI;
+
+               /* reset els sgl post count for next round of posting */
+               post_cnt = 0;
+       }
+
+       /* free the els sgls failed to post */
+       lpfc_free_sgl_list(phba, &free_sgl_list);
+
+       /* push els sgls posted to the availble list */
+       if (!list_empty(&post_sgl_list)) {
+               spin_lock(&phba->hbalock);
+               list_splice_init(&post_sgl_list,
+                                &phba->sli4_hba.lpfc_sgl_list);
+               spin_unlock(&phba->hbalock);
+       } else {
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                               "3161 Failure to post els sgl to port.\n");
+               return -EIO;
+       }
+       return 0;
+}
+
 /**
  * lpfc_sli4_hba_setup - SLI4 device intialization PCI function
  * @phba: Pointer to HBA context object.
@@ -6063,8 +6209,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
                                "rc = x%x\n", rc);
                goto out_free_mbox;
        }
-       /* update physical xri mappings in the scsi buffers */
-       lpfc_scsi_buf_update(phba);
 
        /* Read the port's service parameters. */
        rc = lpfc_read_sparam(phba, mboxq, vport->vpi);
@@ -6105,28 +6249,26 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
        fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn);
        fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn);
 
-       /* Register SGL pool to the device using non-embedded mailbox command */
-       if (!phba->sli4_hba.extents_in_use) {
-               rc = lpfc_sli4_post_els_sgl_list(phba);
-               if (unlikely(rc)) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
-                                       "0582 Error %d during els sgl post "
-                                       "operation\n", rc);
-                       rc = -ENODEV;
-                       goto out_free_mbox;
-               }
-       } else {
-               rc = lpfc_sli4_post_els_sgl_list_ext(phba);
-               if (unlikely(rc)) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
-                                       "2560 Error %d during els sgl post "
-                                       "operation\n", rc);
-                       rc = -ENODEV;
-                       goto out_free_mbox;
-               }
+       /* update host els and scsi xri-sgl sizes and mappings */
+       rc = lpfc_sli4_xri_sgl_update(phba);
+       if (unlikely(rc)) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+                               "1400 Failed to update xri-sgl size and "
+                               "mapping: %d\n", rc);
+               goto out_free_mbox;
        }
 
-       /* Register SCSI SGL pool to the device */
+       /* register the els sgl pool to the port */
+       rc = lpfc_sli4_repost_els_sgl_list(phba);
+       if (unlikely(rc)) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+                               "0582 Error %d during els sgl post "
+                               "operation\n", rc);
+               rc = -ENODEV;
+               goto out_free_mbox;
+       }
+
+       /* register the allocated scsi sgl pool to the port */
        rc = lpfc_sli4_repost_scsi_sgl_list(phba);
        if (unlikely(rc)) {
                lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
@@ -13080,9 +13222,7 @@ lpfc_sli4_alloc_xri(struct lpfc_hba *phba)
        } else {
                set_bit(xri, phba->sli4_hba.xri_bmask);
                phba->sli4_hba.max_cfg_param.xri_used++;
-               phba->sli4_hba.xri_count++;
        }
-
        spin_unlock_irq(&phba->hbalock);
        return xri;
 }
@@ -13098,7 +13238,6 @@ void
 __lpfc_sli4_free_xri(struct lpfc_hba *phba, int xri)
 {
        if (test_and_clear_bit(xri, phba->sli4_hba.xri_bmask)) {
-               phba->sli4_hba.xri_count--;
                phba->sli4_hba.max_cfg_param.xri_used--;
        }
 }
@@ -13149,31 +13288,32 @@ lpfc_sli4_next_xritag(struct lpfc_hba *phba)
 /**
  * lpfc_sli4_post_els_sgl_list - post a block of ELS sgls to the port.
  * @phba: pointer to lpfc hba data structure.
+ * @post_sgl_list: pointer to els sgl entry list.
+ * @count: number of els sgl entries on the list.
  *
  * This routine is invoked to post a block of driver's sgl pages to the
  * HBA using non-embedded mailbox command. No Lock is held. This routine
  * is only called when the driver is loading and after all IO has been
  * stopped.
  **/
-int
-lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba)
+static int
+lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba,
+                           struct list_head *post_sgl_list,
+                           int post_cnt)
 {
-       struct lpfc_sglq *sglq_entry;
+       struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
        struct lpfc_mbx_post_uembed_sgl_page1 *sgl;
        struct sgl_page_pairs *sgl_pg_pairs;
        void *viraddr;
        LPFC_MBOXQ_t *mbox;
        uint32_t reqlen, alloclen, pg_pairs;
        uint32_t mbox_tmo;
-       uint16_t xritag_start = 0, lxri = 0;
-       int els_xri_cnt, rc = 0;
+       uint16_t xritag_start = 0;
+       int rc = 0;
        uint32_t shdr_status, shdr_add_status;
        union lpfc_sli4_cfg_shdr *shdr;
 
-       /* The number of sgls to be posted */
-       els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba);
-
-       reqlen = els_xri_cnt * sizeof(struct sgl_page_pairs) +
+       reqlen = phba->sli4_hba.els_xri_cnt * sizeof(struct sgl_page_pairs) +
                 sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t);
        if (reqlen > SLI4_PAGE_SIZE) {
                lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
@@ -13203,25 +13343,8 @@ lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba)
        sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr;
        sgl_pg_pairs = &sgl->sgl_pg_pairs;
 
-       for (pg_pairs = 0; pg_pairs < els_xri_cnt; pg_pairs++) {
-               sglq_entry = phba->sli4_hba.lpfc_els_sgl_array[pg_pairs];
-
-               /*
-                * Assign the sglq a physical xri only if the driver has not
-                * initialized those resources.  A port reset only needs
-                * the sglq's posted.
-                */
-               if (bf_get(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags) !=
-                   LPFC_XRI_RSRC_RDY) {
-                       lxri = lpfc_sli4_next_xritag(phba);
-                       if (lxri == NO_XRI) {
-                               lpfc_sli4_mbox_cmd_free(phba, mbox);
-                               return -ENOMEM;
-                       }
-                       sglq_entry->sli4_lxritag = lxri;
-                       sglq_entry->sli4_xritag = phba->sli4_hba.xri_ids[lxri];
-               }
-
+       pg_pairs = 0;
+       list_for_each_entry_safe(sglq_entry, sglq_next, post_sgl_list, list) {
                /* Set up the sge entry */
                sgl_pg_pairs->sgl_pg0_addr_lo =
                                cpu_to_le32(putPaddrLow(sglq_entry->phys));
@@ -13236,11 +13359,12 @@ lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba)
                if (pg_pairs == 0)
                        xritag_start = sglq_entry->sli4_xritag;
                sgl_pg_pairs++;
+               pg_pairs++;
        }
 
        /* Complete initialization and perform endian conversion. */
        bf_set(lpfc_post_sgl_pages_xri, sgl, xritag_start);
-       bf_set(lpfc_post_sgl_pages_xricnt, sgl, els_xri_cnt);
+       bf_set(lpfc_post_sgl_pages_xricnt, sgl, phba->sli4_hba.els_xri_cnt);
        sgl->word0 = cpu_to_le32(sgl->word0);
        if (!phba->sli4_hba.intr_enable)
                rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
@@ -13260,183 +13384,6 @@ lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba)
                                shdr_status, shdr_add_status, rc);
                rc = -ENXIO;
        }
-
-       if (rc == 0)
-               bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags,
-                      LPFC_XRI_RSRC_RDY);
-       return rc;
-}
-
-/**
- * lpfc_sli4_post_els_sgl_list_ext - post a block of ELS sgls to the port.
- * @phba: pointer to lpfc hba data structure.
- *
- * This routine is invoked to post a block of driver's sgl pages to the
- * HBA using non-embedded mailbox command. No Lock is held. This routine
- * is only called when the driver is loading and after all IO has been
- * stopped.
- **/
-int
-lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba)
-{
-       struct lpfc_sglq *sglq_entry;
-       struct lpfc_mbx_post_uembed_sgl_page1 *sgl;
-       struct sgl_page_pairs *sgl_pg_pairs;
-       void *viraddr;
-       LPFC_MBOXQ_t *mbox;
-       uint32_t reqlen, alloclen, index;
-       uint32_t mbox_tmo;
-       uint16_t rsrc_start, rsrc_size, els_xri_cnt, post_els_xri_cnt;
-       uint16_t xritag_start = 0, lxri = 0;
-       struct lpfc_rsrc_blks *rsrc_blk;
-       int cnt, ttl_cnt, rc = 0;
-       int loop_cnt;
-       uint32_t shdr_status, shdr_add_status;
-       union lpfc_sli4_cfg_shdr *shdr;
-
-       /* The number of sgls to be posted */
-       els_xri_cnt = lpfc_sli4_get_els_iocb_cnt(phba);
-
-       reqlen = els_xri_cnt * sizeof(struct sgl_page_pairs) +
-                sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t);
-       if (reqlen > SLI4_PAGE_SIZE) {
-               lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
-                               "2989 Block sgl registration required DMA "
-                               "size (%d) great than a page\n", reqlen);
-               return -ENOMEM;
-       }
-
-       cnt = 0;
-       ttl_cnt = 0;
-       post_els_xri_cnt = els_xri_cnt;
-       list_for_each_entry(rsrc_blk, &phba->sli4_hba.lpfc_xri_blk_list,
-                           list) {
-               rsrc_start = rsrc_blk->rsrc_start;
-               rsrc_size = rsrc_blk->rsrc_size;
-
-               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                               "3014 Working ELS Extent start %d, cnt %d\n",
-                               rsrc_start, rsrc_size);
-
-               loop_cnt = min(post_els_xri_cnt, rsrc_size);
-               if (loop_cnt < post_els_xri_cnt) {
-                       post_els_xri_cnt -= loop_cnt;
-                       ttl_cnt += loop_cnt;
-               } else
-                       ttl_cnt += post_els_xri_cnt;
-
-               mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-               if (!mbox)
-                       return -ENOMEM;
-               /*
-                * Allocate DMA memory and set up the non-embedded mailbox
-                * command.
-                */
-               alloclen = lpfc_sli4_config(phba, mbox,
-                                       LPFC_MBOX_SUBSYSTEM_FCOE,
-                                       LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES,
-                                       reqlen, LPFC_SLI4_MBX_NEMBED);
-               if (alloclen < reqlen) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                                       "2987 Allocated DMA memory size (%d) "
-                                       "is less than the requested DMA memory "
-                                       "size (%d)\n", alloclen, reqlen);
-                       lpfc_sli4_mbox_cmd_free(phba, mbox);
-                       return -ENOMEM;
-               }
-
-               /* Set up the SGL pages in the non-embedded DMA pages */
-               viraddr = mbox->sge_array->addr[0];
-               sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr;
-               sgl_pg_pairs = &sgl->sgl_pg_pairs;
-
-               /*
-                * The starting resource may not begin at zero. Control
-                * the loop variants via the block resource parameters,
-                * but handle the sge pointers with a zero-based index
-                * that doesn't get reset per loop pass.
-                */
-               for (index = rsrc_start;
-                    index < rsrc_start + loop_cnt;
-                    index++) {
-                       sglq_entry = phba->sli4_hba.lpfc_els_sgl_array[cnt];
-
-                       /*
-                        * Assign the sglq a physical xri only if the driver
-                        * has not initialized those resources.  A port reset
-                        * only needs the sglq's posted.
-                        */
-                       if (bf_get(lpfc_xri_rsrc_rdy,
-                                  &phba->sli4_hba.sli4_flags) !=
-                                  LPFC_XRI_RSRC_RDY) {
-                               lxri = lpfc_sli4_next_xritag(phba);
-                               if (lxri == NO_XRI) {
-                                       lpfc_sli4_mbox_cmd_free(phba, mbox);
-                                       rc = -ENOMEM;
-                                       goto err_exit;
-                               }
-                               sglq_entry->sli4_lxritag = lxri;
-                               sglq_entry->sli4_xritag =
-                                               phba->sli4_hba.xri_ids[lxri];
-                       }
-
-                       /* Set up the sge entry */
-                       sgl_pg_pairs->sgl_pg0_addr_lo =
-                               cpu_to_le32(putPaddrLow(sglq_entry->phys));
-                       sgl_pg_pairs->sgl_pg0_addr_hi =
-                               cpu_to_le32(putPaddrHigh(sglq_entry->phys));
-                       sgl_pg_pairs->sgl_pg1_addr_lo =
-                               cpu_to_le32(putPaddrLow(0));
-                       sgl_pg_pairs->sgl_pg1_addr_hi =
-                               cpu_to_le32(putPaddrHigh(0));
-
-                       /* Track the starting physical XRI for the mailbox. */
-                       if (index == rsrc_start)
-                               xritag_start = sglq_entry->sli4_xritag;
-                       sgl_pg_pairs++;
-                       cnt++;
-               }
-
-               /* Complete initialization and perform endian conversion. */
-               rsrc_blk->rsrc_used += loop_cnt;
-               bf_set(lpfc_post_sgl_pages_xri, sgl, xritag_start);
-               bf_set(lpfc_post_sgl_pages_xricnt, sgl, loop_cnt);
-               sgl->word0 = cpu_to_le32(sgl->word0);
-
-               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                               "3015 Post ELS Extent SGL, start %d, "
-                               "cnt %d, used %d\n",
-                               xritag_start, loop_cnt, rsrc_blk->rsrc_used);
-               if (!phba->sli4_hba.intr_enable)
-                       rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
-               else {
-                       mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
-                       rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
-               }
-               shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
-               shdr_status = bf_get(lpfc_mbox_hdr_status,
-                                    &shdr->response);
-               shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
-                                        &shdr->response);
-               if (rc != MBX_TIMEOUT)
-                       lpfc_sli4_mbox_cmd_free(phba, mbox);
-               if (shdr_status || shdr_add_status || rc) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                                       "2988 POST_SGL_BLOCK mailbox "
-                                       "command failed status x%x "
-                                       "add_status x%x mbx status x%x\n",
-                                       shdr_status, shdr_add_status, rc);
-                       rc = -ENXIO;
-                       goto err_exit;
-               }
-               if (ttl_cnt >= els_xri_cnt)
-                       break;
-       }
-
- err_exit:
-       if (rc == 0)
-               bf_set(lpfc_xri_rsrc_rdy, &phba->sli4_hba.sli4_flags,
-                      LPFC_XRI_RSRC_RDY);
        return rc;
 }
 
@@ -13452,8 +13399,9 @@ lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba)
  *
  **/
 int
-lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist,
-                             int cnt)
+lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba,
+                             struct list_head *sblist,
+                             int count)
 {
        struct lpfc_scsi_buf *psb;
        struct lpfc_mbx_post_uembed_sgl_page1 *sgl;
@@ -13469,7 +13417,7 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist,
        union lpfc_sli4_cfg_shdr *shdr;
 
        /* Calculate the requested length of the dma memory */
-       reqlen = cnt * sizeof(struct sgl_page_pairs) +
+       reqlen = count * sizeof(struct sgl_page_pairs) +
                 sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t);
        if (reqlen > SLI4_PAGE_SIZE) {
                lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
@@ -13552,169 +13500,6 @@ lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *phba, struct list_head *sblist,
        return rc;
 }
 
-/**
- * lpfc_sli4_post_scsi_sgl_blk_ext - post a block of scsi sgls to the port.
- * @phba: pointer to lpfc hba data structure.
- * @sblist: pointer to scsi buffer list.
- * @count: number of scsi buffers on the list.
- *
- * This routine is invoked to post a block of @count scsi sgl pages from a
- * SCSI buffer list @sblist to the HBA using non-embedded mailbox command.
- * No Lock is held.
- *
- **/
-int
-lpfc_sli4_post_scsi_sgl_blk_ext(struct lpfc_hba *phba, struct list_head *sblist,
-                               int cnt)
-{
-       struct lpfc_scsi_buf *psb = NULL;
-       struct lpfc_mbx_post_uembed_sgl_page1 *sgl;
-       struct sgl_page_pairs *sgl_pg_pairs;
-       void *viraddr;
-       LPFC_MBOXQ_t *mbox;
-       uint32_t reqlen, alloclen, pg_pairs;
-       uint32_t mbox_tmo;
-       uint16_t xri_start = 0, scsi_xri_start;
-       uint16_t rsrc_range;
-       int rc = 0, avail_cnt;
-       uint32_t shdr_status, shdr_add_status;
-       dma_addr_t pdma_phys_bpl1;
-       union lpfc_sli4_cfg_shdr *shdr;
-       struct lpfc_rsrc_blks *rsrc_blk;
-       uint32_t xri_cnt = 0;
-
-       /* Calculate the total requested length of the dma memory */
-       reqlen = cnt * sizeof(struct sgl_page_pairs) +
-                sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t);
-       if (reqlen > SLI4_PAGE_SIZE) {
-               lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
-                               "2932 Block sgl registration required DMA "
-                               "size (%d) great than a page\n", reqlen);
-               return -ENOMEM;
-       }
-
-       /*
-        * The use of extents requires the driver to post the sgl headers
-        * in multiple postings to meet the contiguous resource assignment.
-        */
-       psb = list_prepare_entry(psb, sblist, list);
-       scsi_xri_start = phba->sli4_hba.scsi_xri_start;
-       list_for_each_entry(rsrc_blk, &phba->sli4_hba.lpfc_xri_blk_list,
-                           list) {
-               rsrc_range = rsrc_blk->rsrc_start + rsrc_blk->rsrc_size;
-               if (rsrc_range < scsi_xri_start)
-                       continue;
-               else if (rsrc_blk->rsrc_used >= rsrc_blk->rsrc_size)
-                       continue;
-               else
-                       avail_cnt = rsrc_blk->rsrc_size - rsrc_blk->rsrc_used;
-
-               reqlen = (avail_cnt * sizeof(struct sgl_page_pairs)) +
-                       sizeof(union lpfc_sli4_cfg_shdr) + sizeof(uint32_t);
-               /*
-                * Allocate DMA memory and set up the non-embedded mailbox
-                * command. The mbox is used to post an SGL page per loop
-                * but the DMA memory has a use-once semantic so the mailbox
-                * is used and freed per loop pass.
-                */
-               mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-               if (!mbox) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                                       "2933 Failed to allocate mbox cmd "
-                                       "memory\n");
-                       return -ENOMEM;
-               }
-               alloclen = lpfc_sli4_config(phba, mbox,
-                                       LPFC_MBOX_SUBSYSTEM_FCOE,
-                                       LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES,
-                                       reqlen,
-                                       LPFC_SLI4_MBX_NEMBED);
-               if (alloclen < reqlen) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                                       "2934 Allocated DMA memory size (%d) "
-                                       "is less than the requested DMA memory "
-                                       "size (%d)\n", alloclen, reqlen);
-                       lpfc_sli4_mbox_cmd_free(phba, mbox);
-                       return -ENOMEM;
-               }
-
-               /* Get the first SGE entry from the non-embedded DMA memory */
-               viraddr = mbox->sge_array->addr[0];
-
-               /* Set up the SGL pages in the non-embedded DMA pages */
-               sgl = (struct lpfc_mbx_post_uembed_sgl_page1 *)viraddr;
-               sgl_pg_pairs = &sgl->sgl_pg_pairs;
-
-               /* pg_pairs tracks posted SGEs per loop iteration. */
-               pg_pairs = 0;
-               list_for_each_entry_continue(psb, sblist, list) {
-                       /* Set up the sge entry */
-                       sgl_pg_pairs->sgl_pg0_addr_lo =
-                               cpu_to_le32(putPaddrLow(psb->dma_phys_bpl));
-                       sgl_pg_pairs->sgl_pg0_addr_hi =
-                               cpu_to_le32(putPaddrHigh(psb->dma_phys_bpl));
-                       if (phba->cfg_sg_dma_buf_size > SGL_PAGE_SIZE)
-                               pdma_phys_bpl1 = psb->dma_phys_bpl +
-                                       SGL_PAGE_SIZE;
-                       else
-                               pdma_phys_bpl1 = 0;
-                       sgl_pg_pairs->sgl_pg1_addr_lo =
-                               cpu_to_le32(putPaddrLow(pdma_phys_bpl1));
-                       sgl_pg_pairs->sgl_pg1_addr_hi =
-                               cpu_to_le32(putPaddrHigh(pdma_phys_bpl1));
-                       /* Keep the first xri for this extent. */
-                       if (pg_pairs == 0)
-                               xri_start = psb->cur_iocbq.sli4_xritag;
-                       sgl_pg_pairs++;
-                       pg_pairs++;
-                       xri_cnt++;
-
-                       /*
-                        * Track two exit conditions - the loop has constructed
-                        * all of the caller's SGE pairs or all available
-                        * resource IDs in this extent are consumed.
-                        */
-                       if ((xri_cnt == cnt) || (pg_pairs >= avail_cnt))
-                               break;
-               }
-               rsrc_blk->rsrc_used += pg_pairs;
-               bf_set(lpfc_post_sgl_pages_xri, sgl, xri_start);
-               bf_set(lpfc_post_sgl_pages_xricnt, sgl, pg_pairs);
-
-               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                               "3016 Post SCSI Extent SGL, start %d, cnt %d "
-                               "blk use %d\n",
-                               xri_start, pg_pairs, rsrc_blk->rsrc_used);
-               /* Perform endian conversion if necessary */
-               sgl->word0 = cpu_to_le32(sgl->word0);
-               if (!phba->sli4_hba.intr_enable)
-                       rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
-               else {
-                       mbox_tmo = lpfc_mbox_tmo_val(phba, mbox);
-                       rc = lpfc_sli_issue_mbox_wait(phba, mbox, mbox_tmo);
-               }
-               shdr = (union lpfc_sli4_cfg_shdr *) &sgl->cfg_shdr;
-               shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
-               shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
-                                        &shdr->response);
-               if (rc != MBX_TIMEOUT)
-                       lpfc_sli4_mbox_cmd_free(phba, mbox);
-               if (shdr_status || shdr_add_status || rc) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                                       "2935 POST_SGL_BLOCK mailbox command "
-                                       "failed status x%x add_status x%x "
-                                       "mbx status x%x\n",
-                                       shdr_status, shdr_add_status, rc);
-                       return -ENXIO;
-               }
-
-               /* Post only what is requested. */
-               if (xri_cnt >= cnt)
-                       break;
-       }
-       return rc;
-}
-
 /**
  * lpfc_fc_frame_check - Check that this frame is a valid frame to handle
  * @phba: pointer to lpfc_hba struct that the frame was received on
index c19d139618b729ed7d7f5b8dfb99406e59e25236..f097382d7b91d2e88d24721980747324654417bc 100644 (file)
@@ -493,14 +493,12 @@ struct lpfc_sli4_hba {
        uint16_t next_rpi;
        uint16_t scsi_xri_max;
        uint16_t scsi_xri_cnt;
+       uint16_t els_xri_cnt;
        uint16_t scsi_xri_start;
        struct list_head lpfc_free_sgl_list;
        struct list_head lpfc_sgl_list;
-       struct lpfc_sglq **lpfc_els_sgl_array;
        struct list_head lpfc_abts_els_sgl_list;
-       struct lpfc_scsi_buf **lpfc_scsi_psb_array;
        struct list_head lpfc_abts_scsi_buf_list;
-       uint32_t total_sglq_bufs;
        struct lpfc_sglq **lpfc_sglq_active_list;
        struct list_head lpfc_rpi_hdr_list;
        unsigned long *rpi_bmask;
@@ -509,7 +507,6 @@ struct lpfc_sli4_hba {
        struct list_head lpfc_rpi_blk_list;
        unsigned long *xri_bmask;
        uint16_t *xri_ids;
-       uint16_t xri_count;
        struct list_head lpfc_xri_blk_list;
        unsigned long *vfi_bmask;
        uint16_t *vfi_ids;
@@ -614,11 +611,7 @@ int lpfc_sli4_post_sgl(struct lpfc_hba *, dma_addr_t, dma_addr_t, uint16_t);
 int lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *);
 uint16_t lpfc_sli4_next_xritag(struct lpfc_hba *);
 int lpfc_sli4_post_async_mbox(struct lpfc_hba *);
-int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *phba);
-int lpfc_sli4_post_els_sgl_list_ext(struct lpfc_hba *phba);
 int lpfc_sli4_post_scsi_sgl_block(struct lpfc_hba *, struct list_head *, int);
-int lpfc_sli4_post_scsi_sgl_blk_ext(struct lpfc_hba *, struct list_head *,
-                                   int);
 struct lpfc_cq_event *__lpfc_sli4_cq_event_alloc(struct lpfc_hba *);
 struct lpfc_cq_event *lpfc_sli4_cq_event_alloc(struct lpfc_hba *);
 void __lpfc_sli4_cq_event_release(struct lpfc_hba *, struct lpfc_cq_event *);
This page took 0.079372 seconds and 5 git commands to generate.