--- zzzz-none-000/linux-4.9.276/net/sched/sch_drr.c 2021-07-20 14:21:16.000000000 +0000 +++ falcon-5530-750/linux-4.9.276/net/sched/sch_drr.c 2023-04-05 08:19:02.000000000 +0000 @@ -39,6 +39,43 @@ struct Qdisc_class_hash clhash; }; +static int drr_offload(struct Qdisc *sch, enum tc_drr_command cmd) +{ + struct net_device *dev = qdisc_dev(sch); + struct tc_drr_qopt_offload opt = { + .command = cmd, + .parent = sch->parent, + .handle = sch->handle, + }; + struct tc_to_netdev tc = { .type = TC_SETUP_DRR, + { .sch_drr = &opt } }; + + if (!(dev->features & NETIF_F_HW_TC) || !dev->netdev_ops->ndo_setup_tc) + return -EOPNOTSUPP; + + return dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc); +} + +static int drr_cl_offload(struct Qdisc *sch, struct drr_class *cl, + enum tc_drr_command cmd) +{ + struct net_device *dev = qdisc_dev(sch); + struct tc_drr_qopt_offload opt = { + .command = cmd, + .parent = sch->handle, + .handle = cl->common.classid, + }; + struct tc_to_netdev tc = { .type = TC_SETUP_DRR, + { .sch_drr = &opt } }; + + if (!(dev->features & NETIF_F_HW_TC) || !dev->netdev_ops->ndo_setup_tc) + return -EOPNOTSUPP; + + opt.set_params.quantum = cl->quantum; + + return dev->netdev_ops->ndo_setup_tc(dev, cl->common.classid, 0, &tc); +} + static struct drr_class *drr_find_class(struct Qdisc *sch, u32 classid) { struct drr_sched *q = qdisc_priv(sch); @@ -136,6 +173,8 @@ qdisc_class_hash_grow(sch, &q->clhash); + drr_cl_offload(sch, cl, TC_DRR_REPLACE); + *arg = (unsigned long)cl; return 0; } @@ -144,6 +183,7 @@ { gen_kill_estimator(&cl->bstats, &cl->rate_est); qdisc_destroy(cl->qdisc); + drr_cl_offload(sch, cl, TC_DRR_DESTROY); kfree(cl); } @@ -244,8 +284,7 @@ { struct drr_class *cl = (struct drr_class *)arg; - if (cl->qdisc->q.qlen == 0) - list_del(&cl->alist); + list_del(&cl->alist); } static int drr_dump_class(struct Qdisc *sch, unsigned long arg, @@ -337,6 +376,7 @@ switch (result) { case TC_ACT_QUEUED: case TC_ACT_STOLEN: + case TC_ACT_TRAP: *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; case TC_ACT_SHOT: return NULL; @@ -433,6 +473,9 @@ if (err < 0) return err; INIT_LIST_HEAD(&q->active); + + drr_offload(sch, TC_DRR_REPLACE); + return 0; } @@ -468,6 +511,8 @@ drr_destroy_class(sch, cl); } qdisc_class_hash_destroy(&q->clhash); + + drr_offload(sch, TC_DRR_DESTROY); } static const struct Qdisc_class_ops drr_class_ops = {