| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * net/sched/sch_prio.c Simple 3-band priority "scheduler". |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or |
|---|
| 5 | | - * modify it under the terms of the GNU General Public License |
|---|
| 6 | | - * as published by the Free Software Foundation; either version |
|---|
| 7 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 8 | 4 | * |
|---|
| 9 | 5 | * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> |
|---|
| 10 | 6 | * Fixes: 19990609: J Hadi Salim <hadi@nortelnetworks.com>: |
|---|
| .. | .. |
|---|
| 50 | 46 | case TC_ACT_QUEUED: |
|---|
| 51 | 47 | case TC_ACT_TRAP: |
|---|
| 52 | 48 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; |
|---|
| 53 | | - /* fall through */ |
|---|
| 49 | + fallthrough; |
|---|
| 54 | 50 | case TC_ACT_SHOT: |
|---|
| 55 | 51 | return NULL; |
|---|
| 56 | 52 | } |
|---|
| .. | .. |
|---|
| 72 | 68 | static int |
|---|
| 73 | 69 | prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free) |
|---|
| 74 | 70 | { |
|---|
| 71 | + unsigned int len = qdisc_pkt_len(skb); |
|---|
| 75 | 72 | struct Qdisc *qdisc; |
|---|
| 76 | 73 | int ret; |
|---|
| 77 | 74 | |
|---|
| .. | .. |
|---|
| 88 | 85 | |
|---|
| 89 | 86 | ret = qdisc_enqueue(skb, qdisc, to_free); |
|---|
| 90 | 87 | if (ret == NET_XMIT_SUCCESS) { |
|---|
| 91 | | - qdisc_qstats_backlog_inc(sch, skb); |
|---|
| 88 | + sch->qstats.backlog += len; |
|---|
| 92 | 89 | sch->q.qlen++; |
|---|
| 93 | 90 | return NET_XMIT_SUCCESS; |
|---|
| 94 | 91 | } |
|---|
| .. | .. |
|---|
| 138 | 135 | |
|---|
| 139 | 136 | for (prio = 0; prio < q->bands; prio++) |
|---|
| 140 | 137 | qdisc_reset(q->queues[prio]); |
|---|
| 141 | | - sch->qstats.backlog = 0; |
|---|
| 142 | | - sch->q.qlen = 0; |
|---|
| 143 | 138 | } |
|---|
| 144 | 139 | |
|---|
| 145 | 140 | static int prio_offload(struct Qdisc *sch, struct tc_prio_qopt *qopt) |
|---|
| .. | .. |
|---|
| 215 | 210 | q->bands = qopt->bands; |
|---|
| 216 | 211 | memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1); |
|---|
| 217 | 212 | |
|---|
| 218 | | - for (i = q->bands; i < oldbands; i++) { |
|---|
| 219 | | - struct Qdisc *child = q->queues[i]; |
|---|
| 220 | | - |
|---|
| 221 | | - qdisc_tree_reduce_backlog(child, child->q.qlen, |
|---|
| 222 | | - child->qstats.backlog); |
|---|
| 223 | | - qdisc_put(child); |
|---|
| 224 | | - } |
|---|
| 213 | + for (i = q->bands; i < oldbands; i++) |
|---|
| 214 | + qdisc_tree_flush_backlog(q->queues[i]); |
|---|
| 225 | 215 | |
|---|
| 226 | 216 | for (i = oldbands; i < q->bands; i++) { |
|---|
| 227 | 217 | q->queues[i] = queues[i]; |
|---|
| .. | .. |
|---|
| 230 | 220 | } |
|---|
| 231 | 221 | |
|---|
| 232 | 222 | sch_tree_unlock(sch); |
|---|
| 223 | + |
|---|
| 224 | + for (i = q->bands; i < oldbands; i++) |
|---|
| 225 | + qdisc_put(q->queues[i]); |
|---|
| 233 | 226 | return 0; |
|---|
| 234 | 227 | } |
|---|
| 235 | 228 | |
|---|
| .. | .. |
|---|
| 251 | 244 | |
|---|
| 252 | 245 | static int prio_dump_offload(struct Qdisc *sch) |
|---|
| 253 | 246 | { |
|---|
| 254 | | - struct net_device *dev = qdisc_dev(sch); |
|---|
| 255 | 247 | struct tc_prio_qopt_offload hw_stats = { |
|---|
| 256 | 248 | .command = TC_PRIO_STATS, |
|---|
| 257 | 249 | .handle = sch->handle, |
|---|
| .. | .. |
|---|
| 263 | 255 | }, |
|---|
| 264 | 256 | }, |
|---|
| 265 | 257 | }; |
|---|
| 266 | | - int err; |
|---|
| 267 | 258 | |
|---|
| 268 | | - sch->flags &= ~TCQ_F_OFFLOADED; |
|---|
| 269 | | - if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc) |
|---|
| 270 | | - return 0; |
|---|
| 271 | | - |
|---|
| 272 | | - err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_PRIO, |
|---|
| 273 | | - &hw_stats); |
|---|
| 274 | | - if (err == -EOPNOTSUPP) |
|---|
| 275 | | - return 0; |
|---|
| 276 | | - |
|---|
| 277 | | - if (!err) |
|---|
| 278 | | - sch->flags |= TCQ_F_OFFLOADED; |
|---|
| 279 | | - |
|---|
| 280 | | - return err; |
|---|
| 259 | + return qdisc_offload_dump_helper(sch, TC_SETUP_QDISC_PRIO, &hw_stats); |
|---|
| 281 | 260 | } |
|---|
| 282 | 261 | |
|---|
| 283 | 262 | static int prio_dump(struct Qdisc *sch, struct sk_buff *skb) |
|---|
| .. | .. |
|---|
| 309 | 288 | { |
|---|
| 310 | 289 | struct prio_sched_data *q = qdisc_priv(sch); |
|---|
| 311 | 290 | struct tc_prio_qopt_offload graft_offload; |
|---|
| 312 | | - struct net_device *dev = qdisc_dev(sch); |
|---|
| 313 | 291 | unsigned long band = arg - 1; |
|---|
| 314 | | - bool any_qdisc_is_offloaded; |
|---|
| 315 | | - int err; |
|---|
| 316 | 292 | |
|---|
| 317 | 293 | if (!new) { |
|---|
| 318 | 294 | new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops, |
|---|
| .. | .. |
|---|
| 325 | 301 | |
|---|
| 326 | 302 | *old = qdisc_replace(sch, new, &q->queues[band]); |
|---|
| 327 | 303 | |
|---|
| 328 | | - if (!tc_can_offload(dev)) |
|---|
| 329 | | - return 0; |
|---|
| 330 | | - |
|---|
| 331 | 304 | graft_offload.handle = sch->handle; |
|---|
| 332 | 305 | graft_offload.parent = sch->parent; |
|---|
| 333 | 306 | graft_offload.graft_params.band = band; |
|---|
| 334 | 307 | graft_offload.graft_params.child_handle = new->handle; |
|---|
| 335 | 308 | graft_offload.command = TC_PRIO_GRAFT; |
|---|
| 336 | 309 | |
|---|
| 337 | | - err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_PRIO, |
|---|
| 338 | | - &graft_offload); |
|---|
| 339 | | - |
|---|
| 340 | | - /* Don't report error if the graft is part of destroy operation. */ |
|---|
| 341 | | - if (err && new != &noop_qdisc) { |
|---|
| 342 | | - /* Don't report error if the parent, the old child and the new |
|---|
| 343 | | - * one are not offloaded. |
|---|
| 344 | | - */ |
|---|
| 345 | | - any_qdisc_is_offloaded = sch->flags & TCQ_F_OFFLOADED; |
|---|
| 346 | | - any_qdisc_is_offloaded |= new->flags & TCQ_F_OFFLOADED; |
|---|
| 347 | | - if (*old) |
|---|
| 348 | | - any_qdisc_is_offloaded |= (*old)->flags & |
|---|
| 349 | | - TCQ_F_OFFLOADED; |
|---|
| 350 | | - |
|---|
| 351 | | - if (any_qdisc_is_offloaded) |
|---|
| 352 | | - NL_SET_ERR_MSG(extack, "Offloading graft operation failed."); |
|---|
| 353 | | - } |
|---|
| 354 | | - |
|---|
| 310 | + qdisc_offload_graft_helper(qdisc_dev(sch), sch, new, *old, |
|---|
| 311 | + TC_SETUP_QDISC_PRIO, &graft_offload, |
|---|
| 312 | + extack); |
|---|
| 355 | 313 | return 0; |
|---|
| 356 | 314 | } |
|---|
| 357 | 315 | |
|---|
| .. | .. |
|---|
| 403 | 361 | cl_q = q->queues[cl - 1]; |
|---|
| 404 | 362 | if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch), |
|---|
| 405 | 363 | d, cl_q->cpu_bstats, &cl_q->bstats) < 0 || |
|---|
| 406 | | - gnet_stats_copy_queue(d, NULL, &cl_q->qstats, cl_q->q.qlen) < 0) |
|---|
| 364 | + qdisc_qstats_copy(d, cl_q) < 0) |
|---|
| 407 | 365 | return -1; |
|---|
| 408 | 366 | |
|---|
| 409 | 367 | return 0; |
|---|