Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e7baf0f authored by Manish Chopra's avatar Manish Chopra Committed by David S. Miller
Browse files

qed/qede: Multi CoS support.



This patch adds support for tc mqprio offload,
using this different traffic classes on the adapter
can be utilized based on configured priority to tc map.

For example -

tc qdisc add dev eth0 root mqprio num_tc 4 map 0 1 2 3

This will cause SKBs with priority 0,1,2,3 to transmit
over tc 0,1,2,3 hardware queues respectively.

Signed-off-by: default avatarManish Chopra <manish.chopra@cavium.com>
Signed-off-by: default avatarAriel Elior <ariel.elior@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2eee32a7
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -2188,16 +2188,17 @@ int qed_get_queue_coalesce(struct qed_hwfn *p_hwfn, u16 *p_coal, void *handle)
static int qed_fill_eth_dev_info(struct qed_dev *cdev,
				 struct qed_dev_eth_info *info)
{
	struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
	int i;

	memset(info, 0, sizeof(*info));

	info->num_tc = 1;

	if (IS_PF(cdev)) {
		int max_vf_vlan_filters = 0;
		int max_vf_mac_filters = 0;

		info->num_tc = p_hwfn->hw_info.num_hw_tc;

		if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
			u16 num_queues = 0;

@@ -2248,6 +2249,8 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
	} else {
		u16 total_cids = 0;

		info->num_tc = 1;

		/* Determine queues &  XDP support */
		for_each_hwfn(cdev, i) {
			struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
@@ -2554,7 +2557,7 @@ static int qed_start_txq(struct qed_dev *cdev,

	rc = qed_eth_tx_queue_start(p_hwfn,
				    p_hwfn->hw_info.opaque_fid,
				    p_params, 0,
				    p_params, p_params->tc,
				    pbl_addr, pbl_size, ret_params);

	if (rc) {
+3 −2
Original line number Diff line number Diff line
@@ -948,13 +948,14 @@ static void qed_update_pf_params(struct qed_dev *cdev,
		params->eth_pf_params.num_arfs_filters = 0;

	/* In case we might support RDMA, don't allow qede to be greedy
	 * with the L2 contexts. Allow for 64 queues [rx, tx, xdp] per hwfn.
	 * with the L2 contexts. Allow for 64 queues [rx, tx cos, xdp]
	 * per hwfn.
	 */
	if (QED_IS_RDMA_PERSONALITY(QED_LEADING_HWFN(cdev))) {
		u16 *num_cons;

		num_cons = &params->eth_pf_params.num_cons;
		*num_cons = min_t(u16, *num_cons, 192);
		*num_cons = min_t(u16, *num_cons, QED_MAX_L2_CONS);
	}

	for (i = 0; i < cdev->num_hwfns; i++) {
+13 −0
Original line number Diff line number Diff line
@@ -386,6 +386,15 @@ struct qede_tx_queue {
#define QEDE_TXQ_XDP_TO_IDX(edev, txq)	((txq)->index - \
					 QEDE_MAX_TSS_CNT(edev))
#define QEDE_TXQ_IDX_TO_XDP(edev, idx)	((idx) + QEDE_MAX_TSS_CNT(edev))
#define QEDE_NDEV_TXQ_ID_TO_FP_ID(edev, idx)	((edev)->fp_num_rx + \
						 ((idx) % QEDE_TSS_COUNT(edev)))
#define QEDE_NDEV_TXQ_ID_TO_TXQ_COS(edev, idx)	((idx) / QEDE_TSS_COUNT(edev))
#define QEDE_TXQ_TO_NDEV_TXQ_ID(edev, txq)	((QEDE_TSS_COUNT(edev) * \
						 (txq)->cos) + (txq)->index)
#define QEDE_NDEV_TXQ_ID_TO_TXQ(edev, idx)	\
	(&((edev)->fp_array[QEDE_NDEV_TXQ_ID_TO_FP_ID(edev, idx)].txq \
	[QEDE_NDEV_TXQ_ID_TO_TXQ_COS(edev, idx)]))
#define QEDE_FP_TC0_TXQ(fp)	(&((fp)->txq[0]))

	/* Regular Tx requires skb + metadata for release purpose,
	 * while XDP requires the pages and the mapped address.
@@ -399,6 +408,8 @@ struct qede_tx_queue {

	/* Slowpath; Should be kept in end [unless missing padding] */
	void *handle;
	u16 cos;
	u16 ndev_txq_id;
};

#define BD_UNMAP_ADDR(bd)		HILO_U64(le32_to_cpu((bd)->addr.hi), \
@@ -541,5 +552,7 @@ void qede_update_rx_prod(struct qede_dev *edev, struct qede_rx_queue *rxq);
#define QEDE_RX_HDR_SIZE		256
#define QEDE_MAX_JUMBO_PACKET_SIZE	9600
#define	for_each_queue(i) for (i = 0; i < edev->num_queues; i++)
#define for_each_cos_in_txq(edev, var) \
	for ((var) = 0; (var) < (edev)->dev_info.num_tc; (var)++)

#endif /* _QEDE_H_ */
+38 −10
Original line number Diff line number Diff line
@@ -222,7 +222,7 @@ static void qede_get_strings_stats_txq(struct qede_dev *edev,
				QEDE_TXQ_XDP_TO_IDX(edev, txq),
				qede_tqstats_arr[i].string);
		else
			sprintf(*buf, "%d: %s", txq->index,
			sprintf(*buf, "%d_%d: %s", txq->index, txq->cos,
				qede_tqstats_arr[i].string);
		*buf += ETH_GSTRING_LEN;
	}
@@ -262,8 +262,13 @@ static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf)
		if (fp->type & QEDE_FASTPATH_XDP)
			qede_get_strings_stats_txq(edev, fp->xdp_tx, &buf);

		if (fp->type & QEDE_FASTPATH_TX)
			qede_get_strings_stats_txq(edev, fp->txq, &buf);
		if (fp->type & QEDE_FASTPATH_TX) {
			int cos;

			for_each_cos_in_txq(edev, cos)
				qede_get_strings_stats_txq(edev,
							   &fp->txq[cos], &buf);
		}
	}

	/* Account for non-queue statistics */
@@ -338,8 +343,12 @@ static void qede_get_ethtool_stats(struct net_device *dev,
		if (fp->type & QEDE_FASTPATH_XDP)
			qede_get_ethtool_stats_txq(fp->xdp_tx, &buf);

		if (fp->type & QEDE_FASTPATH_TX)
			qede_get_ethtool_stats_txq(fp->txq, &buf);
		if (fp->type & QEDE_FASTPATH_TX) {
			int cos;

			for_each_cos_in_txq(edev, cos)
				qede_get_ethtool_stats_txq(&fp->txq[cos], &buf);
		}
	}

	for (i = 0; i < QEDE_NUM_STATS; i++) {
@@ -366,7 +375,8 @@ static int qede_get_sset_count(struct net_device *dev, int stringset)
				num_stats--;

		/* Account for the Regular Tx statistics */
		num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS;
		num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS *
				edev->dev_info.num_tc;

		/* Account for the Regular Rx statistics */
		num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS;
@@ -741,9 +751,17 @@ static int qede_get_coalesce(struct net_device *dev,
		}

		for_each_queue(i) {
			struct qede_tx_queue *txq;

			fp = &edev->fp_array[i];

			/* All TX queues of given fastpath uses same
			 * coalescing value, so no need to iterate over
			 * all TCs, TC0 txq should suffice.
			 */
			if (fp->type & QEDE_FASTPATH_TX) {
				tx_handle = fp->txq->handle;
				txq = QEDE_FP_TC0_TXQ(fp);
				tx_handle = txq->handle;
				break;
			}
		}
@@ -801,9 +819,17 @@ static int qede_set_coalesce(struct net_device *dev,
		}

		if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
			struct qede_tx_queue *txq;

			/* All TX queues of given fastpath uses same
			 * coalescing value, so no need to iterate over
			 * all TCs, TC0 txq should suffice.
			 */
			txq = QEDE_FP_TC0_TXQ(fp);

			rc = edev->ops->common->set_coalesce(edev->cdev,
							     0, txc,
							     fp->txq->handle);
							     txq->handle);
			if (rc) {
				DP_INFO(edev,
					"Set TX coalesce error, rc = %d\n", rc);
@@ -1385,8 +1411,10 @@ static int qede_selftest_transmit_traffic(struct qede_dev *edev,
	u16 val;

	for_each_queue(i) {
		if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
			txq = edev->fp_array[i].txq;
		struct qede_fastpath *fp = &edev->fp_array[i];

		if (fp->type & QEDE_FASTPATH_TX) {
			txq = QEDE_FP_TC0_TXQ(fp);
			break;
		}
	}
+20 −9
Original line number Diff line number Diff line
@@ -408,12 +408,12 @@ static void qede_xdp_tx_int(struct qede_dev *edev, struct qede_tx_queue *txq)

static int qede_tx_int(struct qede_dev *edev, struct qede_tx_queue *txq)
{
	unsigned int pkts_compl = 0, bytes_compl = 0;
	struct netdev_queue *netdev_txq;
	u16 hw_bd_cons;
	unsigned int pkts_compl = 0, bytes_compl = 0;
	int rc;

	netdev_txq = netdev_get_tx_queue(edev->ndev, txq->index);
	netdev_txq = netdev_get_tx_queue(edev->ndev, txq->ndev_txq_id);

	hw_bd_cons = le16_to_cpu(*txq->hw_cons_ptr);
	barrier();
@@ -1365,9 +1365,14 @@ static bool qede_poll_is_more_work(struct qede_fastpath *fp)
		if (qede_txq_has_work(fp->xdp_tx))
			return true;

	if (likely(fp->type & QEDE_FASTPATH_TX))
		if (qede_txq_has_work(fp->txq))
	if (likely(fp->type & QEDE_FASTPATH_TX)) {
		int cos;

		for_each_cos_in_txq(fp->edev, cos) {
			if (qede_txq_has_work(&fp->txq[cos]))
				return true;
		}
	}

	return false;
}
@@ -1382,8 +1387,14 @@ int qede_poll(struct napi_struct *napi, int budget)
	struct qede_dev *edev = fp->edev;
	int rx_work_done = 0;

	if (likely(fp->type & QEDE_FASTPATH_TX) && qede_txq_has_work(fp->txq))
		qede_tx_int(edev, fp->txq);
	if (likely(fp->type & QEDE_FASTPATH_TX)) {
		int cos;

		for_each_cos_in_txq(fp->edev, cos) {
			if (qede_txq_has_work(&fp->txq[cos]))
				qede_tx_int(edev, &fp->txq[cos]);
		}
	}

	if ((fp->type & QEDE_FASTPATH_XDP) && qede_txq_has_work(fp->xdp_tx))
		qede_xdp_tx_int(edev, fp->xdp_tx);
@@ -1444,8 +1455,8 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev)

	/* Get tx-queue context and netdev index */
	txq_index = skb_get_queue_mapping(skb);
	WARN_ON(txq_index >= QEDE_TSS_COUNT(edev));
	txq = edev->fp_array[edev->fp_num_rx + txq_index].txq;
	WARN_ON(txq_index >= QEDE_TSS_COUNT(edev) * edev->dev_info.num_tc);
	txq = QEDE_NDEV_TXQ_ID_TO_TXQ(edev, txq_index);
	netdev_txq = netdev_get_tx_queue(ndev, txq_index);

	WARN_ON(qed_chain_get_elem_left(&txq->tx_pbl) < (MAX_SKB_FRAGS + 1));
Loading