static int prio_offload(struct Qdisc *sch, struct tc_prio_qopt *qopt) { struct net_device *dev = qdisc_dev(sch); struct tc_prio_qopt_offload opt = { .handle = sch->handle, .parent = sch->parent, }; if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc) return -EOPNOTSUPP; if (qopt) { opt.command = TC_PRIO_REPLACE; opt.replace_params.bands = qopt->bands; memcpy(&opt.replace_params.priomap, qopt->priomap, TC_PRIO_MAX + 1); opt.replace_params.qstats = &sch->qstats; } else { opt.command = TC_PRIO_DESTROY; } return dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_PRIO, &opt); } static void prio_destroy(struct Qdisc *sch) { int prio; struct prio_sched_data *q = qdisc_priv(sch); tcf_block_put(q->block); prio_offload(sch, NULL); for (prio = 0; prio < q->bands; prio++) qdisc_put(q->queues[prio]); }
static void gred_offload(struct Qdisc *sch, enum tc_gred_command command) { struct gred_sched *table = qdisc_priv(sch); struct net_device *dev = qdisc_dev(sch); struct tc_gred_qopt_offload opt = { .command = command, .handle = sch->handle, .parent = sch->parent, }; if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc) return; if (command == TC_GRED_REPLACE) { unsigned int i; opt.set.grio_on = gred_rio_mode(table); opt.set.wred_on = gred_wred_mode(table); opt.set.dp_cnt = table->DPs; opt.set.dp_def = table->def; for (i = 0; i < table->DPs; i++) { struct gred_sched_data *q = table->tab[i]; if (!q) continue; opt.set.tab[i].present = true; opt.set.tab[i].limit = q->limit; opt.set.tab[i].prio = q->prio; opt.set.tab[i].min = q->parms.qth_min >> q->parms.Wlog; opt.set.tab[i].max = q->parms.qth_max >> q->parms.Wlog; opt.set.tab[i].is_ecn = gred_use_ecn(q); opt.set.tab[i].is_harddrop = gred_use_harddrop(q); opt.set.tab[i].probability = q->parms.max_P; opt.set.tab[i].backlog = &q->backlog; } opt.set.qstats = &sch->qstats; } dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_GRED, &opt); }