Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8a9d2e80 authored by James Smart's avatar James Smart Committed by James Bottomley
Browse files

[SCSI] lpfc 8.3.31: Correct handling of SLI4-port XRI resource-provisioning profile change

parent 587a37f6
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -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 *);
+3 −7
Original line number Diff line number Diff line
@@ -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
+218 −149
Original line number Diff line number Diff line
@@ -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 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
	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 @@ lpfc_init_iocb_list(struct lpfc_hba *phba, int iocb_count)
}

/**
 * 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);

	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;
	}
	/* els xri-sgl book keeping */
	phba->sli4_hba.els_xri_cnt = 0;

	/* 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;
}
+172 −124

File changed.

Preview size limit exceeded, changes collapsed.

+196 −411

File changed.

Preview size limit exceeded, changes collapsed.

Loading