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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
08308f149b
|
@ -90,7 +90,7 @@ static struct sk_buff *taprio_peek(struct Qdisc *sch)
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
entry = rcu_dereference(q->current_entry);
|
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();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (!gate_mask)
|
if (!gate_mask)
|
||||||
|
@ -112,7 +112,7 @@ static struct sk_buff *taprio_peek(struct Qdisc *sch)
|
||||||
tc = netdev_get_prio_tc_map(dev, prio);
|
tc = netdev_get_prio_tc_map(dev, prio);
|
||||||
|
|
||||||
if (!(gate_mask & BIT(tc)))
|
if (!(gate_mask & BIT(tc)))
|
||||||
return NULL;
|
continue;
|
||||||
|
|
||||||
return skb;
|
return skb;
|
||||||
}
|
}
|
||||||
|
@ -188,12 +188,12 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
|
||||||
*/
|
*/
|
||||||
if (gate_mask != TAPRIO_ALL_GATES_OPEN &&
|
if (gate_mask != TAPRIO_ALL_GATES_OPEN &&
|
||||||
ktime_after(guard, entry->close_time))
|
ktime_after(guard, entry->close_time))
|
||||||
return NULL;
|
continue;
|
||||||
|
|
||||||
/* ... and no budget. */
|
/* ... and no budget. */
|
||||||
if (gate_mask != TAPRIO_ALL_GATES_OPEN &&
|
if (gate_mask != TAPRIO_ALL_GATES_OPEN &&
|
||||||
atomic_sub_return(len, &entry->budget) < 0)
|
atomic_sub_return(len, &entry->budget) < 0)
|
||||||
return NULL;
|
continue;
|
||||||
|
|
||||||
skb = child->ops->dequeue(child);
|
skb = child->ops->dequeue(child);
|
||||||
if (unlikely(!skb))
|
if (unlikely(!skb))
|
||||||
|
@ -209,14 +209,6 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
|
||||||
return NULL;
|
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)
|
static enum hrtimer_restart advance_sched(struct hrtimer *timer)
|
||||||
{
|
{
|
||||||
struct taprio_sched *q = container_of(timer, struct taprio_sched,
|
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;
|
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,
|
next = list_first_entry(&q->entries, struct sched_entry,
|
||||||
list);
|
list);
|
||||||
else
|
else
|
||||||
|
@ -539,7 +531,7 @@ static int taprio_parse_mqprio_opt(struct net_device *dev,
|
||||||
return 0;
|
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 taprio_sched *q = qdisc_priv(sch);
|
||||||
struct sched_entry *entry;
|
struct sched_entry *entry;
|
||||||
|
@ -547,27 +539,33 @@ static ktime_t taprio_get_start_time(struct Qdisc *sch)
|
||||||
s64 n;
|
s64 n;
|
||||||
|
|
||||||
base = ns_to_ktime(q->base_time);
|
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.
|
/* Calculate the cycle_time, by summing all the intervals.
|
||||||
*/
|
*/
|
||||||
|
cycle = 0;
|
||||||
list_for_each_entry(entry, &q->entries, list)
|
list_for_each_entry(entry, &q->entries, list)
|
||||||
cycle = ktime_add_ns(cycle, entry->interval);
|
cycle = ktime_add_ns(cycle, entry->interval);
|
||||||
|
|
||||||
if (!cycle)
|
/* The qdisc is expected to have at least one sched_entry. Moreover,
|
||||||
return base;
|
* 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
|
||||||
now = q->get_time();
|
* inconsistent state and return error.
|
||||||
|
*/
|
||||||
if (ktime_after(base, now))
|
if (WARN_ON(!cycle))
|
||||||
return base;
|
return -EFAULT;
|
||||||
|
|
||||||
/* Schedule the start time for the beginning of the next
|
/* Schedule the start time for the beginning of the next
|
||||||
* cycle.
|
* cycle.
|
||||||
*/
|
*/
|
||||||
n = div64_s64(ktime_sub_ns(now, base), cycle);
|
n = div64_s64(ktime_sub_ns(now, base), cycle);
|
||||||
|
*start = ktime_add_ns(base, (n + 1) * cycle);
|
||||||
return ktime_add_ns(base, (n + 1) * cycle);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void taprio_start_sched(struct Qdisc *sch, ktime_t start)
|
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)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = -EINVAL;
|
|
||||||
if (tb[TCA_TAPRIO_ATTR_PRIOMAP])
|
if (tb[TCA_TAPRIO_ATTR_PRIOMAP])
|
||||||
mqprio = nla_data(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);
|
taprio_set_picos_per_byte(dev, q);
|
||||||
start = taprio_get_start_time(sch);
|
|
||||||
if (!start)
|
err = taprio_get_start_time(sch, &start);
|
||||||
return 0;
|
if (err < 0) {
|
||||||
|
NL_SET_ERR_MSG(extack, "Internal error: failed get start time");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
taprio_start_sched(sch, start);
|
taprio_start_sched(sch, start);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue