[SCSI] lpfc 8.3.31: Correct handling of SLI4-port XRI resource-provisioning profile change
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>
This commit is contained in:
parent
587a37f6e0
commit
8a9d2e8003
|
@ -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 *);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
/* els xri-sgl book keeping */
|
||||
phba->sli4_hba.els_xri_cnt = 0;
|
||||
|
||||
/* 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -718,11 +718,137 @@ 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 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 = failure, non-zero number of successfully posted buffers.
|
||||
**/
|
||||
int
|
||||
lpfc_sli4_post_scsi_sgl_list(struct lpfc_hba *phba,
|
||||
struct list_head *post_sblist, int sb_count)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
num_posting++;
|
||||
last_xritag = psb->cur_iocbq.sli4_xritag;
|
||||
|
||||
/* 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 a nembed page worth of sgls */
|
||||
if (post_cnt == 0)
|
||||
continue;
|
||||
|
||||
/* 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) {
|
||||
/* 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++;
|
||||
}
|
||||
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 HBA by using SGL block post. This is needed after a
|
||||
* 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.
|
||||
|
@ -732,57 +858,21 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
|
|||
int
|
||||
lpfc_sli4_repost_scsi_sgl_list(struct lpfc_hba *phba)
|
||||
{
|
||||
struct lpfc_scsi_buf *psb;
|
||||
int index, status, bcnt = 0, rcnt = 0, rc = 0;
|
||||
LIST_HEAD(sblist);
|
||||
LIST_HEAD(post_sblist);
|
||||
int num_posted, rc = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
} else
|
||||
/* A hole present in the XRI array, need to skip */
|
||||
bcnt = rcnt;
|
||||
/* 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);
|
||||
|
||||
if (index == phba->sli4_hba.scsi_xri_cnt - 1)
|
||||
/* End of XRI array for SCSI buffer, complete */
|
||||
bcnt = rcnt;
|
||||
|
||||
/* Continue until collect up to a nembed page worth of sgls */
|
||||
if (bcnt == 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);
|
||||
if (status) {
|
||||
/* Put this back on the abort scsi list */
|
||||
psb->exch_busy = 1;
|
||||
rc++;
|
||||
} else {
|
||||
psb->exch_busy = 0;
|
||||
psb->status = IOSTAT_SUCCESS;
|
||||
}
|
||||
/* Put it back into the SCSI buffer list */
|
||||
lpfc_release_scsi_buf_s4(phba, psb);
|
||||
}
|
||||
/* 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);
|
||||
|
||||
return bcnt + non_sequential_xri;
|
||||
/* 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 num_posted;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 *);
|
||||
|
|
Loading…
Reference in New Issue