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

Commit 2026fecf authored by Alexander Duyck's avatar Alexander Duyck Committed by David S. Miller
Browse files

mqprio: Change handling of hw u8 to allow for multiple hardware offload modes



This patch is meant to allow for support of multiple hardware offload type
for a single device. There is currently no bounds checking for the hw
member of the mqprio_qopt structure.  This results in us being able to pass
values from 1 to 255 with all being treated the same.  On retreiving the
value it is returned as 1 for anything 1 or greater being set.

With this change we are currently adding limited bounds checking by
defining an enum and using those values to limit the reported hardware
offloads.

Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5b769649
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -617,6 +617,14 @@ struct tc_drr_stats {
#define TC_QOPT_BITMASK 15
#define TC_QOPT_BITMASK 15
#define TC_QOPT_MAX_QUEUE 16
#define TC_QOPT_MAX_QUEUE 16


enum {
	TC_MQPRIO_HW_OFFLOAD_NONE,	/* no offload requested */
	TC_MQPRIO_HW_OFFLOAD_TCS,	/* offload TCs, no queue counts */
	__TC_MQPRIO_HW_OFFLOAD_MAX
};

#define TC_MQPRIO_HW_OFFLOAD_MAX (__TC_MQPRIO_HW_OFFLOAD_MAX - 1)

struct tc_mqprio_qopt {
struct tc_mqprio_qopt {
	__u8	num_tc;
	__u8	num_tc;
	__u8	prio_tc_map[TC_QOPT_BITMASK + 1];
	__u8	prio_tc_map[TC_QOPT_BITMASK + 1];
+16 −10
Original line number Original line Diff line number Diff line
@@ -21,7 +21,7 @@


struct mqprio_sched {
struct mqprio_sched {
	struct Qdisc		**qdiscs;
	struct Qdisc		**qdiscs;
	int hw_owned;
	int hw_offload;
};
};


static void mqprio_destroy(struct Qdisc *sch)
static void mqprio_destroy(struct Qdisc *sch)
@@ -39,7 +39,7 @@ static void mqprio_destroy(struct Qdisc *sch)
		kfree(priv->qdiscs);
		kfree(priv->qdiscs);
	}
	}


	if (priv->hw_owned && dev->netdev_ops->ndo_setup_tc)
	if (priv->hw_offload && dev->netdev_ops->ndo_setup_tc)
		dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
		dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
	else
	else
		netdev_set_num_tc(dev, 0);
		netdev_set_num_tc(dev, 0);
@@ -59,15 +59,20 @@ static int mqprio_parse_opt(struct net_device *dev, struct tc_mqprio_qopt *qopt)
			return -EINVAL;
			return -EINVAL;
	}
	}


	/* net_device does not support requested operation */
	/* Limit qopt->hw to maximum supported offload value.  Drivers have
	if (qopt->hw && !dev->netdev_ops->ndo_setup_tc)
	 * the option of overriding this later if they don't support the a
		return -EINVAL;
	 * given offload type.
	 */
	if (qopt->hw > TC_MQPRIO_HW_OFFLOAD_MAX)
		qopt->hw = TC_MQPRIO_HW_OFFLOAD_MAX;


	/* if hw owned qcount and qoffset are taken from LLD so
	/* If hardware offload is requested we will leave it to the device
	 * no reason to verify them here
	 * to either populate the queue counts itself or to validate the
	 * provided queue counts.  If ndo_setup_tc is not present then
	 * hardware doesn't support offload and we should return an error.
	 */
	 */
	if (qopt->hw)
	if (qopt->hw)
		return 0;
		return dev->netdev_ops->ndo_setup_tc ? 0 : -EINVAL;


	for (i = 0; i < qopt->num_tc; i++) {
	for (i = 0; i < qopt->num_tc; i++) {
		unsigned int last = qopt->offset[i] + qopt->count[i];
		unsigned int last = qopt->offset[i] + qopt->count[i];
@@ -142,10 +147,11 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)
		struct tc_to_netdev tc = {.type = TC_SETUP_MQPRIO,
		struct tc_to_netdev tc = {.type = TC_SETUP_MQPRIO,
					  { .tc = qopt->num_tc }};
					  { .tc = qopt->num_tc }};


		priv->hw_owned = 1;
		err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
		err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
		if (err)
		if (err)
			return err;
			return err;

		priv->hw_offload = qopt->hw;
	} else {
	} else {
		netdev_set_num_tc(dev, qopt->num_tc);
		netdev_set_num_tc(dev, qopt->num_tc);
		for (i = 0; i < qopt->num_tc; i++)
		for (i = 0; i < qopt->num_tc; i++)
@@ -243,7 +249,7 @@ static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb)


	opt.num_tc = netdev_get_num_tc(dev);
	opt.num_tc = netdev_get_num_tc(dev);
	memcpy(opt.prio_tc_map, dev->prio_tc_map, sizeof(opt.prio_tc_map));
	memcpy(opt.prio_tc_map, dev->prio_tc_map, sizeof(opt.prio_tc_map));
	opt.hw = priv->hw_owned;
	opt.hw = priv->hw_offload;


	for (i = 0; i < netdev_get_num_tc(dev); i++) {
	for (i = 0; i < netdev_get_num_tc(dev); i++) {
		opt.count[i] = dev->tc_to_txq[i].count;
		opt.count[i] = dev->tc_to_txq[i].count;