Commit 5e6808b4 authored by Naveen Mamindlapalli's avatar Naveen Mamindlapalli Committed by David S. Miller
Browse files

octeontx2-pf: Add support for HTB offload



This patch registers callbacks to support HTB offload.

Below are features supported,

- supports traffic shaping on the given class by honoring rate and ceil
configuration.

- supports traffic scheduling,  which prioritizes different types of
traffic based on strict priority values.

- supports the creation of leaf to inner classes such that parent node
rate limits apply to all child nodes.

Signed-off-by: default avatarNaveen Mamindlapalli <naveenm@marvell.com>
Signed-off-by: default avatarHariprasad Kelam <hkelam@marvell.com>
Signed-off-by: default avatarSunil Kovvuri Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent cb748a7e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -142,7 +142,7 @@ enum nix_scheduler {

#define TXSCH_RR_QTM_MAX		((1 << 24) - 1)
#define TXSCH_TL1_DFLT_RR_QTM		TXSCH_RR_QTM_MAX
#define TXSCH_TL1_DFLT_RR_PRIO		(0x1ull)
#define TXSCH_TL1_DFLT_RR_PRIO		(0x7ull)
#define CN10K_MAX_DWRR_WEIGHT          16384 /* Weight is 14bit on CN10K */

/* Min/Max packet sizes, excluding FCS */
+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 qos_sq.o
               otx2_devlink.o qos_sq.o qos.o
rvu_nicvf-y := otx2_vf.o otx2_devlink.o

rvu_nicpf-$(CONFIG_DCB) += otx2_dcbnl.o
+5 −0
Original line number Diff line number Diff line
@@ -89,6 +89,11 @@ int otx2_update_sq_stats(struct otx2_nic *pfvf, int qidx)
	if (!pfvf->qset.sq)
		return 0;

	if (qidx >= pfvf->hw.non_qos_queues) {
		if (!test_bit(qidx - pfvf->hw.non_qos_queues, pfvf->qos.qos_sq_bmap))
			return 0;
	}

	otx2_nix_sq_op_stats(&sq->stats, pfvf, qidx);
	return 1;
}
+10 −0
Original line number Diff line number Diff line
@@ -1099,8 +1099,18 @@ 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;
	INIT_LIST_HEAD(&pfvf->qos.qos_tree);
	mutex_init(&pfvf->qos.qos_lock);
}

static inline void otx2_shutdown_qos(struct otx2_nic *pfvf)
{
	mutex_destroy(&pfvf->qos.qos_lock);
}

u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
		      struct net_device *sb_dev);
int otx2_get_txq_by_classid(struct otx2_nic *pfvf, u16 classid);
void otx2_qos_config_txschq(struct otx2_nic *pfvf);
void otx2_clean_qos_queues(struct otx2_nic *pfvf);
#endif /* OTX2_COMMON_H */
+50 −3
Original line number Diff line number Diff line
@@ -1387,6 +1387,9 @@ static void otx2_free_sq_res(struct otx2_nic *pf)
	otx2_sq_free_sqbs(pf);
	for (qidx = 0; qidx < otx2_get_total_tx_queues(pf); qidx++) {
		sq = &qset->sq[qidx];
		/* Skip freeing Qos queues if they are not initialized */
		if (!sq->sqe)
			continue;
		qmem_free(pf->dev, sq->sqe);
		qmem_free(pf->dev, sq->tso_hdrs);
		kfree(sq->sg);
@@ -1566,6 +1569,8 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
		otx2_pfc_txschq_stop(pf);
#endif

	otx2_clean_qos_queues(pf);

	mutex_lock(&mbox->lock);
	/* Disable backpressure */
	if (!(pf->pcifunc & RVU_PFVF_FUNC_MASK))
@@ -1710,7 +1715,7 @@ int otx2_open(struct net_device *netdev)
	if (!qset->cq)
		goto err_free_mem;

	qset->sq = kcalloc(pf->hw.non_qos_queues,
	qset->sq = kcalloc(otx2_get_total_tx_queues(pf),
			   sizeof(struct otx2_snd_queue), GFP_KERNEL);
	if (!qset->sq)
		goto err_free_mem;
@@ -1833,6 +1838,9 @@ int otx2_open(struct net_device *netdev)
	/* 'intf_down' may be checked on any cpu */
	smp_wmb();

	/* Enable QoS configuration before starting tx queues */
	otx2_qos_config_txschq(pf);

	/* we have already received link status notification */
	if (pf->linfo.link_up && !(pf->pcifunc & RVU_PFVF_FUNC_MASK))
		otx2_handle_link_event(pf);
@@ -1986,14 +1994,48 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
	return NETDEV_TX_OK;
}

static int otx2_qos_select_htb_queue(struct otx2_nic *pf, struct sk_buff *skb,
				     u16 htb_maj_id)
{
	u16 classid;

	if ((TC_H_MAJ(skb->priority) >> 16) == htb_maj_id)
		classid = TC_H_MIN(skb->priority);
	else
		classid = READ_ONCE(pf->qos.defcls);

	if (!classid)
		return 0;

	return otx2_get_txq_by_classid(pf, classid);
}

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);
	bool qos_enabled;
#ifdef CONFIG_DCB
	u8 vlan_prio;
#endif
	int txq;

	qos_enabled = (netdev->real_num_tx_queues > pf->hw.tx_queues) ? true : false;
	if (unlikely(qos_enabled)) {
		/* This smp_load_acquire() pairs with smp_store_release() in
		 * otx2_qos_root_add() called from htb offload root creation
		 */
		u16 htb_maj_id = smp_load_acquire(&pf->qos.maj_id);

		if (unlikely(htb_maj_id)) {
			txq = otx2_qos_select_htb_queue(pf, skb, htb_maj_id);
			if (txq > 0)
				return txq;
			goto process_pfc;
		}
	}

process_pfc:
#ifdef CONFIG_DCB
	if (!skb_vlan_tag_present(skb))
		goto pick_tx;
@@ -2007,7 +2049,11 @@ u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,

pick_tx:
#endif
	return netdev_pick_tx(netdev, skb, NULL);
	txq = netdev_pick_tx(netdev, skb, NULL);
	if (unlikely(qos_enabled))
		return txq % pf->hw.tx_queues;

	return txq;
}
EXPORT_SYMBOL(otx2_select_queue);

@@ -3121,6 +3167,7 @@ static void otx2_remove(struct pci_dev *pdev)
	otx2_ptp_destroy(pf);
	otx2_mcam_flow_del(pf);
	otx2_shutdown_tc(pf);
	otx2_shutdown_qos(pf);
	otx2_detach_resources(&pf->mbox);
	if (pf->hw.lmt_info)
		free_percpu(pf->hw.lmt_info);
Loading