Exemplo n.º 1
0
/* SP - CREQ Completion handlers */
static void bnxt_qplib_service_creq(unsigned long data)
{
	struct bnxt_qplib_rcfw *rcfw = (struct bnxt_qplib_rcfw *)data;
	struct bnxt_qplib_hwq *creq = &rcfw->creq;
	struct creq_base *creqe, **creq_ptr;
	u32 sw_cons, raw_cons;
	unsigned long flags;
	u32 type, budget = CREQ_ENTRY_POLL_BUDGET;

	/* Service the CREQ until budget is over */
	spin_lock_irqsave(&creq->lock, flags);
	raw_cons = creq->cons;
	while (budget > 0) {
		sw_cons = HWQ_CMP(raw_cons, creq);
		creq_ptr = (struct creq_base **)creq->pbl_ptr;
		creqe = &creq_ptr[get_creq_pg(sw_cons)][get_creq_idx(sw_cons)];
		if (!CREQ_CMP_VALID(creqe, raw_cons, creq->max_elements))
			break;
		/* The valid test of the entry must be done first before
		 * reading any further.
		 */
		dma_rmb();

		type = creqe->type & CREQ_BASE_TYPE_MASK;
		switch (type) {
		case CREQ_BASE_TYPE_QP_EVENT:
			bnxt_qplib_process_qp_event
				(rcfw, (struct creq_qp_event *)creqe);
			rcfw->creq_qp_event_processed++;
			break;
		case CREQ_BASE_TYPE_FUNC_EVENT:
			if (!bnxt_qplib_process_func_event
			    (rcfw, (struct creq_func_event *)creqe))
				rcfw->creq_func_event_processed++;
			else
				dev_warn
				(&rcfw->pdev->dev, "QPLIB:aeqe:%#x Not handled",
				 type);
			break;
		default:
			dev_warn(&rcfw->pdev->dev, "QPLIB: creqe with ");
			dev_warn(&rcfw->pdev->dev,
				 "QPLIB: op_event = 0x%x not handled", type);
			break;
		}
		raw_cons++;
		budget--;
	}

	if (creq->cons != raw_cons) {
		creq->cons = raw_cons;
		CREQ_DB_REARM(rcfw->creq_bar_reg_iomem, raw_cons,
			      creq->max_elements);
	}
	spin_unlock_irqrestore(&creq->lock, flags);
}
Exemplo n.º 2
0
static irqreturn_t bnxt_qplib_creq_irq(int irq, void *dev_instance)
{
	struct bnxt_qplib_rcfw *rcfw = dev_instance;
	struct bnxt_qplib_hwq *creq = &rcfw->creq;
	struct creq_base **creq_ptr;
	u32 sw_cons;

	/* Prefetch the CREQ element */
	sw_cons = HWQ_CMP(creq->cons, creq);
	creq_ptr = (struct creq_base **)rcfw->creq.pbl_ptr;
	prefetch(&creq_ptr[get_creq_pg(sw_cons)][get_creq_idx(sw_cons)]);

	tasklet_schedule(&rcfw->worker);

	return IRQ_HANDLED;
}