Skip to content

Commit

Permalink
octeontx2-pf: qos send queues management
Browse files Browse the repository at this point in the history
Current implementation is such that the number of Send queues (SQs)
are decided on the device probe which is equal to the number of online
cpus. These SQs are allocated and deallocated in interface open and c
lose calls respectively.

This patch defines new APIs for initializing and deinitializing Send
queues dynamically and allocates more number of transmit queues for
QOS feature.

Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
Signed-off-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Subbaraya Sundeep authored and David S. Miller committed May 15, 2023
1 parent 508c58f commit ab6dddd
Show file tree
Hide file tree
Showing 10 changed files with 426 additions and 42 deletions.
5 changes: 5 additions & 0 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1222,6 +1222,11 @@ static int rvu_dbg_npa_ctx_display(struct seq_file *m, void *unused, int ctype)

for (aura = id; aura < max_id; aura++) {
aq_req.aura_id = aura;

/* Skip if queue is uninitialized */
if (ctype == NPA_AQ_CTYPE_POOL && !test_bit(aura, pfvf->pool_bmap))
continue;

seq_printf(m, "======%s : %d=======\n",
(ctype == NPA_AQ_CTYPE_AURA) ? "AURA" : "POOL",
aq_req.aura_id);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/marvell/octeontx2/nic/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ obj-$(CONFIG_OCTEONTX2_VF) += rvu_nicvf.o otx2_ptp.o

rvu_nicpf-y := otx2_pf.o otx2_common.o otx2_txrx.o otx2_ethtool.o \
otx2_flows.o otx2_tc.o cn10k.o otx2_dmac_flt.o \
otx2_devlink.o
otx2_devlink.o qos_sq.o
rvu_nicvf-y := otx2_vf.o otx2_devlink.o

rvu_nicpf-$(CONFIG_DCB) += otx2_dcbnl.o
Expand Down
43 changes: 28 additions & 15 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -513,8 +513,8 @@ void otx2_config_irq_coalescing(struct otx2_nic *pfvf, int qidx)
(pfvf->hw.cq_ecount_wait - 1));
}

int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
dma_addr_t *dma)
static int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
dma_addr_t *dma)
{
u8 *buf;

Expand All @@ -532,8 +532,8 @@ int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
return 0;
}

static int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
dma_addr_t *dma)
int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
dma_addr_t *dma)
{
int ret;

Expand Down Expand Up @@ -758,11 +758,16 @@ int otx2_txschq_stop(struct otx2_nic *pfvf)
void otx2_sqb_flush(struct otx2_nic *pfvf)
{
int qidx, sqe_tail, sqe_head;
struct otx2_snd_queue *sq;
u64 incr, *ptr, val;
int timeout = 1000;

ptr = (u64 *)otx2_get_regaddr(pfvf, NIX_LF_SQ_OP_STATUS);
for (qidx = 0; qidx < pfvf->hw.non_qos_queues; qidx++) {
for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
sq = &pfvf->qset.sq[qidx];
if (!sq->sqb_ptrs)
continue;

incr = (u64)qidx << 32;
while (timeout) {
val = otx2_atomic64_add(incr, ptr);
Expand Down Expand Up @@ -862,7 +867,7 @@ int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
return otx2_sync_mbox_msg(&pfvf->mbox);
}

static int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
{
struct otx2_qset *qset = &pfvf->qset;
struct otx2_snd_queue *sq;
Expand Down Expand Up @@ -935,9 +940,17 @@ static int otx2_cq_init(struct otx2_nic *pfvf, u16 qidx)
cq->cint_idx = qidx - pfvf->hw.rx_queues;
cq->cqe_cnt = qset->sqe_cnt;
} else {
cq->cq_type = CQ_XDP;
cq->cint_idx = qidx - non_xdp_queues;
cq->cqe_cnt = qset->sqe_cnt;
if (pfvf->hw.xdp_queues &&
qidx < non_xdp_queues + pfvf->hw.xdp_queues) {
cq->cq_type = CQ_XDP;
cq->cint_idx = qidx - non_xdp_queues;
cq->cqe_cnt = qset->sqe_cnt;
} else {
cq->cq_type = CQ_QOS;
cq->cint_idx = qidx - non_xdp_queues -
pfvf->hw.xdp_queues;
cq->cqe_cnt = qset->sqe_cnt;
}
}
cq->cqe_size = pfvf->qset.xqe_size;

Expand Down Expand Up @@ -1095,7 +1108,7 @@ int otx2_config_nix(struct otx2_nic *pfvf)

/* Set RQ/SQ/CQ counts */
nixlf->rq_cnt = pfvf->hw.rx_queues;
nixlf->sq_cnt = pfvf->hw.non_qos_queues;
nixlf->sq_cnt = otx2_get_total_tx_queues(pfvf);
nixlf->cq_cnt = pfvf->qset.cq_cnt;
nixlf->rss_sz = MAX_RSS_INDIR_TBL_SIZE;
nixlf->rss_grps = MAX_RSS_GROUPS;
Expand Down Expand Up @@ -1133,7 +1146,7 @@ void otx2_sq_free_sqbs(struct otx2_nic *pfvf)
int sqb, qidx;
u64 iova, pa;

for (qidx = 0; qidx < hw->non_qos_queues; qidx++) {
for (qidx = 0; qidx < otx2_get_total_tx_queues(pfvf); qidx++) {
sq = &qset->sq[qidx];
if (!sq->sqb_ptrs)
continue;
Expand Down Expand Up @@ -1201,8 +1214,8 @@ void otx2_aura_pool_free(struct otx2_nic *pfvf)
pfvf->qset.pool = NULL;
}

static int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
int pool_id, int numptrs)
int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
int pool_id, int numptrs)
{
struct npa_aq_enq_req *aq;
struct otx2_pool *pool;
Expand Down Expand Up @@ -1278,8 +1291,8 @@ static int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
return 0;
}

static int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
int stack_pages, int numptrs, int buf_size)
int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
int stack_pages, int numptrs, int buf_size)
{
struct npa_aq_enq_req *aq;
struct otx2_pool *pool;
Expand Down
39 changes: 34 additions & 5 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "otx2_txrx.h"
#include "otx2_devlink.h"
#include <rvu_trace.h>
#include "qos.h"

/* IPv4 flag more fragment bit */
#define IPV4_FLAG_MORE 0x20
Expand Down Expand Up @@ -190,6 +191,7 @@ struct otx2_hw {
u16 rx_queues;
u16 tx_queues;
u16 xdp_queues;
u16 tc_tx_queues;
u16 non_qos_queues; /* tx queues plus xdp queues */
u16 max_queues;
u16 pool_cnt;
Expand Down Expand Up @@ -506,6 +508,8 @@ struct otx2_nic {
u16 pfc_schq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
bool pfc_alloc_status[NIX_PF_PFC_PRIO_MAX];
#endif
/* qos */
struct otx2_qos qos;

/* napi event count. It is needed for adaptive irq coalescing. */
u32 napi_events;
Expand Down Expand Up @@ -750,8 +754,7 @@ static inline void cn10k_aura_freeptr(void *dev, int aura, u64 buf)
/* Alloc pointer from pool/aura */
static inline u64 otx2_aura_allocptr(struct otx2_nic *pfvf, int aura)
{
u64 *ptr = (u64 *)otx2_get_regaddr(pfvf,
NPA_LF_AURA_OP_ALLOCX(0));
u64 *ptr = (__force u64 *)otx2_get_regaddr(pfvf, NPA_LF_AURA_OP_ALLOCX(0));
u64 incr = (u64)aura | BIT_ULL(63);

return otx2_atomic64_add(incr, ptr);
Expand Down Expand Up @@ -893,12 +896,23 @@ static inline void otx2_dma_unmap_page(struct otx2_nic *pfvf,

static inline u16 otx2_get_smq_idx(struct otx2_nic *pfvf, u16 qidx)
{
u16 smq;
#ifdef CONFIG_DCB
if (qidx < NIX_PF_PFC_PRIO_MAX && pfvf->pfc_alloc_status[qidx])
return pfvf->pfc_schq_list[NIX_TXSCH_LVL_SMQ][qidx];
#endif
/* check if qidx falls under QOS queues */
if (qidx >= pfvf->hw.non_qos_queues)
smq = pfvf->qos.qid_to_sqmap[qidx - pfvf->hw.non_qos_queues];
else
smq = pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0];

return pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0];
return smq;
}

static inline u16 otx2_get_total_tx_queues(struct otx2_nic *pfvf)
{
return pfvf->hw.non_qos_queues + pfvf->hw.tc_tx_queues;
}

/* MSI-X APIs */
Expand Down Expand Up @@ -927,17 +941,22 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool pfc_en);
int otx2_txsch_alloc(struct otx2_nic *pfvf);
int otx2_txschq_stop(struct otx2_nic *pfvf);
void otx2_sqb_flush(struct otx2_nic *pfvf);
int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
dma_addr_t *dma);
int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
dma_addr_t *dma);
int otx2_rxtx_enable(struct otx2_nic *pfvf, bool enable);
void otx2_ctx_disable(struct mbox *mbox, int type, bool npa);
int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable);
void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura);
int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura);
int otx2_alloc_buffer(struct otx2_nic *pfvf, struct otx2_cq_queue *cq,
dma_addr_t *dma);
int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
int stack_pages, int numptrs, int buf_size);
int otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
int pool_id, int numptrs);

/* RSS configuration APIs*/
int otx2_rss_init(struct otx2_nic *pfvf);
Expand Down Expand Up @@ -1045,4 +1064,14 @@ static inline void cn10k_handle_mcs_event(struct otx2_nic *pfvf,
{}
#endif /* CONFIG_MACSEC */

/* qos support */
static inline void otx2_qos_init(struct otx2_nic *pfvf, int qos_txqs)
{
struct otx2_hw *hw = &pfvf->hw;

hw->tc_tx_queues = qos_txqs;
}

u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
struct net_device *sb_dev);
#endif /* OTX2_COMMON_H */
44 changes: 34 additions & 10 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "otx2_struct.h"
#include "otx2_ptp.h"
#include "cn10k.h"
#include "qos.h"
#include <rvu_trace.h>

#define DRV_NAME "rvu_nicpf"
Expand Down Expand Up @@ -1228,6 +1229,7 @@ static char *nix_snd_status_e_str[NIX_SND_STATUS_MAX] = {
static irqreturn_t otx2_q_intr_handler(int irq, void *data)
{
struct otx2_nic *pf = data;
struct otx2_snd_queue *sq;
u64 val, *ptr;
u64 qidx = 0;

Expand Down Expand Up @@ -1257,10 +1259,14 @@ static irqreturn_t otx2_q_intr_handler(int irq, void *data)
}

/* SQ */
for (qidx = 0; qidx < pf->hw.non_qos_queues; qidx++) {
for (qidx = 0; qidx < otx2_get_total_tx_queues(pf); qidx++) {
u64 sq_op_err_dbg, mnq_err_dbg, snd_err_dbg;
u8 sq_op_err_code, mnq_err_code, snd_err_code;

sq = &pf->qset.sq[qidx];
if (!sq->sqb_ptrs)
continue;

/* Below debug registers captures first errors corresponding to
* those registers. We don't have to check against SQ qid as
* these are fatal errors.
Expand Down Expand Up @@ -1383,7 +1389,7 @@ static void otx2_free_sq_res(struct otx2_nic *pf)
otx2_ctx_disable(&pf->mbox, NIX_AQ_CTYPE_SQ, false);
/* Free SQB pointers */
otx2_sq_free_sqbs(pf);
for (qidx = 0; qidx < pf->hw.non_qos_queues; qidx++) {
for (qidx = 0; qidx < otx2_get_total_tx_queues(pf); qidx++) {
sq = &qset->sq[qidx];
qmem_free(pf->dev, sq->sqe);
qmem_free(pf->dev, sq->tso_hdrs);
Expand Down Expand Up @@ -1433,7 +1439,7 @@ static int otx2_init_hw_resources(struct otx2_nic *pf)
* so, aura count = pool count.
*/
hw->rqpool_cnt = hw->rx_queues;
hw->sqpool_cnt = hw->non_qos_queues;
hw->sqpool_cnt = otx2_get_total_tx_queues(pf);
hw->pool_cnt = hw->rqpool_cnt + hw->sqpool_cnt;

/* Maximum hardware supported transmit length */
Expand Down Expand Up @@ -1688,11 +1694,14 @@ int otx2_open(struct net_device *netdev)

netif_carrier_off(netdev);

pf->qset.cq_cnt = pf->hw.rx_queues + pf->hw.non_qos_queues;
/* RQ and SQs are mapped to different CQs,
* so find out max CQ IRQs (i.e CINTs) needed.
*/
pf->hw.cint_cnt = max(pf->hw.rx_queues, pf->hw.tx_queues);
pf->hw.cint_cnt = max3(pf->hw.rx_queues, pf->hw.tx_queues,
pf->hw.tc_tx_queues);

pf->qset.cq_cnt = pf->hw.rx_queues + otx2_get_total_tx_queues(pf);

qset->napi = kcalloc(pf->hw.cint_cnt, sizeof(*cq_poll), GFP_KERNEL);
if (!qset->napi)
return -ENOMEM;
Expand Down Expand Up @@ -1743,6 +1752,11 @@ int otx2_open(struct net_device *netdev)
else
cq_poll->cq_ids[CQ_XDP] = CINT_INVALID_CQ;

cq_poll->cq_ids[CQ_QOS] = (qidx < pf->hw.tc_tx_queues) ?
(qidx + pf->hw.rx_queues +
pf->hw.non_qos_queues) :
CINT_INVALID_CQ;

cq_poll->dev = (void *)pf;
cq_poll->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_CQE;
INIT_WORK(&cq_poll->dim.work, otx2_dim_work);
Expand Down Expand Up @@ -1947,6 +1961,12 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
int qidx = skb_get_queue_mapping(skb);
struct otx2_snd_queue *sq;
struct netdev_queue *txq;
int sq_idx;

/* XDP SQs are not mapped with TXQs
* advance qid to derive correct sq mapped with QOS
*/
sq_idx = (qidx >= pf->hw.tx_queues) ? (qidx + pf->hw.xdp_queues) : qidx;

/* Check for minimum and maximum packet length */
if (skb->len <= ETH_HLEN ||
Expand All @@ -1955,7 +1975,7 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}

sq = &pf->qset.sq[qidx];
sq = &pf->qset.sq[sq_idx];
txq = netdev_get_tx_queue(netdev, qidx);

if (!otx2_sq_append_skb(netdev, sq, skb, qidx)) {
Expand All @@ -1973,8 +1993,8 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
}

static u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
struct net_device *sb_dev)
u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
struct net_device *sb_dev)
{
#ifdef CONFIG_DCB
struct otx2_nic *pf = netdev_priv(netdev);
Expand All @@ -1996,6 +2016,7 @@ static u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
#endif
return netdev_pick_tx(netdev, skb, NULL);
}
EXPORT_SYMBOL(otx2_select_queue);

static netdev_features_t otx2_fix_features(struct net_device *dev,
netdev_features_t features)
Expand Down Expand Up @@ -2712,10 +2733,10 @@ static void otx2_sriov_vfcfg_cleanup(struct otx2_nic *pf)
static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct device *dev = &pdev->dev;
int err, qcount, qos_txqs;
struct net_device *netdev;
struct otx2_nic *pf;
struct otx2_hw *hw;
int err, qcount;
int num_vec;

err = pcim_enable_device(pdev);
Expand All @@ -2740,8 +2761,9 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)

/* Set number of queues */
qcount = min_t(int, num_online_cpus(), OTX2_MAX_CQ_CNT);
qos_txqs = min_t(int, qcount, OTX2_QOS_MAX_LEAF_NODES);

netdev = alloc_etherdev_mqs(sizeof(*pf), qcount, qcount);
netdev = alloc_etherdev_mqs(sizeof(*pf), qcount + qos_txqs, qcount);
if (!netdev) {
err = -ENOMEM;
goto err_release_regions;
Expand Down Expand Up @@ -2929,6 +2951,8 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_pf_sriov_init;
#endif

otx2_qos_init(pf, qos_txqs);

return 0;

err_pf_sriov_init:
Expand Down
Loading

0 comments on commit ab6dddd

Please sign in to comment.