/* 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); }
int bnxt_qplib_rcfw_start_irq(struct bnxt_qplib_rcfw *rcfw, int msix_vector, bool need_init) { int rc; if (rcfw->requested) return -EFAULT; rcfw->vector = msix_vector; if (need_init) tasklet_init(&rcfw->worker, bnxt_qplib_service_creq, (unsigned long)rcfw); else tasklet_enable(&rcfw->worker); rc = request_irq(rcfw->vector, bnxt_qplib_creq_irq, 0, "bnxt_qplib_creq", rcfw); if (rc) return rc; rcfw->requested = true; CREQ_DB_REARM(rcfw->creq_bar_reg_iomem, rcfw->creq.cons, rcfw->creq.max_elements); return 0; }
int bnxt_qplib_enable_rcfw_channel(struct pci_dev *pdev, struct bnxt_qplib_rcfw *rcfw, int msix_vector, int cp_bar_reg_off, int virt_fn, int (*aeq_handler)(struct bnxt_qplib_rcfw *, struct creq_func_event *)) { resource_size_t res_base; struct cmdq_init init; u16 bmap_size; int rc; /* General */ rcfw->seq_num = 0; rcfw->flags = FIRMWARE_FIRST_FLAG; bmap_size = BITS_TO_LONGS(RCFW_MAX_OUTSTANDING_CMD * sizeof(unsigned long)); rcfw->cmdq_bitmap = kzalloc(bmap_size, GFP_KERNEL); if (!rcfw->cmdq_bitmap) return -ENOMEM; rcfw->bmap_size = bmap_size; /* CMDQ */ rcfw->cmdq_bar_reg = RCFW_COMM_PCI_BAR_REGION; res_base = pci_resource_start(pdev, rcfw->cmdq_bar_reg); if (!res_base) return -ENOMEM; rcfw->cmdq_bar_reg_iomem = ioremap_nocache(res_base + RCFW_COMM_BASE_OFFSET, RCFW_COMM_SIZE); if (!rcfw->cmdq_bar_reg_iomem) { dev_err(&rcfw->pdev->dev, "QPLIB: CMDQ BAR region %d mapping failed", rcfw->cmdq_bar_reg); return -ENOMEM; } rcfw->cmdq_bar_reg_prod_off = virt_fn ? RCFW_VF_COMM_PROD_OFFSET : RCFW_PF_COMM_PROD_OFFSET; rcfw->cmdq_bar_reg_trig_off = RCFW_COMM_TRIG_OFFSET; /* CREQ */ rcfw->creq_bar_reg = RCFW_COMM_CONS_PCI_BAR_REGION; res_base = pci_resource_start(pdev, rcfw->creq_bar_reg); if (!res_base) dev_err(&rcfw->pdev->dev, "QPLIB: CREQ BAR region %d resc start is 0!", rcfw->creq_bar_reg); rcfw->creq_bar_reg_iomem = ioremap_nocache(res_base + cp_bar_reg_off, 4); if (!rcfw->creq_bar_reg_iomem) { dev_err(&rcfw->pdev->dev, "QPLIB: CREQ BAR region %d mapping failed", rcfw->creq_bar_reg); return -ENOMEM; } rcfw->creq_qp_event_processed = 0; rcfw->creq_func_event_processed = 0; rcfw->vector = msix_vector; if (aeq_handler) rcfw->aeq_handler = aeq_handler; tasklet_init(&rcfw->worker, bnxt_qplib_service_creq, (unsigned long)rcfw); rcfw->requested = false; rc = request_irq(rcfw->vector, bnxt_qplib_creq_irq, 0, "bnxt_qplib_creq", rcfw); if (rc) { dev_err(&rcfw->pdev->dev, "QPLIB: Failed to request IRQ for CREQ rc = 0x%x", rc); bnxt_qplib_disable_rcfw_channel(rcfw); return rc; } rcfw->requested = true; init_waitqueue_head(&rcfw->waitq); CREQ_DB_REARM(rcfw->creq_bar_reg_iomem, 0, rcfw->creq.max_elements); init.cmdq_pbl = cpu_to_le64(rcfw->cmdq.pbl[PBL_LVL_0].pg_map_arr[0]); init.cmdq_size_cmdq_lvl = cpu_to_le16( ((BNXT_QPLIB_CMDQE_MAX_CNT << CMDQ_INIT_CMDQ_SIZE_SFT) & CMDQ_INIT_CMDQ_SIZE_MASK) | ((rcfw->cmdq.level << CMDQ_INIT_CMDQ_LVL_SFT) & CMDQ_INIT_CMDQ_LVL_MASK)); init.creq_ring_id = cpu_to_le16(rcfw->creq_ring_id); /* Write to the Bono mailbox register */ __iowrite32_copy(rcfw->cmdq_bar_reg_iomem, &init, sizeof(init) / 4); return 0; }