提交 0f3154e6 编写于 作者: S Shannon Nelson 提交者: David S. Miller

ionic: Add Tx and Rx handling

Add both the Tx and Rx queue setup and handling.  The related
stats display comes later.  Instead of using the generic napi
routines used by the slow-path commands, the Tx and Rx paths
are simplified and inlined in one file in order to get better
compiler optimizations.
Signed-off-by: NShannon Nelson <snelson@pensando.io>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 4d03e00a
...@@ -4,4 +4,5 @@ ...@@ -4,4 +4,5 @@
obj-$(CONFIG_IONIC) := ionic.o obj-$(CONFIG_IONIC) := ionic.o
ionic-y := ionic_main.o ionic_bus_pci.o ionic_devlink.o ionic_dev.o \ ionic-y := ionic_main.o ionic_bus_pci.o ionic_devlink.o ionic_dev.o \
ionic_debugfs.o ionic_lif.o ionic_rx_filter.o ionic_ethtool.o ionic_debugfs.o ionic_lif.o ionic_rx_filter.o ionic_ethtool.o \
ionic_txrx.o
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "ionic.h" #include "ionic.h"
#include "ionic_bus.h" #include "ionic_bus.h"
#include "ionic_lif.h" #include "ionic_lif.h"
#include "ionic_txrx.h"
#include "ionic_ethtool.h" #include "ionic_ethtool.h"
#include "ionic_debugfs.h" #include "ionic_debugfs.h"
...@@ -80,11 +81,17 @@ static void ionic_link_status_check(struct ionic_lif *lif) ...@@ -80,11 +81,17 @@ static void ionic_link_status_check(struct ionic_lif *lif)
netdev_info(netdev, "Link up - %d Gbps\n", netdev_info(netdev, "Link up - %d Gbps\n",
le32_to_cpu(lif->info->status.link_speed) / 1000); le32_to_cpu(lif->info->status.link_speed) / 1000);
if (test_bit(IONIC_LIF_UP, lif->state)) {
netif_tx_wake_all_queues(lif->netdev);
netif_carrier_on(netdev);
}
} else { } else {
netdev_info(netdev, "Link down\n"); netdev_info(netdev, "Link down\n");
/* carrier off first to avoid watchdog timeout */ /* carrier off first to avoid watchdog timeout */
netif_carrier_off(netdev); netif_carrier_off(netdev);
if (test_bit(IONIC_LIF_UP, lif->state))
netif_tx_stop_all_queues(netdev);
} }
link_out: link_out:
...@@ -163,6 +170,77 @@ static void ionic_intr_free(struct ionic_lif *lif, int index) ...@@ -163,6 +170,77 @@ static void ionic_intr_free(struct ionic_lif *lif, int index)
clear_bit(index, lif->ionic->intrs); clear_bit(index, lif->ionic->intrs);
} }
static int ionic_qcq_enable(struct ionic_qcq *qcq)
{
struct ionic_queue *q = &qcq->q;
struct ionic_lif *lif = q->lif;
struct ionic_dev *idev;
struct device *dev;
struct ionic_admin_ctx ctx = {
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
.cmd.q_control = {
.opcode = IONIC_CMD_Q_CONTROL,
.lif_index = cpu_to_le16(lif->index),
.type = q->type,
.index = cpu_to_le32(q->index),
.oper = IONIC_Q_ENABLE,
},
};
idev = &lif->ionic->idev;
dev = lif->ionic->dev;
dev_dbg(dev, "q_enable.index %d q_enable.qtype %d\n",
ctx.cmd.q_control.index, ctx.cmd.q_control.type);
if (qcq->flags & IONIC_QCQ_F_INTR) {
irq_set_affinity_hint(qcq->intr.vector,
&qcq->intr.affinity_mask);
napi_enable(&qcq->napi);
ionic_intr_clean(idev->intr_ctrl, qcq->intr.index);
ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
IONIC_INTR_MASK_CLEAR);
}
return ionic_adminq_post_wait(lif, &ctx);
}
static int ionic_qcq_disable(struct ionic_qcq *qcq)
{
struct ionic_queue *q = &qcq->q;
struct ionic_lif *lif = q->lif;
struct ionic_dev *idev;
struct device *dev;
struct ionic_admin_ctx ctx = {
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
.cmd.q_control = {
.opcode = IONIC_CMD_Q_CONTROL,
.lif_index = cpu_to_le16(lif->index),
.type = q->type,
.index = cpu_to_le32(q->index),
.oper = IONIC_Q_DISABLE,
},
};
idev = &lif->ionic->idev;
dev = lif->ionic->dev;
dev_dbg(dev, "q_disable.index %d q_disable.qtype %d\n",
ctx.cmd.q_control.index, ctx.cmd.q_control.type);
if (qcq->flags & IONIC_QCQ_F_INTR) {
ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
IONIC_INTR_MASK_SET);
synchronize_irq(qcq->intr.vector);
irq_set_affinity_hint(qcq->intr.vector, NULL);
napi_disable(&qcq->napi);
}
return ionic_adminq_post_wait(lif, &ctx);
}
static void ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq) static void ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)
{ {
struct ionic_dev *idev = &lif->ionic->idev; struct ionic_dev *idev = &lif->ionic->idev;
...@@ -209,6 +287,9 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq) ...@@ -209,6 +287,9 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
static void ionic_qcqs_free(struct ionic_lif *lif) static void ionic_qcqs_free(struct ionic_lif *lif)
{ {
struct device *dev = lif->ionic->dev;
unsigned int i;
if (lif->notifyqcq) { if (lif->notifyqcq) {
ionic_qcq_free(lif, lif->notifyqcq); ionic_qcq_free(lif, lif->notifyqcq);
lif->notifyqcq = NULL; lif->notifyqcq = NULL;
...@@ -218,6 +299,20 @@ static void ionic_qcqs_free(struct ionic_lif *lif) ...@@ -218,6 +299,20 @@ static void ionic_qcqs_free(struct ionic_lif *lif)
ionic_qcq_free(lif, lif->adminqcq); ionic_qcq_free(lif, lif->adminqcq);
lif->adminqcq = NULL; lif->adminqcq = NULL;
} }
for (i = 0; i < lif->nxqs; i++)
if (lif->rxqcqs[i].stats)
devm_kfree(dev, lif->rxqcqs[i].stats);
devm_kfree(dev, lif->rxqcqs);
lif->rxqcqs = NULL;
for (i = 0; i < lif->nxqs; i++)
if (lif->txqcqs[i].stats)
devm_kfree(dev, lif->txqcqs[i].stats);
devm_kfree(dev, lif->txqcqs);
lif->txqcqs = NULL;
} }
static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq, static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq,
...@@ -373,8 +468,11 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type, ...@@ -373,8 +468,11 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
static int ionic_qcqs_alloc(struct ionic_lif *lif) static int ionic_qcqs_alloc(struct ionic_lif *lif)
{ {
struct device *dev = lif->ionic->dev;
unsigned int q_list_size;
unsigned int flags; unsigned int flags;
int err; int err;
int i;
flags = IONIC_QCQ_F_INTR; flags = IONIC_QCQ_F_INTR;
err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags, err = ionic_qcq_alloc(lif, IONIC_QTYPE_ADMINQ, 0, "admin", flags,
...@@ -399,8 +497,49 @@ static int ionic_qcqs_alloc(struct ionic_lif *lif) ...@@ -399,8 +497,49 @@ static int ionic_qcqs_alloc(struct ionic_lif *lif)
ionic_link_qcq_interrupts(lif->adminqcq, lif->notifyqcq); ionic_link_qcq_interrupts(lif->adminqcq, lif->notifyqcq);
} }
q_list_size = sizeof(*lif->txqcqs) * lif->nxqs;
err = -ENOMEM;
lif->txqcqs = devm_kzalloc(dev, q_list_size, GFP_KERNEL);
if (!lif->txqcqs)
goto err_out_free_notifyqcq;
for (i = 0; i < lif->nxqs; i++) {
lif->txqcqs[i].stats = devm_kzalloc(dev,
sizeof(struct ionic_q_stats),
GFP_KERNEL);
if (!lif->txqcqs[i].stats)
goto err_out_free_tx_stats;
}
lif->rxqcqs = devm_kzalloc(dev, q_list_size, GFP_KERNEL);
if (!lif->rxqcqs)
goto err_out_free_tx_stats;
for (i = 0; i < lif->nxqs; i++) {
lif->rxqcqs[i].stats = devm_kzalloc(dev,
sizeof(struct ionic_q_stats),
GFP_KERNEL);
if (!lif->rxqcqs[i].stats)
goto err_out_free_rx_stats;
}
return 0; return 0;
err_out_free_rx_stats:
for (i = 0; i < lif->nxqs; i++)
if (lif->rxqcqs[i].stats)
devm_kfree(dev, lif->rxqcqs[i].stats);
devm_kfree(dev, lif->rxqcqs);
lif->rxqcqs = NULL;
err_out_free_tx_stats:
for (i = 0; i < lif->nxqs; i++)
if (lif->txqcqs[i].stats)
devm_kfree(dev, lif->txqcqs[i].stats);
devm_kfree(dev, lif->txqcqs);
lif->txqcqs = NULL;
err_out_free_notifyqcq:
if (lif->notifyqcq) {
ionic_qcq_free(lif, lif->notifyqcq);
lif->notifyqcq = NULL;
}
err_out_free_adminqcq: err_out_free_adminqcq:
ionic_qcq_free(lif, lif->adminqcq); ionic_qcq_free(lif, lif->adminqcq);
lif->adminqcq = NULL; lif->adminqcq = NULL;
...@@ -408,6 +547,107 @@ static int ionic_qcqs_alloc(struct ionic_lif *lif) ...@@ -408,6 +547,107 @@ static int ionic_qcqs_alloc(struct ionic_lif *lif)
return err; return err;
} }
static int ionic_lif_txq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
{
struct device *dev = lif->ionic->dev;
struct ionic_queue *q = &qcq->q;
struct ionic_cq *cq = &qcq->cq;
struct ionic_admin_ctx ctx = {
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
.cmd.q_init = {
.opcode = IONIC_CMD_Q_INIT,
.lif_index = cpu_to_le16(lif->index),
.type = q->type,
.index = cpu_to_le32(q->index),
.flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
IONIC_QINIT_F_SG),
.intr_index = cpu_to_le16(lif->rxqcqs[q->index].qcq->intr.index),
.pid = cpu_to_le16(q->pid),
.ring_size = ilog2(q->num_descs),
.ring_base = cpu_to_le64(q->base_pa),
.cq_ring_base = cpu_to_le64(cq->base_pa),
.sg_ring_base = cpu_to_le64(q->sg_base_pa),
},
};
int err;
dev_dbg(dev, "txq_init.pid %d\n", ctx.cmd.q_init.pid);
dev_dbg(dev, "txq_init.index %d\n", ctx.cmd.q_init.index);
dev_dbg(dev, "txq_init.ring_base 0x%llx\n", ctx.cmd.q_init.ring_base);
dev_dbg(dev, "txq_init.ring_size %d\n", ctx.cmd.q_init.ring_size);
err = ionic_adminq_post_wait(lif, &ctx);
if (err)
return err;
q->hw_type = ctx.comp.q_init.hw_type;
q->hw_index = le32_to_cpu(ctx.comp.q_init.hw_index);
q->dbval = IONIC_DBELL_QID(q->hw_index);
dev_dbg(dev, "txq->hw_type %d\n", q->hw_type);
dev_dbg(dev, "txq->hw_index %d\n", q->hw_index);
qcq->flags |= IONIC_QCQ_F_INITED;
ionic_debugfs_add_qcq(lif, qcq);
return 0;
}
static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
{
struct device *dev = lif->ionic->dev;
struct ionic_queue *q = &qcq->q;
struct ionic_cq *cq = &qcq->cq;
struct ionic_admin_ctx ctx = {
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
.cmd.q_init = {
.opcode = IONIC_CMD_Q_INIT,
.lif_index = cpu_to_le16(lif->index),
.type = q->type,
.index = cpu_to_le32(q->index),
.flags = cpu_to_le16(IONIC_QINIT_F_IRQ),
.intr_index = cpu_to_le16(cq->bound_intr->index),
.pid = cpu_to_le16(q->pid),
.ring_size = ilog2(q->num_descs),
.ring_base = cpu_to_le64(q->base_pa),
.cq_ring_base = cpu_to_le64(cq->base_pa),
},
};
int err;
dev_dbg(dev, "rxq_init.pid %d\n", ctx.cmd.q_init.pid);
dev_dbg(dev, "rxq_init.index %d\n", ctx.cmd.q_init.index);
dev_dbg(dev, "rxq_init.ring_base 0x%llx\n", ctx.cmd.q_init.ring_base);
dev_dbg(dev, "rxq_init.ring_size %d\n", ctx.cmd.q_init.ring_size);
err = ionic_adminq_post_wait(lif, &ctx);
if (err)
return err;
q->hw_type = ctx.comp.q_init.hw_type;
q->hw_index = le32_to_cpu(ctx.comp.q_init.hw_index);
q->dbval = IONIC_DBELL_QID(q->hw_index);
dev_dbg(dev, "rxq->hw_type %d\n", q->hw_type);
dev_dbg(dev, "rxq->hw_index %d\n", q->hw_index);
netif_napi_add(lif->netdev, &qcq->napi, ionic_rx_napi,
NAPI_POLL_WEIGHT);
err = ionic_request_irq(lif, qcq);
if (err) {
netif_napi_del(&qcq->napi);
return err;
}
qcq->flags |= IONIC_QCQ_F_INITED;
ionic_debugfs_add_qcq(lif, qcq);
return 0;
}
static bool ionic_notifyq_service(struct ionic_cq *cq, static bool ionic_notifyq_service(struct ionic_cq *cq,
struct ionic_cq_info *cq_info) struct ionic_cq_info *cq_info)
{ {
...@@ -1075,17 +1315,180 @@ static int ionic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, ...@@ -1075,17 +1315,180 @@ static int ionic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto,
return ionic_adminq_post_wait(lif, &ctx); return ionic_adminq_post_wait(lif, &ctx);
} }
static void ionic_txrx_disable(struct ionic_lif *lif)
{
unsigned int i;
for (i = 0; i < lif->nxqs; i++) {
ionic_qcq_disable(lif->txqcqs[i].qcq);
ionic_qcq_disable(lif->rxqcqs[i].qcq);
}
}
static void ionic_txrx_deinit(struct ionic_lif *lif)
{
unsigned int i;
for (i = 0; i < lif->nxqs; i++) {
ionic_lif_qcq_deinit(lif, lif->txqcqs[i].qcq);
ionic_tx_flush(&lif->txqcqs[i].qcq->cq);
ionic_lif_qcq_deinit(lif, lif->rxqcqs[i].qcq);
ionic_rx_flush(&lif->rxqcqs[i].qcq->cq);
ionic_rx_empty(&lif->rxqcqs[i].qcq->q);
}
}
static void ionic_txrx_free(struct ionic_lif *lif)
{
unsigned int i;
for (i = 0; i < lif->nxqs; i++) {
ionic_qcq_free(lif, lif->txqcqs[i].qcq);
lif->txqcqs[i].qcq = NULL;
ionic_qcq_free(lif, lif->rxqcqs[i].qcq);
lif->rxqcqs[i].qcq = NULL;
}
}
static int ionic_txrx_alloc(struct ionic_lif *lif)
{
unsigned int flags;
unsigned int i;
int err = 0;
flags = IONIC_QCQ_F_TX_STATS | IONIC_QCQ_F_SG;
for (i = 0; i < lif->nxqs; i++) {
err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, i, "tx", flags,
lif->ntxq_descs,
sizeof(struct ionic_txq_desc),
sizeof(struct ionic_txq_comp),
sizeof(struct ionic_txq_sg_desc),
lif->kern_pid, &lif->txqcqs[i].qcq);
if (err)
goto err_out;
lif->txqcqs[i].qcq->stats = lif->txqcqs[i].stats;
}
flags = IONIC_QCQ_F_RX_STATS | IONIC_QCQ_F_INTR;
for (i = 0; i < lif->nxqs; i++) {
err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags,
lif->nrxq_descs,
sizeof(struct ionic_rxq_desc),
sizeof(struct ionic_rxq_comp),
0, lif->kern_pid, &lif->rxqcqs[i].qcq);
if (err)
goto err_out;
lif->rxqcqs[i].qcq->stats = lif->rxqcqs[i].stats;
ionic_link_qcq_interrupts(lif->rxqcqs[i].qcq,
lif->txqcqs[i].qcq);
}
return 0;
err_out:
ionic_txrx_free(lif);
return err;
}
static int ionic_txrx_init(struct ionic_lif *lif)
{
unsigned int i;
int err;
for (i = 0; i < lif->nxqs; i++) {
err = ionic_lif_txq_init(lif, lif->txqcqs[i].qcq);
if (err)
goto err_out;
err = ionic_lif_rxq_init(lif, lif->rxqcqs[i].qcq);
if (err) {
ionic_lif_qcq_deinit(lif, lif->txqcqs[i].qcq);
goto err_out;
}
}
ionic_set_rx_mode(lif->netdev);
return 0;
err_out:
while (i--) {
ionic_lif_qcq_deinit(lif, lif->txqcqs[i].qcq);
ionic_lif_qcq_deinit(lif, lif->rxqcqs[i].qcq);
}
return err;
}
static int ionic_txrx_enable(struct ionic_lif *lif)
{
int i, err;
for (i = 0; i < lif->nxqs; i++) {
err = ionic_qcq_enable(lif->txqcqs[i].qcq);
if (err)
goto err_out;
ionic_rx_fill(&lif->rxqcqs[i].qcq->q);
err = ionic_qcq_enable(lif->rxqcqs[i].qcq);
if (err) {
ionic_qcq_disable(lif->txqcqs[i].qcq);
goto err_out;
}
}
return 0;
err_out:
while (i--) {
ionic_qcq_disable(lif->rxqcqs[i].qcq);
ionic_qcq_disable(lif->txqcqs[i].qcq);
}
return err;
}
int ionic_open(struct net_device *netdev) int ionic_open(struct net_device *netdev)
{ {
struct ionic_lif *lif = netdev_priv(netdev); struct ionic_lif *lif = netdev_priv(netdev);
int err;
netif_carrier_off(netdev); netif_carrier_off(netdev);
err = ionic_txrx_alloc(lif);
if (err)
return err;
err = ionic_txrx_init(lif);
if (err)
goto err_txrx_free;
err = ionic_txrx_enable(lif);
if (err)
goto err_txrx_deinit;
netif_set_real_num_tx_queues(netdev, lif->nxqs);
netif_set_real_num_rx_queues(netdev, lif->nxqs);
set_bit(IONIC_LIF_UP, lif->state); set_bit(IONIC_LIF_UP, lif->state);
ionic_link_status_check_request(lif); ionic_link_status_check_request(lif);
if (netif_carrier_ok(netdev))
netif_tx_wake_all_queues(netdev);
return 0; return 0;
err_txrx_deinit:
ionic_txrx_deinit(lif);
err_txrx_free:
ionic_txrx_free(lif);
return err;
} }
int ionic_stop(struct net_device *netdev) int ionic_stop(struct net_device *netdev)
...@@ -1103,6 +1506,12 @@ int ionic_stop(struct net_device *netdev) ...@@ -1103,6 +1506,12 @@ int ionic_stop(struct net_device *netdev)
/* carrier off before disabling queues to avoid watchdog timeout */ /* carrier off before disabling queues to avoid watchdog timeout */
netif_carrier_off(netdev); netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev);
netif_tx_disable(netdev);
ionic_txrx_disable(lif);
ionic_txrx_deinit(lif);
ionic_txrx_free(lif);
return err; return err;
} }
...@@ -1110,6 +1519,7 @@ int ionic_stop(struct net_device *netdev) ...@@ -1110,6 +1519,7 @@ int ionic_stop(struct net_device *netdev)
static const struct net_device_ops ionic_netdev_ops = { static const struct net_device_ops ionic_netdev_ops = {
.ndo_open = ionic_open, .ndo_open = ionic_open,
.ndo_stop = ionic_stop, .ndo_stop = ionic_stop,
.ndo_start_xmit = ionic_start_xmit,
.ndo_get_stats64 = ionic_get_stats64, .ndo_get_stats64 = ionic_get_stats64,
.ndo_set_rx_mode = ionic_set_rx_mode, .ndo_set_rx_mode = ionic_set_rx_mode,
.ndo_set_features = ionic_set_features, .ndo_set_features = ionic_set_features,
...@@ -1174,6 +1584,8 @@ static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index ...@@ -1174,6 +1584,8 @@ static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index
lif->ionic = ionic; lif->ionic = ionic;
lif->index = index; lif->index = index;
lif->ntxq_descs = IONIC_DEF_TXRX_DESC;
lif->nrxq_descs = IONIC_DEF_TXRX_DESC;
snprintf(lif->name, sizeof(lif->name), "lif%u", index); snprintf(lif->name, sizeof(lif->name), "lif%u", index);
...@@ -1507,6 +1919,8 @@ static int ionic_lif_init(struct ionic_lif *lif) ...@@ -1507,6 +1919,8 @@ static int ionic_lif_init(struct ionic_lif *lif)
if (err) if (err)
goto err_out_notifyq_deinit; goto err_out_notifyq_deinit;
lif->rx_copybreak = IONIC_RX_COPYBREAK_DEFAULT;
set_bit(IONIC_LIF_INITED, lif->state); set_bit(IONIC_LIF_INITED, lif->state);
return 0; return 0;
......
...@@ -12,20 +12,38 @@ ...@@ -12,20 +12,38 @@
#define IONIC_MAX_NUM_NAPI_CNTR (NAPI_POLL_WEIGHT + 1) #define IONIC_MAX_NUM_NAPI_CNTR (NAPI_POLL_WEIGHT + 1)
#define IONIC_MAX_NUM_SG_CNTR (IONIC_TX_MAX_SG_ELEMS + 1) #define IONIC_MAX_NUM_SG_CNTR (IONIC_TX_MAX_SG_ELEMS + 1)
#define IONIC_RX_COPYBREAK_DEFAULT 256
struct ionic_tx_stats { struct ionic_tx_stats {
u64 dma_map_err;
u64 pkts; u64 pkts;
u64 bytes; u64 bytes;
u64 clean;
u64 linearize;
u64 no_csum;
u64 csum;
u64 crc32_csum;
u64 tso;
u64 frags;
u64 sg_cntr[IONIC_MAX_NUM_SG_CNTR];
}; };
struct ionic_rx_stats { struct ionic_rx_stats {
u64 dma_map_err;
u64 alloc_err;
u64 pkts; u64 pkts;
u64 bytes; u64 bytes;
u64 csum_none;
u64 csum_complete;
u64 csum_error;
u64 buffers_posted;
}; };
#define IONIC_QCQ_F_INITED BIT(0) #define IONIC_QCQ_F_INITED BIT(0)
#define IONIC_QCQ_F_SG BIT(1) #define IONIC_QCQ_F_SG BIT(1)
#define IONIC_QCQ_F_INTR BIT(2) #define IONIC_QCQ_F_INTR BIT(2)
#define IONIC_QCQ_F_TX_STATS BIT(3)
#define IONIC_QCQ_F_RX_STATS BIT(4)
#define IONIC_QCQ_F_NOTIFYQ BIT(5) #define IONIC_QCQ_F_NOTIFYQ BIT(5)
struct ionic_napi_stats { struct ionic_napi_stats {
...@@ -54,7 +72,14 @@ struct ionic_qcq { ...@@ -54,7 +72,14 @@ struct ionic_qcq {
struct dentry *dentry; struct dentry *dentry;
}; };
struct ionic_qcqst {
struct ionic_qcq *qcq;
struct ionic_q_stats *stats;
};
#define q_to_qcq(q) container_of(q, struct ionic_qcq, q) #define q_to_qcq(q) container_of(q, struct ionic_qcq, q)
#define q_to_tx_stats(q) (&q_to_qcq(q)->stats->tx)
#define q_to_rx_stats(q) (&q_to_qcq(q)->stats->rx)
#define napi_to_qcq(napi) container_of(napi, struct ionic_qcq, napi) #define napi_to_qcq(napi) container_of(napi, struct ionic_qcq, napi)
#define napi_to_cq(napi) (&napi_to_qcq(napi)->cq) #define napi_to_cq(napi) (&napi_to_qcq(napi)->cq)
...@@ -106,11 +131,14 @@ struct ionic_lif { ...@@ -106,11 +131,14 @@ struct ionic_lif {
spinlock_t adminq_lock; /* lock for AdminQ operations */ spinlock_t adminq_lock; /* lock for AdminQ operations */
struct ionic_qcq *adminqcq; struct ionic_qcq *adminqcq;
struct ionic_qcq *notifyqcq; struct ionic_qcq *notifyqcq;
struct ionic_qcqst *txqcqs;
struct ionic_qcqst *rxqcqs;
u64 last_eid; u64 last_eid;
unsigned int neqs; unsigned int neqs;
unsigned int nxqs; unsigned int nxqs;
unsigned int ntxq_descs; unsigned int ntxq_descs;
unsigned int nrxq_descs; unsigned int nrxq_descs;
u32 rx_copybreak;
unsigned int rx_mode; unsigned int rx_mode;
u64 hw_features; u64 hw_features;
bool mc_overflow; bool mc_overflow;
...@@ -131,6 +159,11 @@ struct ionic_lif { ...@@ -131,6 +159,11 @@ struct ionic_lif {
u32 flags; u32 flags;
}; };
#define lif_to_txqcq(lif, i) ((lif)->txqcqs[i].qcq)
#define lif_to_rxqcq(lif, i) ((lif)->rxqcqs[i].qcq)
#define lif_to_txq(lif, i) (&lif_to_txqcq((lif), i)->q)
#define lif_to_rxq(lif, i) (&lif_to_txqcq((lif), i)->q)
static inline int ionic_wait_for_bit(struct ionic_lif *lif, int bitname) static inline int ionic_wait_for_bit(struct ionic_lif *lif, int bitname)
{ {
unsigned long tlimit = jiffies + HZ; unsigned long tlimit = jiffies + HZ;
...@@ -156,6 +189,20 @@ int ionic_open(struct net_device *netdev); ...@@ -156,6 +189,20 @@ int ionic_open(struct net_device *netdev);
int ionic_stop(struct net_device *netdev); int ionic_stop(struct net_device *netdev);
int ionic_reset_queues(struct ionic_lif *lif); int ionic_reset_queues(struct ionic_lif *lif);
static inline void debug_stats_txq_post(struct ionic_qcq *qcq,
struct ionic_txq_desc *desc, bool dbell)
{
u8 num_sg_elems = ((le64_to_cpu(desc->cmd) >> IONIC_TXQ_DESC_NSGE_SHIFT)
& IONIC_TXQ_DESC_NSGE_MASK);
qcq->q.dbell_count += dbell;
if (num_sg_elems > (IONIC_MAX_NUM_SG_CNTR - 1))
num_sg_elems = IONIC_MAX_NUM_SG_CNTR - 1;
qcq->stats->tx.sg_cntr[num_sg_elems]++;
}
static inline void debug_stats_napi_poll(struct ionic_qcq *qcq, static inline void debug_stats_napi_poll(struct ionic_qcq *qcq,
unsigned int work_done) unsigned int work_done)
{ {
...@@ -168,7 +215,10 @@ static inline void debug_stats_napi_poll(struct ionic_qcq *qcq, ...@@ -168,7 +215,10 @@ static inline void debug_stats_napi_poll(struct ionic_qcq *qcq,
} }
#define DEBUG_STATS_CQE_CNT(cq) ((cq)->compl_count++) #define DEBUG_STATS_CQE_CNT(cq) ((cq)->compl_count++)
#define DEBUG_STATS_RX_BUFF_CNT(qcq) ((qcq)->stats->rx.buffers_posted++)
#define DEBUG_STATS_INTR_REARM(intr) ((intr)->rearm_count++) #define DEBUG_STATS_INTR_REARM(intr) ((intr)->rearm_count++)
#define DEBUG_STATS_TXQ_POST(qcq, txdesc, dbell) \
debug_stats_txq_post(qcq, txdesc, dbell)
#define DEBUG_STATS_NAPI_POLL(qcq, work_done) \ #define DEBUG_STATS_NAPI_POLL(qcq, work_done) \
debug_stats_napi_poll(qcq, work_done) debug_stats_napi_poll(qcq, work_done)
......
此差异已折叠。
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
#ifndef _IONIC_TXRX_H_
#define _IONIC_TXRX_H_
void ionic_rx_flush(struct ionic_cq *cq);
void ionic_tx_flush(struct ionic_cq *cq);
void ionic_rx_fill(struct ionic_queue *q);
void ionic_rx_empty(struct ionic_queue *q);
int ionic_rx_napi(struct napi_struct *napi, int budget);
netdev_tx_t ionic_start_xmit(struct sk_buff *skb, struct net_device *netdev);
#endif /* _IONIC_TXRX_H_ */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册