| @@ -102,6 +102,91 @@ static u32 ets_class_id(struct Qdisc *sch, const struct ets_class *cl) · 101 unmodified lines |
| 102 | return TC_H_MAKE(sch->handle, band + 1); | 102 | return TC_H_MAKE(sch->handle, band + 1); |
| 103 | } | 103 | } |
| 104 | | 104 | |
| | 105 | static void ets_offload_change(struct Qdisc *sch) |
| | 106 | { |
| | 107 | struct net_device *dev = qdisc_dev(sch); |
| | 108 | struct ets_sched *q = qdisc_priv(sch); |
| | 109 | struct tc_ets_qopt_offload qopt; |
| | 110 | unsigned int w_psum_prev = 0; |
| | 111 | unsigned int q_psum = 0; |
| | 112 | unsigned int q_sum = 0; |
| | 113 | unsigned int quantum; |
| | 114 | unsigned int w_psum; |
| | 115 | unsigned int weight; |
| | 116 | unsigned int i; |
| | 117 | |
| | 118 | if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc) |
| | 119 | return; |
| | 120 | |
| | 121 | qopt.command = TC_ETS_REPLACE; |
| | 122 | qopt.handle = sch->handle; |
| | 123 | qopt.parent = sch->parent; |
| | 124 | qopt.replace_params.bands = q->nbands; |
| | 125 | qopt.replace_params.qstats = &sch->qstats; |
| | 126 | memcpy(&qopt.replace_params.priomap, |
| | 127 | q->prio2band, sizeof(q->prio2band)); |
| | 128 | |
| | 129 | for (i = 0; i < q->nbands; i++) |
| | 130 | q_sum += q->classes[i].quantum; |
| | 131 | |
| | 132 | for (i = 0; i < q->nbands; i++) { |
| | 133 | quantum = q->classes[i].quantum; |
| | 134 | q_psum += quantum; |
| | 135 | w_psum = quantum ? q_psum * 100 / q_sum : 0; |
| | 136 | weight = w_psum - w_psum_prev; |
| | 137 | w_psum_prev = w_psum; |
| | 138 | |
| | 139 | qopt.replace_params.quanta[i] = quantum; |
| | 140 | qopt.replace_params.weights[i] = weight; |
| | 141 | } |
| | 142 | |
| | 143 | dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_ETS, &qopt); |
| | 144 | } |
| | 145 | |
| | 146 | static void ets_offload_destroy(struct Qdisc *sch) |
| | 147 | { |
| | 148 | struct net_device *dev = qdisc_dev(sch); |
| | 149 | struct tc_ets_qopt_offload qopt; |
| | 150 | |
| | 151 | if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc) |
| | 152 | return; |
| | 153 | |
| | 154 | qopt.command = TC_ETS_DESTROY; |
| | 155 | qopt.handle = sch->handle; |
| | 156 | qopt.parent = sch->parent; |
| | 157 | dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_ETS, &qopt); |
| | 158 | } |
| | 159 | |
| | 160 | static void ets_offload_graft(struct Qdisc *sch, struct Qdisc *new, |
| | 161 | struct Qdisc *old, unsigned long arg, |
| | 162 | struct netlink_ext_ack *extack) |
| | 163 | { |
| | 164 | struct net_device *dev = qdisc_dev(sch); |
| | 165 | struct tc_ets_qopt_offload qopt; |
| | 166 | |
| | 167 | qopt.command = TC_ETS_GRAFT; |
| | 168 | qopt.handle = sch->handle; |
| | 169 | qopt.parent = sch->parent; |
| | 170 | qopt.graft_params.band = arg - 1; |
| | 171 | qopt.graft_params.child_handle = new->handle; |
| | 172 | |
| | 173 | qdisc_offload_graft_helper(dev, sch, new, old, TC_SETUP_QDISC_ETS, |
| | 174 | &qopt, extack); |
| | 175 | } |
| | 176 | |
| | 177 | static int ets_offload_dump(struct Qdisc *sch) |
| | 178 | { |
| | 179 | struct tc_ets_qopt_offload qopt; |
| | 180 | |
| | 181 | qopt.command = TC_ETS_STATS; |
| | 182 | qopt.handle = sch->handle; |
| | 183 | qopt.parent = sch->parent; |
| | 184 | qopt.stats.bstats = &sch->bstats; |
| | 185 | qopt.stats.qstats = &sch->qstats; |
| | 186 | |
| | 187 | return qdisc_offload_dump_helper(sch, TC_SETUP_QDISC_ETS, &qopt); |
| | 188 | } |
| | 189 | |
| 105 | static bool ets_class_is_strict(struct ets_sched *q, const struct ets_class *cl) | 190 | static bool ets_class_is_strict(struct ets_sched *q, const struct ets_class *cl) |
| 106 | { | 191 | { |
| 107 | unsigned int band = cl - q->classes; | 192 | unsigned int band = cl - q->classes; |
| @@ -154,6 +239,8 @@ static int ets_class_change(struct Qdisc *sch, u32 classid, u32 parentid, · 46 unmodified lines |
| 154 | sch_tree_lock(sch); | 239 | sch_tree_lock(sch); |
| 155 | cl->quantum = quantum; | 240 | cl->quantum = quantum; |
| 156 | sch_tree_unlock(sch); | 241 | sch_tree_unlock(sch); |
| | 242 | |
| | 243 | ets_offload_change(sch); |
| 157 | return 0; | 244 | return 0; |
| 158 | } | 245 | } |
| 159 | | 246 | |
| @@ -173,6 +260,7 @@ static int ets_class_graft(struct Qdisc *sch, unsigned long arg, · 13 unmodified lines |
| 173 | } | 260 | } |
| 174 | | 261 | |
| 175 | *old = qdisc_replace(sch, new, &cl->qdisc); | 262 | *old = qdisc_replace(sch, new, &cl->qdisc); |
| | 263 | ets_offload_graft(sch, new, *old, arg, extack); |
| 176 | return 0; | 264 | return 0; |
| 177 | } | 265 | } |
| 178 | | 266 | |
| @@ -589,6 +677,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, · 410 unmodified lines |
| 589 | | 677 | |
| 590 | sch_tree_unlock(sch); | 678 | sch_tree_unlock(sch); |
| 591 | | 679 | |
| | 680 | ets_offload_change(sch); |
| 592 | for (i = q->nbands; i < oldbands; i++) { | 681 | for (i = q->nbands; i < oldbands; i++) { |
| 593 | qdisc_put(q->classes[i].qdisc); | 682 | qdisc_put(q->classes[i].qdisc); |
| 594 | memset(&q->classes[i], 0, sizeof(q->classes[i])); | 683 | memset(&q->classes[i], 0, sizeof(q->classes[i])); |
| @@ -633,6 +722,7 @@ static void ets_qdisc_destroy(struct Qdisc *sch) · 38 unmodified lines |
| 633 | struct ets_sched *q = qdisc_priv(sch); | 722 | struct ets_sched *q = qdisc_priv(sch); |
| 634 | int band; | 723 | int band; |
| 635 | | 724 | |
| | 725 | ets_offload_destroy(sch); |
| 636 | tcf_block_put(q->block); | 726 | tcf_block_put(q->block); |
| 637 | for (band = 0; band < q->nbands; band++) | 727 | for (band = 0; band < q->nbands; band++) |
| 638 | qdisc_put(q->classes[band].qdisc); | 728 | qdisc_put(q->classes[band].qdisc); |
| @@ -645,6 +735,11 @@ static int ets_qdisc_dump(struct Qdisc *sch, struct sk_buff *skb) · 6 unmodified lines |
| 645 | struct nlattr *nest; | 735 | struct nlattr *nest; |
| 646 | int band; | 736 | int band; |
| 647 | int prio; | 737 | int prio; |
| | 738 | int err; |
| | 739 | |
| | 740 | err = ets_offload_dump(sch); |
| | 741 | if (err) |
| | 742 | return err; |
| 648 | | 743 | |
| 649 | opts = nla_nest_start_noflag(skb, TCA_OPTIONS); | 744 | opts = nla_nest_start_noflag(skb, TCA_OPTIONS); |
| 650 | if (!opts) | 745 | if (!opts) |