static int enic_poll(struct napi_struct *napi, int budget) { struct enic *enic = container_of(napi, struct enic, napi); struct net_device *netdev = enic->netdev; unsigned int rq_work_to_do = budget; unsigned int wq_work_to_do = -1; /* no limit */ unsigned int work_done, rq_work_done, wq_work_done; /* Service RQ (first) and WQ */ rq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ], rq_work_to_do, enic_rq_service, NULL); wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ], wq_work_to_do, enic_wq_service, NULL); /* Accumulate intr event credits for this polling * cycle. An intr event is the completion of a * a WQ or RQ packet. */ work_done = rq_work_done + wq_work_done; if (work_done > 0) vnic_intr_return_credits(&enic->intr[ENIC_INTX_WQ_RQ], work_done, 0 /* don't unmask intr */, 0 /* don't reset intr timer */); if (rq_work_done > 0) { /* Replenish RQ */ vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf); } else { /* If no work done, flush all LROs and exit polling */ if (netdev->features & NETIF_F_LRO) lro_flush_all(&enic->lro_mgr); netif_rx_complete(napi); vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]); } return rq_work_done; }
static int enic_stop(struct net_device *netdev) { struct enic *enic = netdev_priv(netdev); unsigned int i; int err; del_timer_sync(&enic->notify_timer); spin_lock(&enic->devcmd_lock); vnic_dev_disable(enic->vdev); spin_unlock(&enic->devcmd_lock); napi_disable(&enic->napi); netif_stop_queue(netdev); for (i = 0; i < enic->intr_count; i++) vnic_intr_mask(&enic->intr[i]); for (i = 0; i < enic->wq_count; i++) { err = vnic_wq_disable(&enic->wq[i]); if (err) return err; } for (i = 0; i < enic->rq_count; i++) { err = vnic_rq_disable(&enic->rq[i]); if (err) return err; } spin_lock(&enic->devcmd_lock); vnic_dev_notify_unset(enic->vdev); spin_unlock(&enic->devcmd_lock); enic_free_intr(enic); (void)vnic_cq_service(&enic->cq[ENIC_CQ_RQ], -1, enic_rq_service_drop, NULL); (void)vnic_cq_service(&enic->cq[ENIC_CQ_WQ], -1, enic_wq_service, NULL); for (i = 0; i < enic->wq_count; i++) vnic_wq_clean(&enic->wq[i], enic_free_wq_buf); for (i = 0; i < enic->rq_count; i++) vnic_rq_clean(&enic->rq[i], enic_free_rq_buf); for (i = 0; i < enic->cq_count; i++) vnic_cq_clean(&enic->cq[i]); for (i = 0; i < enic->intr_count; i++) vnic_intr_clean(&enic->intr[i]); return 0; }
unsigned int enic_cleanup_wq(struct enic *enic, struct vnic_wq *wq) { unsigned int cq = enic_cq_wq(enic, wq->index); /* Return the work done */ return vnic_cq_service(&enic->cq[cq], -1 /*wq_work_to_do*/, enic_wq_service, NULL); }
static int enic_poll(struct napi_struct *napi, int budget) { struct enic *enic = container_of(napi, struct enic, napi); struct net_device *netdev = enic->netdev; unsigned int rq_work_to_do = budget; unsigned int wq_work_to_do = -1; unsigned int work_done, rq_work_done, wq_work_done; rq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_RQ], rq_work_to_do, enic_rq_service, NULL); wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ], wq_work_to_do, enic_wq_service, NULL); work_done = rq_work_done + wq_work_done; if (work_done > 0) vnic_intr_return_credits(&enic->intr[ENIC_INTX_WQ_RQ], work_done, 0 , 0 ); if (rq_work_done > 0) { vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf); } else { if (netdev->features & NETIF_F_LRO) lro_flush_all(&enic->lro_mgr); napi_complete(napi); vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); } return rq_work_done; }
int fnic_wq_cmpl_handler(struct fnic *fnic, int work_to_do) { unsigned int wq_work_done = 0; unsigned int i; for (i = 0; i < fnic->raw_wq_count; i++) { wq_work_done += vnic_cq_service(&fnic->cq[fnic->rq_count+i], work_to_do, fnic_wq_cmpl_handler_cont, NULL); } return wq_work_done; }
static irqreturn_t enic_isr_msix_wq(int irq, void *data) { struct enic *enic = data; unsigned int wq_work_to_do = -1; unsigned int wq_work_done; wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ], wq_work_to_do, enic_wq_service, NULL); vnic_intr_return_credits(&enic->intr[ENIC_MSIX_WQ], wq_work_done, 1 , 1 ); return IRQ_HANDLED; }
static irqreturn_t enic_isr_msix_wq(int irq, void *data) { struct enic *enic = data; unsigned int wq_work_to_do = -1; /* no limit */ unsigned int wq_work_done; wq_work_done = vnic_cq_service(&enic->cq[ENIC_CQ_WQ], wq_work_to_do, enic_wq_service, NULL); vnic_intr_return_credits(&enic->intr[ENIC_MSIX_WQ], wq_work_done, 1 /* unmask intr */, 1 /* reset intr timer */); return IRQ_HANDLED; }
int enic_poll(struct vnic_rq *rq, struct rte_mbuf **rx_pkts, unsigned int budget, unsigned int *work_done) { struct enic *enic = vnic_dev_priv(rq->vdev); unsigned int cq = enic_cq_rq(enic, rq->index); int err = 0; *work_done = vnic_cq_service(&enic->cq[cq], budget, enic_rq_service, (void *)rx_pkts); if (*work_done) { vnic_rq_fill(rq, enic_rq_alloc_buf); /* Need at least one buffer on ring to get going */ if (vnic_rq_desc_used(rq) == 0) { dev_err(enic, "Unable to alloc receive buffers\n"); err = -1; } } return err; }
int fnic_rq_cmpl_handler(struct fnic *fnic, int rq_work_to_do) { unsigned int tot_rq_work_done = 0, cur_work_done; unsigned int i; int err; for (i = 0; i < fnic->rq_count; i++) { cur_work_done = vnic_cq_service(&fnic->cq[i], rq_work_to_do, fnic_rq_cmpl_handler_cont, NULL); if (cur_work_done) { err = vnic_rq_fill(&fnic->rq[i], fnic_alloc_rq_frame); if (err) shost_printk(KERN_ERR, fnic->lport->host, "fnic_alloc_rq_frame cant alloc" " frame\n"); } tot_rq_work_done += cur_work_done; } return tot_rq_work_done; }