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

Commit 7370d10a authored by James Smart's avatar James Smart Committed by Martin K. Petersen
Browse files

scsi: lpfc: Remove extra vector and SLI4 queue for Expresslane



There is a extra queue and msix vector for expresslane. Now that the driver
will be doing queues per cpu, this oddball queue is no longer needed.
Expresslane will utilize the normal per-cpu queues.

Updated debugfs sli4 queue output to go along with the change

Signed-off-by: default avatarDick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 0794d601
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -199,11 +199,6 @@ void lpfc_reset_hba(struct lpfc_hba *);
int lpfc_emptyq_wait(struct lpfc_hba *phba, struct list_head *hd,
			spinlock_t *slock);

int lpfc_fof_queue_create(struct lpfc_hba *);
int lpfc_fof_queue_setup(struct lpfc_hba *);
int lpfc_fof_queue_destroy(struct lpfc_hba *);
irqreturn_t lpfc_sli4_fof_intr_handler(int, void *);

int lpfc_sli_setup(struct lpfc_hba *);
int lpfc_sli4_setup(struct lpfc_hba *phba);
void lpfc_sli_queue_init(struct lpfc_hba *phba);
+1 −35
Original line number Diff line number Diff line
@@ -3390,13 +3390,8 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
	if (phba->sli4_hba.hba_eq && phba->io_channel_irqs) {

		x = phba->lpfc_idiag_last_eq;
		if (phba->cfg_fof && (x >= phba->io_channel_irqs)) {
			phba->lpfc_idiag_last_eq = 0;
			goto fof;
		}
		phba->lpfc_idiag_last_eq++;
		if (phba->lpfc_idiag_last_eq >= phba->io_channel_irqs)
			if (phba->cfg_fof == 0)
			phba->lpfc_idiag_last_eq = 0;

		len += snprintf(pbuffer + len, LPFC_QUE_INFO_GET_BUF_SIZE - len,
@@ -3479,35 +3474,6 @@ lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
		goto out;
	}

fof:
	if (phba->cfg_fof) {
		/* FOF EQ */
		qp = phba->sli4_hba.fof_eq;
		len = __lpfc_idiag_print_eq(qp, "FOF", pbuffer, len);

		/* Reset max counter */
		if (qp)
			qp->EQ_max_eqe = 0;

		if (len >= max_cnt)
			goto too_big;

		/* OAS CQ */
		qp = phba->sli4_hba.oas_cq;
		len = __lpfc_idiag_print_cq(qp, "OAS", pbuffer, len);
		/* Reset max counter */
		if (qp)
			qp->CQ_max_cqe = 0;
		if (len >= max_cnt)
			goto too_big;

		/* OAS WQ */
		qp = phba->sli4_hba.oas_wq;
		len = __lpfc_idiag_print_wq(qp, "OAS", pbuffer, len);
		if (len >= max_cnt)
			goto too_big;
	}

	spin_unlock_irq(&phba->hbalock);
	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);

+8 −217
Original line number Diff line number Diff line
@@ -6059,7 +6059,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
	uint8_t pn_page[LPFC_MAX_SUPPORTED_PAGES] = {0};
	struct lpfc_mqe *mqe;
	int longs;
	int fof_vectors = 0;
	int extra;
	uint64_t wwn;
	u32 if_type;
@@ -6433,8 +6432,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)

	/* Verify OAS is supported */
	lpfc_sli4_oas_verify(phba);
	if (phba->cfg_fof)
		fof_vectors = 1;

	/* Verify RAS support on adapter */
	lpfc_sli4_ras_init(phba);
@@ -6478,7 +6475,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
		goto out_remove_rpi_hdrs;
	}

	phba->sli4_hba.hba_eq_hdl = kcalloc(fof_vectors + phba->io_channel_irqs,
	phba->sli4_hba.hba_eq_hdl = kcalloc(phba->io_channel_irqs,
						sizeof(struct lpfc_hba_eq_hdl),
						GFP_KERNEL);
	if (!phba->sli4_hba.hba_eq_hdl) {
@@ -8048,7 +8045,7 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
			/*
			 * Whats left after this can go toward NVME.
			 * The minus 6 accounts for ELS, NVME LS, MBOX
			 * fof plus a couple extra. When configured for
			 * plus a couple extra. When configured for
			 * NVMET, FCP io channel WQs are not created.
			 */
			length -= 6;
@@ -8280,7 +8277,6 @@ static int
lpfc_sli4_queue_verify(struct lpfc_hba *phba)
{
	int io_channel;
	int fof_vectors = phba->cfg_fof ? 1 : 0;

	/*
	 * Sanity check for configured queue parameters against the run-time
@@ -8299,13 +8295,13 @@ lpfc_sli4_queue_verify(struct lpfc_hba *phba)
		io_channel = phba->sli4_hba.num_online_cpu;
	}

	if (io_channel + fof_vectors > phba->sli4_hba.max_cfg_param.max_eq) {
	if (io_channel > phba->sli4_hba.max_cfg_param.max_eq) {
		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
				"2575 Reducing IO channels to match number of "
				"available EQs: from %d to %d\n",
				io_channel,
				phba->sli4_hba.max_cfg_param.max_eq);
		io_channel = phba->sli4_hba.max_cfg_param.max_eq - fof_vectors;
		io_channel = phba->sli4_hba.max_cfg_param.max_eq;
	}

	/* The actual number of FCP / NVME event queues adopted */
@@ -8769,10 +8765,6 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
			phba->sli4_hba.nvmet_mrq_data[idx] = qdesc;
		}
	}

	/* Create the Queues needed for Flash Optimized Fabric operations */
	if (phba->cfg_fof)
		lpfc_fof_queue_create(phba);
	return 0;

out_error:
@@ -8828,9 +8820,6 @@ lpfc_sli4_release_queue_map(uint16_t **qmap)
void
lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
{
	if (phba->cfg_fof)
		lpfc_fof_queue_destroy(phba);

	/* Release HBA eqs */
	lpfc_sli4_release_queues(&phba->sli4_hba.hba_eq, phba->io_channel_irqs);

@@ -9331,16 +9320,6 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
			phba->sli4_hba.dat_rq->queue_id,
			phba->sli4_hba.els_cq->queue_id);

	if (phba->cfg_fof) {
		rc = lpfc_fof_queue_setup(phba);
		if (rc) {
			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
					"0549 Failed setup of FOF Queues: "
					"rc = 0x%x\n", rc);
			goto out_destroy;
		}
	}

	for (qidx = 0; qidx < io_channel; qidx += LPFC_MAX_EQ_DELAY_EQID_CNT)
		lpfc_modify_hba_eq_delay(phba, qidx, LPFC_MAX_EQ_DELAY_EQID_CNT,
					 phba->cfg_fcp_imax);
@@ -9370,10 +9349,6 @@ lpfc_sli4_queue_unset(struct lpfc_hba *phba)
{
	int qidx;

	/* Unset the queues created for Flash Optimized Fabric operations */
	if (phba->cfg_fof)
		lpfc_fof_queue_destroy(phba);

	/* Unset mailbox command work queue */
	if (phba->sli4_hba.mbx_wq)
		lpfc_mq_destroy(phba, phba->sli4_hba.mbx_wq);
@@ -10297,8 +10272,6 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)

	/* Set up MSI-X multi-message vectors */
	vectors = phba->io_channel_irqs;
	if (phba->cfg_fof)
		vectors++;

	rc = pci_alloc_irq_vectors(phba->pcidev,
				(phba->nvmet_support) ? 1 : 2,
@@ -10320,12 +10293,6 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
		phba->sli4_hba.hba_eq_hdl[index].idx = index;
		phba->sli4_hba.hba_eq_hdl[index].phba = phba;
		atomic_set(&phba->sli4_hba.hba_eq_hdl[index].hba_eq_in_use, 1);
		if (phba->cfg_fof && (index == (vectors - 1)))
			rc = request_irq(pci_irq_vector(phba->pcidev, index),
				 &lpfc_sli4_fof_intr_handler, 0,
				 name,
				 &phba->sli4_hba.hba_eq_hdl[index]);
		else
		rc = request_irq(pci_irq_vector(phba->pcidev, index),
			 &lpfc_sli4_hba_intr_handler, 0,
			 name,
@@ -10338,9 +10305,6 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
		}
	}

	if (phba->cfg_fof)
		vectors--;

	if (vectors != phba->io_channel_irqs) {
		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
				"3238 Reducing IO channels to match number of "
@@ -10415,10 +10379,6 @@ lpfc_sli4_enable_msi(struct lpfc_hba *phba)
		phba->sli4_hba.hba_eq_hdl[index].phba = phba;
	}

	if (phba->cfg_fof) {
		phba->sli4_hba.hba_eq_hdl[index].idx = index;
		phba->sli4_hba.hba_eq_hdl[index].phba = phba;
	}
	return 0;
}

@@ -10485,12 +10445,6 @@ lpfc_sli4_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode)
				eqhdl->phba = phba;
				atomic_set(&eqhdl->hba_eq_in_use, 1);
			}
			if (phba->cfg_fof) {
				eqhdl = &phba->sli4_hba.hba_eq_hdl[idx];
				eqhdl->idx = idx;
				eqhdl->phba = phba;
				atomic_set(&eqhdl->hba_eq_in_use, 1);
			}
		}
	}
	return intr_mode;
@@ -10516,10 +10470,6 @@ lpfc_sli4_disable_intr(struct lpfc_hba *phba)
		for (index = 0; index < phba->io_channel_irqs; index++)
			free_irq(pci_irq_vector(phba->pcidev, index),
					&phba->sli4_hba.hba_eq_hdl[index]);

		if (phba->cfg_fof)
			free_irq(pci_irq_vector(phba->pcidev, index),
					&phba->sli4_hba.hba_eq_hdl[index]);
	} else {
		free_irq(phba->pcidev->irq, phba);
	}
@@ -12692,165 +12642,6 @@ lpfc_sli4_ras_init(struct lpfc_hba *phba)
	}
}

/**
 * lpfc_fof_queue_setup - Set up all the fof queues
 * @phba: pointer to lpfc hba data structure.
 *
 * This routine is invoked to set up all the fof queues for the FC HBA
 * operation.
 *
 * Return codes
 *      0 - successful
 *      -ENOMEM - No available memory
 **/
int
lpfc_fof_queue_setup(struct lpfc_hba *phba)
{
	struct lpfc_sli_ring *pring;
	int rc;

	rc = lpfc_eq_create(phba, phba->sli4_hba.fof_eq, LPFC_MAX_IMAX);
	if (rc)
		return -ENOMEM;

	if (phba->cfg_fof) {

		rc = lpfc_cq_create(phba, phba->sli4_hba.oas_cq,
				    phba->sli4_hba.fof_eq, LPFC_WCQ, LPFC_FCP);
		if (rc)
			goto out_oas_cq;

		rc = lpfc_wq_create(phba, phba->sli4_hba.oas_wq,
				    phba->sli4_hba.oas_cq, LPFC_FCP);
		if (rc)
			goto out_oas_wq;

		/* Bind this CQ/WQ to the NVME ring */
		pring = phba->sli4_hba.oas_wq->pring;
		pring->sli.sli4.wqp =
			(void *)phba->sli4_hba.oas_wq;
		phba->sli4_hba.oas_cq->pring = pring;
	}

	return 0;

out_oas_wq:
	lpfc_cq_destroy(phba, phba->sli4_hba.oas_cq);
out_oas_cq:
	lpfc_eq_destroy(phba, phba->sli4_hba.fof_eq);
	return rc;

}

/**
 * lpfc_fof_queue_create - Create all the fof queues
 * @phba: pointer to lpfc hba data structure.
 *
 * This routine is invoked to allocate all the fof queues for the FC HBA
 * operation. For each SLI4 queue type, the parameters such as queue entry
 * count (queue depth) shall be taken from the module parameter. For now,
 * we just use some constant number as place holder.
 *
 * Return codes
 *      0 - successful
 *      -ENOMEM - No availble memory
 *      -EIO - The mailbox failed to complete successfully.
 **/
int
lpfc_fof_queue_create(struct lpfc_hba *phba)
{
	struct lpfc_queue *qdesc;
	uint32_t wqesize;

	/* Create FOF EQ */
	qdesc = lpfc_sli4_queue_alloc(phba, LPFC_DEFAULT_PAGE_SIZE,
				      phba->sli4_hba.eq_esize,
				      phba->sli4_hba.eq_ecount);
	if (!qdesc)
		goto out_error;

	qdesc->qe_valid = 1;
	phba->sli4_hba.fof_eq = qdesc;

	if (phba->cfg_fof) {

		/* Create OAS CQ */
		if (phba->enab_exp_wqcq_pages)
			qdesc = lpfc_sli4_queue_alloc(phba,
						      LPFC_EXPANDED_PAGE_SIZE,
						      phba->sli4_hba.cq_esize,
						      LPFC_CQE_EXP_COUNT);
		else
			qdesc = lpfc_sli4_queue_alloc(phba,
						      LPFC_DEFAULT_PAGE_SIZE,
						      phba->sli4_hba.cq_esize,
						      phba->sli4_hba.cq_ecount);
		if (!qdesc)
			goto out_error;

		qdesc->qe_valid = 1;
		phba->sli4_hba.oas_cq = qdesc;

		/* Create OAS WQ */
		if (phba->enab_exp_wqcq_pages) {
			wqesize = (phba->fcp_embed_io) ?
				LPFC_WQE128_SIZE : phba->sli4_hba.wq_esize;
			qdesc = lpfc_sli4_queue_alloc(phba,
						      LPFC_EXPANDED_PAGE_SIZE,
						      wqesize,
						      LPFC_WQE_EXP_COUNT);
		} else
			qdesc = lpfc_sli4_queue_alloc(phba,
						      LPFC_DEFAULT_PAGE_SIZE,
						      phba->sli4_hba.wq_esize,
						      phba->sli4_hba.wq_ecount);

		if (!qdesc)
			goto out_error;

		phba->sli4_hba.oas_wq = qdesc;
		list_add_tail(&qdesc->wq_list, &phba->sli4_hba.lpfc_wq_list);

	}
	return 0;

out_error:
	lpfc_fof_queue_destroy(phba);
	return -ENOMEM;
}

/**
 * lpfc_fof_queue_destroy - Destroy all the fof queues
 * @phba: pointer to lpfc hba data structure.
 *
 * This routine is invoked to release all the SLI4 queues with the FC HBA
 * operation.
 *
 * Return codes
 *      0 - successful
 **/
int
lpfc_fof_queue_destroy(struct lpfc_hba *phba)
{
	/* Release FOF Event queue */
	if (phba->sli4_hba.fof_eq != NULL) {
		lpfc_sli4_queue_free(phba->sli4_hba.fof_eq);
		phba->sli4_hba.fof_eq = NULL;
	}

	/* Release OAS Completion queue */
	if (phba->sli4_hba.oas_cq != NULL) {
		lpfc_sli4_queue_free(phba->sli4_hba.oas_cq);
		phba->sli4_hba.oas_cq = NULL;
	}

	/* Release OAS Work queue */
	if (phba->sli4_hba.oas_wq != NULL) {
		lpfc_sli4_queue_free(phba->sli4_hba.oas_wq);
		phba->sli4_hba.oas_wq = NULL;
	}
	return 0;
}

MODULE_DEVICE_TABLE(pci, lpfc_id_table);

+1 −8
Original line number Diff line number Diff line
@@ -4598,14 +4598,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)

	iocb = &lpfc_cmd->cur_iocbq;
	if (phba->sli_rev == LPFC_SLI_REV4) {
		if (!(phba->cfg_fof) ||
		    (!(iocb->iocb_flag & LPFC_IO_FOF))) {
			pring_s4 =
				phba->sli4_hba.fcp_wq[iocb->hba_wqidx]->pring;
		} else {
			iocb->hba_wqidx = 0;
			pring_s4 = phba->sli4_hba.oas_wq->pring;
		}
		pring_s4 = phba->sli4_hba.fcp_wq[iocb->hba_wqidx]->pring;
		if (!pring_s4) {
			ret = FAILED;
			goto out_unlock;
+15 −197
Original line number Diff line number Diff line
@@ -5581,9 +5581,6 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba)
			sli4_hba->sli4_cq_release(sli4_hba->nvme_cq[qidx],
						LPFC_QUEUE_REARM);
	if (phba->cfg_fof)
		sli4_hba->sli4_cq_release(sli4_hba->oas_cq, LPFC_QUEUE_REARM);
	if (sli4_hba->hba_eq)
		for (qidx = 0; qidx < phba->io_channel_irqs; qidx++)
			sli4_hba->sli4_eq_release(sli4_hba->hba_eq[qidx],
@@ -5596,9 +5593,6 @@ lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba)
				LPFC_QUEUE_REARM);
		}
	}
	if (phba->cfg_fof)
		sli4_hba->sli4_eq_release(sli4_hba->fof_eq, LPFC_QUEUE_REARM);
}
/**
@@ -9872,10 +9866,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number,
	/* Get the WQ */
	if ((piocb->iocb_flag & LPFC_IO_FCP) ||
	    (piocb->iocb_flag & LPFC_USE_FCPWQIDX)) {
		if (!phba->cfg_fof || (!(piocb->iocb_flag & LPFC_IO_OAS)))
		wq = phba->sli4_hba.fcp_wq[piocb->hba_wqidx];
		else
			wq = phba->sli4_hba.oas_wq;
	} else {
		wq = phba->sli4_hba.els_wq;
	}
@@ -10010,8 +10001,6 @@ struct lpfc_sli_ring *
lpfc_sli4_calc_ring(struct lpfc_hba *phba, struct lpfc_iocbq *piocb)
{
	if (piocb->iocb_flag & (LPFC_IO_FCP | LPFC_USE_FCPWQIDX)) {
		if (!(phba->cfg_fof) ||
		    (!(piocb->iocb_flag & LPFC_IO_FOF))) {
		if (unlikely(!phba->sli4_hba.fcp_wq))
			return NULL;
		/*
@@ -10020,18 +10009,12 @@ lpfc_sli4_calc_ring(struct lpfc_hba *phba, struct lpfc_iocbq *piocb)
		 */
		if (!(piocb->iocb_flag & LPFC_USE_FCPWQIDX)) {
			piocb->hba_wqidx =
					lpfc_sli4_scmd_to_wqidx_distr(phba,
							      piocb->context1);
				lpfc_sli4_scmd_to_wqidx_distr(
					phba, piocb->context1);
			piocb->hba_wqidx = piocb->hba_wqidx %
				phba->cfg_fcp_io_channel;
		}
		return phba->sli4_hba.fcp_wq[piocb->hba_wqidx]->pring;
		} else {
			if (unlikely(!phba->sli4_hba.oas_wq))
				return NULL;
			piocb->hba_wqidx = 0;
			return phba->sli4_hba.oas_wq->pring;
		}
	} else {
		if (unlikely(!phba->sli4_hba.els_wq))
			return NULL;
@@ -10550,16 +10533,6 @@ lpfc_sli4_queue_init(struct lpfc_hba *phba)
		spin_lock_init(&pring->ring_lock);
	}
	if (phba->cfg_fof) {
		pring = phba->sli4_hba.oas_wq->pring;
		pring->flag = 0;
		pring->ringno = LPFC_FCP_RING;
		INIT_LIST_HEAD(&pring->txq);
		INIT_LIST_HEAD(&pring->txcmplq);
		INIT_LIST_HEAD(&pring->iocb_continueq);
		spin_lock_init(&pring->ring_lock);
	}
	spin_unlock_irq(&phba->hbalock);
}
@@ -14219,154 +14192,6 @@ lpfc_sli4_eq_flush(struct lpfc_hba *phba, struct lpfc_queue *eq)
}
/**
 * lpfc_sli4_fof_handle_eqe - Process a Flash Optimized Fabric event queue
 *			     entry
 * @phba: Pointer to HBA context object.
 * @eqe: Pointer to fast-path event queue entry.
 *
 * This routine process a event queue entry from the Flash Optimized Fabric
 * event queue.  It will check the MajorCode and MinorCode to determine this
 * is for a completion event on a completion queue, if not, an error shall be
 * logged and just return. Otherwise, it will get to the corresponding
 * completion queue and process all the entries on the completion queue, rearm
 * the completion queue, and then return.
 **/
static void
lpfc_sli4_fof_handle_eqe(struct lpfc_hba *phba, struct lpfc_eqe *eqe)
{
	struct lpfc_queue *cq;
	uint16_t cqid;
	if (unlikely(bf_get_le32(lpfc_eqe_major_code, eqe) != 0)) {
		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
				"9147 Not a valid completion "
				"event: majorcode=x%x, minorcode=x%x\n",
				bf_get_le32(lpfc_eqe_major_code, eqe),
				bf_get_le32(lpfc_eqe_minor_code, eqe));
		return;
	}
	/* Get the reference to the corresponding CQ */
	cqid = bf_get_le32(lpfc_eqe_resource_id, eqe);
	/* Next check for OAS */
	cq = phba->sli4_hba.oas_cq;
	if (unlikely(!cq)) {
		if (phba->sli.sli_flag & LPFC_SLI_ACTIVE)
			lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
					"9148 OAS completion queue "
					"does not exist\n");
		return;
	}
	if (unlikely(cqid != cq->queue_id)) {
		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
				"9149 Miss-matched fast-path compl "
				"queue id: eqcqid=%d, fcpcqid=%d\n",
				cqid, cq->queue_id);
		return;
	}
	/* Save EQ associated with this CQ */
	cq->assoc_qp = phba->sli4_hba.fof_eq;
	/* CQ work will be processed on CPU affinitized to this IRQ */
	if (!queue_work(phba->wq, &cq->irqwork))
		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
				"0367 Cannot schedule soft IRQ "
				"for CQ eqcqid=%d, cqid=%d on CPU %d\n",
				cqid, cq->queue_id, smp_processor_id());
}
/**
 * lpfc_sli4_fof_intr_handler - HBA interrupt handler to SLI-4 device
 * @irq: Interrupt number.
 * @dev_id: The device context pointer.
 *
 * This function is directly called from the PCI layer as an interrupt
 * service routine when device with SLI-4 interface spec is enabled with
 * MSI-X multi-message interrupt mode and there is a Flash Optimized Fabric
 * IOCB ring event in the HBA. However, when the device is enabled with either
 * MSI or Pin-IRQ interrupt mode, this function is called as part of the
 * device-level interrupt handler. When the PCI slot is in error recovery
 * or the HBA is undergoing initialization, the interrupt handler will not
 * process the interrupt. The Flash Optimized Fabric ring event are handled in
 * the intrrupt context. This function is called without any lock held.
 * It gets the hbalock to access and update SLI data structures. Note that,
 * the EQ to CQ are one-to-one map such that the EQ index is
 * equal to that of CQ index.
 *
 * This function returns IRQ_HANDLED when interrupt is handled else it
 * returns IRQ_NONE.
 **/
irqreturn_t
lpfc_sli4_fof_intr_handler(int irq, void *dev_id)
{
	struct lpfc_hba *phba;
	struct lpfc_hba_eq_hdl *hba_eq_hdl;
	struct lpfc_queue *eq;
	struct lpfc_eqe *eqe;
	unsigned long iflag;
	int ecount = 0;
	/* Get the driver's phba structure from the dev_id */
	hba_eq_hdl = (struct lpfc_hba_eq_hdl *)dev_id;
	phba = hba_eq_hdl->phba;
	if (unlikely(!phba))
		return IRQ_NONE;
	/* Get to the EQ struct associated with this vector */
	eq = phba->sli4_hba.fof_eq;
	if (unlikely(!eq))
		return IRQ_NONE;
	/* Check device state for handling interrupt */
	if (unlikely(lpfc_intr_state_check(phba))) {
		/* Check again for link_state with lock held */
		spin_lock_irqsave(&phba->hbalock, iflag);
		if (phba->link_state < LPFC_LINK_DOWN)
			/* Flush, clear interrupt, and rearm the EQ */
			lpfc_sli4_eq_flush(phba, eq);
		spin_unlock_irqrestore(&phba->hbalock, iflag);
		return IRQ_NONE;
	}
	/*
	 * Process all the event on FCP fast-path EQ
	 */
	while ((eqe = lpfc_sli4_eq_get(eq))) {
		lpfc_sli4_fof_handle_eqe(phba, eqe);
		if (!(++ecount % eq->entry_repost))
			break;
		eq->EQ_processed++;
	}
	/* Track the max number of EQEs processed in 1 intr */
	if (ecount > eq->EQ_max_eqe)
		eq->EQ_max_eqe = ecount;
	if (unlikely(ecount == 0)) {
		eq->EQ_no_entry++;
		if (phba->intr_type == MSIX)
			/* MSI-X treated interrupt served as no EQ share INT */
			lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
					"9145 MSI-X interrupt with no EQE\n");
		else {
			lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
					"9146 ISR interrupt with no EQE\n");
			/* Non MSI-X treated on interrupt as EQ share INT */
			return IRQ_NONE;
		}
	}
	/* Always clear and re-arm the fast-path EQ */
	phba->sli4_hba.sli4_eq_release(eq, LPFC_QUEUE_REARM);
	return IRQ_HANDLED;
}
/**
 * lpfc_sli4_hba_intr_handler - HBA interrupt handler to SLI-4 device
 * @irq: Interrupt number.
@@ -14522,13 +14347,6 @@ lpfc_sli4_intr_handler(int irq, void *dev_id)
			hba_handled |= true;
	}
	if (phba->cfg_fof) {
		hba_irq_rc = lpfc_sli4_fof_intr_handler(irq,
					&phba->sli4_hba.hba_eq_hdl[qidx]);
		if (hba_irq_rc == IRQ_HANDLED)
			hba_handled |= true;
	}
	return (hba_handled == true) ? IRQ_HANDLED : IRQ_NONE;
} /* lpfc_sli4_intr_handler */
Loading