diff options
Diffstat (limited to 'net/sched/sch_red.c')
| -rw-r--r-- | net/sched/sch_red.c | 33 |
1 files changed, 17 insertions, 16 deletions
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 7f8ea9e297c3..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) |
| @@ -212,6 +220,8 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 212 | max_P = tb[TCA_RED_MAX_P] ? nla_get_u32(tb[TCA_RED_MAX_P]) : 0; | 220 | max_P = tb[TCA_RED_MAX_P] ? nla_get_u32(tb[TCA_RED_MAX_P]) : 0; |
| 213 | 221 | ||
| 214 | ctl = nla_data(tb[TCA_RED_PARMS]); | 222 | ctl = nla_data(tb[TCA_RED_PARMS]); |
| 223 | if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog)) | ||
| 224 | return -EINVAL; | ||
| 215 | 225 | ||
| 216 | if (ctl->limit > 0) { | 226 | if (ctl->limit > 0) { |
| 217 | child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit); | 227 | child = fifo_create_dflt(sch, &bfifo_qdisc_ops, ctl->limit); |
| @@ -272,7 +282,7 @@ static int red_init(struct Qdisc *sch, struct nlattr *opt) | |||
| 272 | return red_change(sch, opt); | 282 | return red_change(sch, opt); |
| 273 | } | 283 | } |
| 274 | 284 | ||
| 275 | 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) |
| 276 | { | 286 | { |
| 277 | struct net_device *dev = qdisc_dev(sch); | 287 | struct net_device *dev = qdisc_dev(sch); |
| 278 | struct tc_red_qopt_offload hw_stats = { | 288 | struct tc_red_qopt_offload hw_stats = { |
| @@ -284,21 +294,12 @@ static int red_dump_offload(struct Qdisc *sch, struct tc_red_qopt *opt) | |||
| 284 | .stats.qstats = &sch->qstats, | 294 | .stats.qstats = &sch->qstats, |
| 285 | }, | 295 | }, |
| 286 | }; | 296 | }; |
| 287 | int err; | ||
| 288 | 297 | ||
| 289 | opt->flags &= ~TC_RED_OFFLOADED; | 298 | if (!(sch->flags & TCQ_F_OFFLOADED)) |
| 290 | if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc) | ||
| 291 | return 0; | ||
| 292 | |||
| 293 | err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_RED, | ||
| 294 | &hw_stats); | ||
| 295 | if (err == -EOPNOTSUPP) | ||
| 296 | return 0; | 299 | return 0; |
| 297 | 300 | ||
| 298 | if (!err) | 301 | return dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_RED, |
| 299 | opt->flags |= TC_RED_OFFLOADED; | 302 | &hw_stats); |
| 300 | |||
| 301 | return err; | ||
| 302 | } | 303 | } |
| 303 | 304 | ||
| 304 | static int red_dump(struct Qdisc *sch, struct sk_buff *skb) | 305 | static int red_dump(struct Qdisc *sch, struct sk_buff *skb) |
| @@ -317,7 +318,7 @@ static int red_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
| 317 | int err; | 318 | int err; |
| 318 | 319 | ||
| 319 | sch->qstats.backlog = q->qdisc->qstats.backlog; | 320 | sch->qstats.backlog = q->qdisc->qstats.backlog; |
| 320 | err = red_dump_offload(sch, &opt); | 321 | err = red_dump_offload_stats(sch, &opt); |
| 321 | if (err) | 322 | if (err) |
| 322 | goto nla_put_failure; | 323 | goto nla_put_failure; |
| 323 | 324 | ||
| @@ -345,7 +346,7 @@ static int red_dump_stats(struct Qdisc *sch, struct gnet_dump *d) | |||
| 345 | .marked = q->stats.prob_mark + q->stats.forced_mark, | 346 | .marked = q->stats.prob_mark + q->stats.forced_mark, |
| 346 | }; | 347 | }; |
| 347 | 348 | ||
| 348 | if (tc_can_offload(dev) && dev->netdev_ops->ndo_setup_tc) { | 349 | if (sch->flags & TCQ_F_OFFLOADED) { |
| 349 | struct red_stats hw_stats = {0}; | 350 | struct red_stats hw_stats = {0}; |
| 350 | struct tc_red_qopt_offload hw_stats_request = { | 351 | struct tc_red_qopt_offload hw_stats_request = { |
| 351 | .command = TC_RED_XSTATS, | 352 | .command = TC_RED_XSTATS, |
