Commit ab6dddd2 authored by Subbaraya Sundeep's avatar Subbaraya Sundeep Committed by David S. Miller
Browse files

octeontx2-pf: qos send queues management



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: default avatarSubbaraya Sundeep <sbhatta@marvell.com>
Signed-off-by: default avatarHariprasad Kelam <hkelam@marvell.com>
Signed-off-by: default avatarSunil Kovvuri Goutham <sgoutham@marvell.com>
Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
Reviewed-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 508c58f7
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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
+28 −15
Original line number Diff line number Diff line
@@ -513,7 +513,7 @@ 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,
static int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
			     dma_addr_t *dma)
{
	u8 *buf;
@@ -532,7 +532,7 @@ 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,
int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
		    dma_addr_t *dma)
{
	int ret;
@@ -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);
@@ -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;
@@ -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 {
		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;

@@ -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;
@@ -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;
@@ -1201,7 +1214,7 @@ 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 otx2_aura_init(struct otx2_nic *pfvf, int aura_id,
		   int pool_id, int numptrs)
{
	struct npa_aq_enq_req *aq;
@@ -1278,7 +1291,7 @@ 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 otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id,
		   int stack_pages, int numptrs, int buf_size)
{
	struct npa_aq_enq_req *aq;
+34 −5
Original line number Diff line number Diff line
@@ -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
@@ -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;
@@ -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;
@@ -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);
@@ -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 */
@@ -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,
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);
@@ -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 */
+34 −10
Original line number Diff line number Diff line
@@ -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"
@@ -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;

@@ -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.
@@ -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);
@@ -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 */
@@ -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;
@@ -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);
@@ -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 ||
@@ -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)) {
@@ -1973,7 +1993,7 @@ 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,
u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
		      struct net_device *sb_dev)
{
#ifdef CONFIG_DCB
@@ -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)
@@ -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);
@@ -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;
@@ -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:
Loading