queue->id, queue->head * GDMA_WQE_BU_SIZE, 1);
}
-void mana_gd_arm_cq(struct gdma_queue *cq)
+void mana_gd_ring_cq(struct gdma_queue *cq, u8 arm_bit)
{
struct gdma_context *gc = cq->gdma_dev->gdma_context;
u32 head = cq->head % (num_cqe << GDMA_CQE_OWNER_BITS);
mana_gd_ring_doorbell(gc, cq->gdma_dev->doorbell, cq->type, cq->id,
- head, SET_ARM_BIT);
+ head, arm_bit);
}
static void mana_gd_process_eqe(struct gdma_queue *eq)
struct gdma_queue *eq = arg;
struct gdma_context *gc;
struct gdma_eqe *eqe;
- unsigned int arm_bit;
u32 head, num_eqe;
int i;
eq->head++;
}
- /* Always rearm the EQ for HWC. For MANA, rearm it when NAPI is done. */
- if (mana_gd_is_hwc(eq->gdma_dev)) {
- arm_bit = SET_ARM_BIT;
- } else if (eq->eq.work_done < eq->eq.budget &&
- napi_complete_done(&eq->eq.napi, eq->eq.work_done)) {
- arm_bit = SET_ARM_BIT;
- } else {
- arm_bit = 0;
- }
-
head = eq->head % (num_eqe << GDMA_EQE_OWNER_BITS);
mana_gd_ring_doorbell(gc, eq->gdma_dev->doorbell, eq->type, eq->id,
- head, arm_bit);
-}
-
-static int mana_poll(struct napi_struct *napi, int budget)
-{
- struct gdma_queue *eq = container_of(napi, struct gdma_queue, eq.napi);
-
- eq->eq.work_done = 0;
- eq->eq.budget = budget;
-
- mana_gd_process_eq_events(eq);
-
- return min(eq->eq.work_done, budget);
-}
-
-static void mana_gd_schedule_napi(void *arg)
-{
- struct gdma_queue *eq = arg;
- struct napi_struct *napi;
-
- napi = &eq->eq.napi;
- napi_schedule_irqoff(napi);
+ head, SET_ARM_BIT);
}
static int mana_gd_register_irq(struct gdma_queue *queue,
const struct gdma_queue_spec *spec)
{
struct gdma_dev *gd = queue->gdma_dev;
- bool is_mana = mana_gd_is_mana(gd);
struct gdma_irq_context *gic;
struct gdma_context *gc;
struct gdma_resource *r;
gic = &gc->irq_contexts[msi_index];
- if (is_mana) {
- netif_napi_add(spec->eq.ndev, &queue->eq.napi, mana_poll,
- NAPI_POLL_WEIGHT);
- napi_enable(&queue->eq.napi);
- }
-
WARN_ON(gic->handler || gic->arg);
gic->arg = queue;
- if (is_mana)
- gic->handler = mana_gd_schedule_napi;
- else
- gic->handler = mana_gd_process_eq_events;
+ gic->handler = mana_gd_process_eq_events;
return 0;
}
mana_gd_deregiser_irq(queue);
- if (mana_gd_is_mana(queue->gdma_dev)) {
- napi_disable(&queue->eq.napi);
- netif_napi_del(&queue->eq.napi);
- }
-
if (queue->eq.disable_needed)
mana_gd_disable_queue(queue);
}
resp.hdr.status);
}
-static void mana_init_cqe_poll_buf(struct gdma_comp *cqe_poll_buf)
-{
- int i;
-
- for (i = 0; i < CQE_POLLING_BUFFER; i++)
- memset(&cqe_poll_buf[i], 0, sizeof(struct gdma_comp));
-}
-
static void mana_destroy_eq(struct gdma_context *gc,
struct mana_port_context *apc)
{
spec.eq.ndev = apc->ndev;
for (i = 0; i < apc->num_queues; i++) {
- mana_init_cqe_poll_buf(apc->eqs[i].cqe_poll);
-
err = mana_gd_create_mana_eq(gd, &spec, &apc->eqs[i].eq);
if (err)
goto out;
static void mana_poll_tx_cq(struct mana_cq *cq)
{
- struct gdma_queue *gdma_eq = cq->gdma_cq->cq.parent;
struct gdma_comp *completions = cq->gdma_comp_buf;
struct gdma_posted_wqe_info *wqe_info;
unsigned int pkt_transmitted = 0;
comp_read = mana_gd_poll_cq(cq->gdma_cq, completions,
CQE_POLLING_BUFFER);
+ if (comp_read < 1)
+ return;
+
for (i = 0; i < comp_read; i++) {
struct mana_tx_comp_oob *cqe_oob;
mana_unmap_skb(skb, apc);
- napi_consume_skb(skb, gdma_eq->eq.budget);
+ napi_consume_skb(skb, cq->budget);
pkt_transmitted++;
}
if (atomic_sub_return(pkt_transmitted, &txq->pending_sends) < 0)
WARN_ON_ONCE(1);
+
+ cq->work_done = pkt_transmitted;
}
static void mana_post_pkt_rxq(struct mana_rxq *rxq)
struct mana_stats *rx_stats = &rxq->stats;
struct net_device *ndev = rxq->ndev;
uint pkt_len = cqe->ppi[0].pkt_len;
- struct mana_port_context *apc;
u16 rxq_idx = rxq->rxq_idx;
struct napi_struct *napi;
- struct gdma_queue *eq;
struct sk_buff *skb;
u32 hash_value;
- apc = netdev_priv(ndev);
- eq = apc->eqs[rxq_idx].eq;
- eq->eq.work_done++;
- napi = &eq->eq.napi;
+ rxq->rx_cq.work_done++;
+ napi = &rxq->rx_cq.napi;
if (!buf_va) {
++ndev->stats.rx_dropped;
static void mana_cq_handler(void *context, struct gdma_queue *gdma_queue)
{
struct mana_cq *cq = context;
+ u8 arm_bit;
WARN_ON_ONCE(cq->gdma_cq != gdma_queue);
else
mana_poll_tx_cq(cq);
- mana_gd_arm_cq(gdma_queue);
+ if (cq->work_done < cq->budget &&
+ napi_complete_done(&cq->napi, cq->work_done)) {
+ arm_bit = SET_ARM_BIT;
+ } else {
+ arm_bit = 0;
+ }
+
+ mana_gd_ring_cq(gdma_queue, arm_bit);
+}
+
+static int mana_poll(struct napi_struct *napi, int budget)
+{
+ struct mana_cq *cq = container_of(napi, struct mana_cq, napi);
+
+ cq->work_done = 0;
+ cq->budget = budget;
+
+ mana_cq_handler(cq, cq->gdma_cq);
+
+ return min(cq->work_done, budget);
+}
+
+static void mana_schedule_napi(void *context, struct gdma_queue *gdma_queue)
+{
+ struct mana_cq *cq = context;
+
+ napi_schedule_irqoff(&cq->napi);
}
static void mana_deinit_cq(struct mana_port_context *apc, struct mana_cq *cq)
static void mana_destroy_txq(struct mana_port_context *apc)
{
+ struct napi_struct *napi;
int i;
if (!apc->tx_qp)
return;
for (i = 0; i < apc->num_queues; i++) {
+ napi = &apc->tx_qp[i].tx_cq.napi;
+ napi_synchronize(napi);
+ napi_disable(napi);
+ netif_napi_del(napi);
+
mana_destroy_wq_obj(apc, GDMA_SQ, apc->tx_qp[i].tx_object);
mana_deinit_cq(apc, &apc->tx_qp[i].tx_cq);
/* Create SQ's CQ */
cq = &apc->tx_qp[i].tx_cq;
- cq->gdma_comp_buf = apc->eqs[i].cqe_poll;
cq->type = MANA_CQ_TYPE_TX;
cq->txq = txq;
spec.type = GDMA_CQ;
spec.monitor_avl_buf = false;
spec.queue_size = cq_size;
- spec.cq.callback = mana_cq_handler;
+ spec.cq.callback = mana_schedule_napi;
spec.cq.parent_eq = apc->eqs[i].eq;
spec.cq.context = cq;
err = mana_gd_create_mana_wq_cq(gd, &spec, &cq->gdma_cq);
gc->cq_table[cq->gdma_id] = cq->gdma_cq;
- mana_gd_arm_cq(cq->gdma_cq);
+ netif_tx_napi_add(net, &cq->napi, mana_poll, NAPI_POLL_WEIGHT);
+ napi_enable(&cq->napi);
+
+ mana_gd_ring_cq(cq->gdma_cq, SET_ARM_BIT);
}
return 0;
return err;
}
-static void mana_napi_sync_for_rx(struct mana_rxq *rxq)
-{
- struct net_device *ndev = rxq->ndev;
- struct mana_port_context *apc;
- u16 rxq_idx = rxq->rxq_idx;
- struct napi_struct *napi;
- struct gdma_queue *eq;
-
- apc = netdev_priv(ndev);
- eq = apc->eqs[rxq_idx].eq;
- napi = &eq->eq.napi;
-
- napi_synchronize(napi);
-}
-
static void mana_destroy_rxq(struct mana_port_context *apc,
struct mana_rxq *rxq, bool validate_state)
struct gdma_context *gc = apc->ac->gdma_dev->gdma_context;
struct mana_recv_buf_oob *rx_oob;
struct device *dev = gc->dev;
+ struct napi_struct *napi;
int i;
if (!rxq)
return;
+ napi = &rxq->rx_cq.napi;
+
if (validate_state)
- mana_napi_sync_for_rx(rxq);
+ napi_synchronize(napi);
+
+ napi_disable(napi);
+ netif_napi_del(napi);
mana_destroy_wq_obj(apc, GDMA_RQ, rxq->rxobj);
/* Create RQ's CQ */
cq = &rxq->rx_cq;
- cq->gdma_comp_buf = eq->cqe_poll;
cq->type = MANA_CQ_TYPE_RX;
cq->rxq = rxq;
spec.type = GDMA_CQ;
spec.monitor_avl_buf = false;
spec.queue_size = cq_size;
- spec.cq.callback = mana_cq_handler;
+ spec.cq.callback = mana_schedule_napi;
spec.cq.parent_eq = eq->eq;
spec.cq.context = cq;
err = mana_gd_create_mana_wq_cq(gd, &spec, &cq->gdma_cq);
gc->cq_table[cq->gdma_id] = cq->gdma_cq;
- mana_gd_arm_cq(cq->gdma_cq);
+ netif_napi_add(ndev, &cq->napi, mana_poll, 1);
+ napi_enable(&cq->napi);
+
+ mana_gd_ring_cq(cq->gdma_cq, SET_ARM_BIT);
out:
if (!err)
return rxq;