Commit e6ebe6c1 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'taprio-auto-qmaxsdu-new-tx'

Vladimir Oltean says:

====================
taprio automatic queueMaxSDU and new TXQ selection procedure

This patch set addresses 2 design limitations in the taprio software scheduler:

1. Software scheduling fundamentally prioritizes traffic incorrectly,
   in a way which was inspired from Intel igb/igc drivers and does not
   follow the inputs user space gives (traffic classes and TC to TXQ
   mapping). Patch 05/15 handles this, 01/15 - 04/15 are preparations
   for this work.

2. Software scheduling assumes that the gate for a traffic class closes
   as soon as the next interval begins. But this isn't true.
   If consecutive schedule entries have that traffic class gate open,
   there is no "gate close" event and taprio should keep dequeuing from
   that TC without interruptions. Patches 06/15 - 15/15 handle this.
   Patch 10/15 is a generic Qdisc change required for this to work.

Future development directions which depend on this patch set are:

- Propagating the automatic queueMaxSDU calculation down to offloading
  device drivers, instead of letting them calculate this, as
  vsc9959_tas_guard_bands_update() does today.

- A software data path for tc-taprio with preemptible traffic and
  Hold/Release events.

v1 at:
https://patchwork.kernel.org/project/netdevbpf/cover/20230128010719.2182346-1-vladimir.oltean@nxp.com/


====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6da13bf9 39b02d6d
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -2810,6 +2810,22 @@ static int igb_offload_txtime(struct igb_adapter *adapter,
	return 0;
}

static int igb_tc_query_caps(struct igb_adapter *adapter,
			     struct tc_query_caps_base *base)
{
	switch (base->type) {
	case TC_SETUP_QDISC_TAPRIO: {
		struct tc_taprio_caps *caps = base->caps;

		caps->broken_mqprio = true;

		return 0;
	}
	default:
		return -EOPNOTSUPP;
	}
}

static LIST_HEAD(igb_block_cb_list);

static int igb_setup_tc(struct net_device *dev, enum tc_setup_type type,
@@ -2818,6 +2834,8 @@ static int igb_setup_tc(struct net_device *dev, enum tc_setup_type type,
	struct igb_adapter *adapter = netdev_priv(dev);

	switch (type) {
	case TC_QUERY_CAPS:
		return igb_tc_query_caps(adapter, type_data);
	case TC_SETUP_QDISC_CBS:
		return igb_offload_cbs(adapter, type_data);
	case TC_SETUP_BLOCK:
+3 −3
Original line number Diff line number Diff line
@@ -6214,9 +6214,9 @@ static int igc_tc_query_caps(struct igc_adapter *adapter,
	case TC_SETUP_QDISC_TAPRIO: {
		struct tc_taprio_caps *caps = base->caps;

		if (hw->mac.type != igc_i225)
			return -EOPNOTSUPP;
		caps->broken_mqprio = true;

		if (hw->mac.type == igc_i225)
			caps->gate_mask_per_txq = true;

		return 0;
+5 −0
Original line number Diff line number Diff line
@@ -177,6 +177,11 @@ struct tc_mqprio_qopt_offload {
struct tc_taprio_caps {
	bool supports_queue_max_sdu:1;
	bool gate_mask_per_txq:1;
	/* Device expects lower TXQ numbers to have higher priority over higher
	 * TXQs, regardless of their TC mapping. DO NOT USE FOR NEW DRIVERS,
	 * INSTEAD ENFORCE A PROPER TC:TXQ MAPPING COMING FROM USER SPACE.
	 */
	bool broken_mqprio:1;
};

struct tc_taprio_sched_entry {
+11 −18
Original line number Diff line number Diff line
@@ -1282,12 +1282,6 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
	if (err)
		goto err_out3;

	if (ops->init) {
		err = ops->init(sch, tca[TCA_OPTIONS], extack);
		if (err != 0)
			goto err_out5;
	}

	if (tca[TCA_STAB]) {
		stab = qdisc_get_stab(tca[TCA_STAB], extack);
		if (IS_ERR(stab)) {
@@ -1296,11 +1290,18 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
		}
		rcu_assign_pointer(sch->stab, stab);
	}

	if (ops->init) {
		err = ops->init(sch, tca[TCA_OPTIONS], extack);
		if (err != 0)
			goto err_out5;
	}

	if (tca[TCA_RATE]) {
		err = -EOPNOTSUPP;
		if (sch->flags & TCQ_F_MQROOT) {
			NL_SET_ERR_MSG(extack, "Cannot attach rate estimator to a multi-queue root qdisc");
			goto err_out4;
			goto err_out5;
		}

		err = gen_new_estimator(&sch->bstats,
@@ -1311,7 +1312,7 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
					tca[TCA_RATE]);
		if (err) {
			NL_SET_ERR_MSG(extack, "Failed to generate new estimator");
			goto err_out4;
			goto err_out5;
		}
	}

@@ -1321,6 +1322,8 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
	return sch;

err_out5:
	qdisc_put_stab(rtnl_dereference(sch->stab));
err_out4:
	/* ops->init() failed, we call ->destroy() like qdisc_create_dflt() */
	if (ops->destroy)
		ops->destroy(sch);
@@ -1332,16 +1335,6 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
err_out:
	*errp = err;
	return NULL;

err_out4:
	/*
	 * Any broken qdiscs that would require a ops->reset() here?
	 * The qdisc was never in action so it shouldn't be necessary.
	 */
	qdisc_put_stab(rtnl_dereference(sch->stab));
	if (ops->destroy)
		ops->destroy(sch);
	goto err_out3;
}

static int qdisc_change(struct Qdisc *sch, struct nlattr **tca,
+463 −176

File changed.

Preview size limit exceeded, changes collapsed.