diff options
Diffstat (limited to 'net/sched/sch_red.c')
-rw-r--r-- | net/sched/sch_red.c | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 9d874e60e032..f0747eb87dc4 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c | |||
@@ -157,6 +157,7 @@ static int red_offload(struct Qdisc *sch, bool enable) | |||
157 | .handle = sch->handle, | 157 | .handle = sch->handle, |
158 | .parent = sch->parent, | 158 | .parent = sch->parent, |
159 | }; | 159 | }; |
160 | int err; | ||
160 | 161 | ||
161 | if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc) | 162 | if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc) |
162 | return -EOPNOTSUPP; | 163 | return -EOPNOTSUPP; |
@@ -171,7 +172,14 @@ static int red_offload(struct Qdisc *sch, bool enable) | |||
171 | opt.command = TC_RED_DESTROY; | 172 | opt.command = TC_RED_DESTROY; |
172 | } | 173 | } |
173 | 174 | ||
174 | return dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_RED, &opt); | 175 | err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_RED, &opt); |
176 | |||
177 | if (!err && enable) | ||
178 | sch->flags |= TCQ_F_OFFLOADED; | ||
179 | else | ||
180 | sch->flags &= ~TCQ_F_OFFLOADED; | ||
181 | |||
182 | return err; | ||
175 | } | 183 | } |
176 | 184 | ||
177 | static void red_destroy(struct Qdisc *sch) | 185 | static void red_destroy(struct Qdisc *sch) |
@@ -274,7 +282,7 @@ static int red_init(struct Qdisc *sch, struct nlattr *opt) | |||
274 | return red_change(sch, opt); | 282 | return red_change(sch, opt); |
275 | } | 283 | } |
276 | 284 | ||
277 | static int red_dump_offload(struct Qdisc *sch, struct tc_red_qopt *opt) | 285 | static int red_dump_offload_stats(struct Qdisc *sch, struct tc_red_qopt *opt) |
278 | { | 286 | { |
279 | struct net_device *dev = qdisc_dev(sch); | 287 | struct net_device *dev = qdisc_dev(sch); |
280 | struct tc_red_qopt_offload hw_stats = { | 288 | struct tc_red_qopt_offload hw_stats = { |
@@ -286,21 +294,12 @@ static int red_dump_offload(struct Qdisc *sch, struct tc_red_qopt *opt) | |||
286 | .stats.qstats = &sch->qstats, | 294 | .stats.qstats = &sch->qstats, |
287 | }, | 295 | }, |
288 | }; | 296 | }; |
289 | int err; | ||
290 | 297 | ||
291 | opt->flags &= ~TC_RED_OFFLOADED; | 298 | if (!(sch->flags & TCQ_F_OFFLOADED)) |
292 | if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc) | ||
293 | return 0; | ||
294 | |||
295 | err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_RED, | ||
296 | &hw_stats); | ||
297 | if (err == -EOPNOTSUPP) | ||
298 | return 0; | 299 | return 0; |
299 | 300 | ||
300 | if (!err) | 301 | return dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_RED, |
301 | opt->flags |= TC_RED_OFFLOADED; | 302 | &hw_stats); |
302 | |||
303 | return err; | ||
304 | } | 303 | } |
305 | 304 | ||
306 | static int red_dump(struct Qdisc *sch, struct sk_buff *skb) | 305 | static int red_dump(struct Qdisc *sch, struct sk_buff *skb) |
@@ -319,7 +318,7 @@ static int red_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
319 | int err; | 318 | int err; |
320 | 319 | ||
321 | sch->qstats.backlog = q->qdisc->qstats.backlog; | 320 | sch->qstats.backlog = q->qdisc->qstats.backlog; |
322 | err = red_dump_offload(sch, &opt); | 321 | err = red_dump_offload_stats(sch, &opt); |
323 | if (err) | 322 | if (err) |
324 | goto nla_put_failure; | 323 | goto nla_put_failure; |
325 | 324 | ||
@@ -347,7 +346,7 @@ static int red_dump_stats(struct Qdisc *sch, struct gnet_dump *d) | |||
347 | .marked = q->stats.prob_mark + q->stats.forced_mark, | 346 | .marked = q->stats.prob_mark + q->stats.forced_mark, |
348 | }; | 347 | }; |
349 | 348 | ||
350 | if (tc_can_offload(dev) && dev->netdev_ops->ndo_setup_tc) { | 349 | if (sch->flags & TCQ_F_OFFLOADED) { |
351 | struct red_stats hw_stats = {0}; | 350 | struct red_stats hw_stats = {0}; |
352 | struct tc_red_qopt_offload hw_stats_request = { | 351 | struct tc_red_qopt_offload hw_stats_request = { |
353 | .command = TC_RED_XSTATS, | 352 | .command = TC_RED_XSTATS, |