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