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

Merge branch 'Taprio-qdisc-fixes'



Andre Guedes says:

====================
Taprio qdisc fixes

I'm re-sending this series, now with the "net-next" prefix in the subject.

The only change from the previous version is in patch 3. As suggested by Cong
Wang, it removes the !entry check within should_restart_cycle() since it is
already checked by the caller. As a side effect, that function becomes a dummy
wrapper on list_is_last() so we simply remove it and call list_is_last()
instead.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ecc5663c 6e734c82
Loading
Loading
Loading
Loading
+28 −28
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ static struct sk_buff *taprio_peek(struct Qdisc *sch)

	rcu_read_lock();
	entry = rcu_dereference(q->current_entry);
	gate_mask = entry ? entry->gate_mask : -1;
	gate_mask = entry ? entry->gate_mask : TAPRIO_ALL_GATES_OPEN;
	rcu_read_unlock();

	if (!gate_mask)
@@ -112,7 +112,7 @@ static struct sk_buff *taprio_peek(struct Qdisc *sch)
		tc = netdev_get_prio_tc_map(dev, prio);

		if (!(gate_mask & BIT(tc)))
			return NULL;
			continue;

		return skb;
	}
@@ -188,12 +188,12 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
		 */
		if (gate_mask != TAPRIO_ALL_GATES_OPEN &&
		    ktime_after(guard, entry->close_time))
			return NULL;
			continue;

		/* ... and no budget. */
		if (gate_mask != TAPRIO_ALL_GATES_OPEN &&
		    atomic_sub_return(len, &entry->budget) < 0)
			return NULL;
			continue;

		skb = child->ops->dequeue(child);
		if (unlikely(!skb))
@@ -209,14 +209,6 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
	return NULL;
}

static bool should_restart_cycle(const struct taprio_sched *q,
				 const struct sched_entry *entry)
{
	WARN_ON(!entry);

	return list_is_last(&entry->list, &q->entries);
}

static enum hrtimer_restart advance_sched(struct hrtimer *timer)
{
	struct taprio_sched *q = container_of(timer, struct taprio_sched,
@@ -240,7 +232,7 @@ static enum hrtimer_restart advance_sched(struct hrtimer *timer)
		goto first_run;
	}

	if (should_restart_cycle(q, entry))
	if (list_is_last(&entry->list, &q->entries))
		next = list_first_entry(&q->entries, struct sched_entry,
					list);
	else
@@ -539,7 +531,7 @@ static int taprio_parse_mqprio_opt(struct net_device *dev,
	return 0;
}

static ktime_t taprio_get_start_time(struct Qdisc *sch)
static int taprio_get_start_time(struct Qdisc *sch, ktime_t *start)
{
	struct taprio_sched *q = qdisc_priv(sch);
	struct sched_entry *entry;
@@ -547,27 +539,33 @@ static ktime_t taprio_get_start_time(struct Qdisc *sch)
	s64 n;

	base = ns_to_ktime(q->base_time);
	cycle = 0;
	now = q->get_time();

	if (ktime_after(base, now)) {
		*start = base;
		return 0;
	}

	/* Calculate the cycle_time, by summing all the intervals.
	 */
	cycle = 0;
	list_for_each_entry(entry, &q->entries, list)
		cycle = ktime_add_ns(cycle, entry->interval);

	if (!cycle)
		return base;

	now = q->get_time();

	if (ktime_after(base, now))
		return base;
	/* The qdisc is expected to have at least one sched_entry.  Moreover,
	 * any entry must have 'interval' > 0. Thus if the cycle time is zero,
	 * something went really wrong. In that case, we should warn about this
	 * inconsistent state and return error.
	 */
	if (WARN_ON(!cycle))
		return -EFAULT;

	/* Schedule the start time for the beginning of the next
	 * cycle.
	 */
	n = div64_s64(ktime_sub_ns(now, base), cycle);

	return ktime_add_ns(base, (n + 1) * cycle);
	*start = ktime_add_ns(base, (n + 1) * cycle);
	return 0;
}

static void taprio_start_sched(struct Qdisc *sch, ktime_t start)
@@ -651,7 +649,6 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
	if (err < 0)
		return err;

	err = -EINVAL;
	if (tb[TCA_TAPRIO_ATTR_PRIOMAP])
		mqprio = nla_data(tb[TCA_TAPRIO_ATTR_PRIOMAP]);

@@ -717,9 +714,12 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
	}

	taprio_set_picos_per_byte(dev, q);
	start = taprio_get_start_time(sch);
	if (!start)
		return 0;

	err = taprio_get_start_time(sch, &start);
	if (err < 0) {
		NL_SET_ERR_MSG(extack, "Internal error: failed get start time");
		return err;
	}

	taprio_start_sched(sch, start);